Merge "Improve AlignmentLine docs and hide .merge" into androidx-master-dev
diff --git a/activity/activity/src/androidTest/java/androidx/activity/result/ActivityResultRegistryTest.kt b/activity/activity/src/androidTest/java/androidx/activity/result/ActivityResultRegistryTest.kt
index ab286fe..14e1cc2 100644
--- a/activity/activity/src/androidTest/java/androidx/activity/result/ActivityResultRegistryTest.kt
+++ b/activity/activity/src/androidTest/java/androidx/activity/result/ActivityResultRegistryTest.kt
@@ -146,9 +146,6 @@
// restore the state of the registry
registry.onRestoreInstanceState(state)
- // launch the result
- activityResult.launch(null)
-
var resultReturned = false
// re-register for the result that should have been saved
registry.register(
@@ -158,6 +155,9 @@
}
)
+ // launch the result
+ activityResult.launch(null)
+
// move to CREATED and make sure the callback is not fired
lifecycleOwner.currentState = Lifecycle.State.CREATED
assertThat(resultReturned).isFalse()
diff --git a/activity/activity/src/main/java/androidx/activity/result/ActivityResultRegistry.java b/activity/activity/src/main/java/androidx/activity/result/ActivityResultRegistry.java
index 12539d7..4b754a7 100644
--- a/activity/activity/src/main/java/androidx/activity/result/ActivityResultRegistry.java
+++ b/activity/activity/src/main/java/androidx/activity/result/ActivityResultRegistry.java
@@ -68,9 +68,11 @@
private final Map<String, Integer> mKeyToRc = new HashMap<>();
private final Map<String, LifecycleContainer> mKeyToLifecycleContainers = new HashMap<>();
- private final transient Map<String, CallbackAndContract<?>> mKeyToCallback = new HashMap<>();
+ @SuppressWarnings("WeakerAccess") /* synthetic access */
+ final transient Map<String, CallbackAndContract<?>> mKeyToCallback = new HashMap<>();
- private final Bundle/*<String, ActivityResult>*/ mPendingResults = new Bundle();
+ @SuppressWarnings("WeakerAccess") /* synthetic access */
+ final Bundle/*<String, ActivityResult>*/ mPendingResults = new Bundle();
/**
* Start the process of executing an {@link ActivityResultContract} in a type-safe way,
@@ -118,41 +120,32 @@
}
final int requestCode = registerKey(key);
- mKeyToCallback.put(key, new CallbackAndContract<>(callback, contract));
-
- final ActivityResult pendingResult = mPendingResults.getParcelable(key);
LifecycleContainer lifecycleContainer = mKeyToLifecycleContainers.get(key);
if (lifecycleContainer == null) {
lifecycleContainer = new LifecycleContainer(lifecycle);
}
- if (pendingResult != null) {
- mPendingResults.remove(key);
- LifecycleEventObserver observer = new LifecycleEventObserver() {
- @Override
- public void onStateChanged(
- @NonNull LifecycleOwner lifecycleOwner,
- @NonNull Lifecycle.Event event) {
- if (Lifecycle.Event.ON_START.equals(event)) {
+ LifecycleEventObserver observer = new LifecycleEventObserver() {
+ @Override
+ public void onStateChanged(
+ @NonNull LifecycleOwner lifecycleOwner,
+ @NonNull Lifecycle.Event event) {
+ if (Lifecycle.Event.ON_START.equals(event)) {
+ mKeyToCallback.put(key, new CallbackAndContract<>(callback, contract));
+ final ActivityResult pendingResult = mPendingResults.getParcelable(key);
+ if (pendingResult != null) {
callback.onActivityResult(contract.parseResult(
pendingResult.getResultCode(),
pendingResult.getData()));
}
- }
- };
- lifecycleContainer.addObserver(observer);
- mKeyToLifecycleContainers.put(key, lifecycleContainer);
- }
-
- LifecycleEventObserver observer = new LifecycleEventObserver() {
- @Override
- public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner,
- @NonNull Lifecycle.Event event) {
- if (Lifecycle.Event.ON_DESTROY.equals(event)) {
+ } else if (Lifecycle.Event.ON_STOP.equals(event)) {
+ mKeyToCallback.remove(key);
+ } else if (Lifecycle.Event.ON_DESTROY.equals(event)) {
unregister(key);
}
}
};
lifecycleContainer.addObserver(observer);
+ mKeyToLifecycleContainers.put(key, lifecycleContainer);
return new ActivityResultLauncher<I>() {
@Override
diff --git a/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/MainActivity.kt b/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/MainActivity.kt
index f78b14f..c182859 100644
--- a/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/MainActivity.kt
+++ b/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/MainActivity.kt
@@ -48,7 +48,8 @@
class MainActivity : ComponentActivity() {
val requestLocation = registerForActivityResult(
- RequestPermission(), ACCESS_FINE_LOCATION) { isGranted ->
+ RequestPermission(), ACCESS_FINE_LOCATION
+ ) { isGranted ->
toast("Location granted: $isGranted")
}
@@ -72,8 +73,10 @@
toast("Got documents: $docs")
}
- val intentSender = registerForActivityResult(ActivityResultContracts
- .StartIntentSenderForResult()) {
+ val intentSender = registerForActivityResult(
+ ActivityResultContracts
+ .StartIntentSenderForResult()
+ ) {
toast("Received intent sender callback")
}
@@ -102,8 +105,12 @@
openDocuments.launch(arrayOf("*/*"))
}
button("Start IntentSender") {
- val request = IntentSenderRequest.Builder(PendingIntent.getActivity(context,
- 0, Intent(MediaStore.ACTION_IMAGE_CAPTURE), 0).intentSender)
+ val request = IntentSenderRequest.Builder(
+ PendingIntent.getActivity(
+ context,
+ 0, Intent(MediaStore.ACTION_IMAGE_CAPTURE), 0
+ ).intentSender
+ )
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK, 1)
.build()
intentSender.launch(request)
diff --git a/annotation/annotation-experimental-lint/src/main/java/androidx/annotation/experimental/lint/ExperimentalDetector.kt b/annotation/annotation-experimental-lint/src/main/java/androidx/annotation/experimental/lint/ExperimentalDetector.kt
index fecec3a..e038722 100644
--- a/annotation/annotation-experimental-lint/src/main/java/androidx/annotation/experimental/lint/ExperimentalDetector.kt
+++ b/annotation/annotation-experimental-lint/src/main/java/androidx/annotation/experimental/lint/ExperimentalDetector.kt
@@ -68,7 +68,8 @@
// Only allow Java annotations, since the Kotlin compiler doesn't understand our
// annotations and could get confused when it's trying to opt-in to some random
// annotation that it doesn't understand.
- checkExperimentalUsage(context, annotation, usage,
+ checkExperimentalUsage(
+ context, annotation, usage,
listOf(
JAVA_USE_EXPERIMENTAL_ANNOTATION,
JAVA_OPT_IN_ANNOTATION
@@ -81,7 +82,8 @@
// we can enforce both and it's possible that a Kotlin-sourced experimental library
// is being used from Java without the Kotlin stdlib in the classpath.
if (!isKotlin(usage.sourcePsi)) {
- checkExperimentalUsage(context, annotation, usage,
+ checkExperimentalUsage(
+ context, annotation, usage,
listOf(
KOTLIN_USE_EXPERIMENTAL_ANNOTATION,
KOTLIN_OPT_IN_ANNOTATION,
@@ -113,10 +115,14 @@
if (!hasOrUsesAnnotation(context, usage, useAnnotation, useAnnotationNames)) {
val level = extractAttribute(annotation, "level")
if (level != null) {
- report(context, usage, """
+ report(
+ context, usage,
+ """
This declaration is opt-in and its usage should be marked with
'@$useAnnotation' or '@OptIn(markerClass = $useAnnotation.class)'
- """, level)
+ """,
+ level
+ )
} else {
report(
context, annotation,
diff --git a/annotation/annotation-experimental-lint/src/test/kotlin/androidx/annotation/experimental/lint/RequiresOptInDetectorTest.kt b/annotation/annotation-experimental-lint/src/test/kotlin/androidx/annotation/experimental/lint/RequiresOptInDetectorTest.kt
index 1e2478e..a6271ae 100644
--- a/annotation/annotation-experimental-lint/src/test/kotlin/androidx/annotation/experimental/lint/RequiresOptInDetectorTest.kt
+++ b/annotation/annotation-experimental-lint/src/test/kotlin/androidx/annotation/experimental/lint/RequiresOptInDetectorTest.kt
@@ -70,7 +70,7 @@
return dateProvider.getDate() + locationProvider.getLocation();
~~~~~~~~~~~
4 errors, 0 warnings
- """.trimIndent()
+ """.trimIndent()
/* ktlint-enable max-line-length */
check(*input).expect(expected)
@@ -189,7 +189,7 @@
callPackageExperimental();
~~~~~~~~~~~~~~~~~~~~~~~
3 errors, 0 warnings
- """.trimIndent()
+ """.trimIndent()
/* ktlint-enable max-line-length */
check(*input).expect(expected)
@@ -219,7 +219,7 @@
callPackageExperimental()
~~~~~~~~~~~~~~~~~~~~~~~
3 errors, 0 warnings
- """.trimIndent()
+ """.trimIndent()
/* ktlint-enable max-line-length */
check(*input).expect(expected)
@@ -247,7 +247,8 @@
* This is a workaround for IntelliJ failing to recognize source files if they are also
* included as resources.
*/
- val ANDROIDX_REQUIRES_OPT_IN_KT: TestFile = kotlin("""
+ val ANDROIDX_REQUIRES_OPT_IN_KT: TestFile = kotlin(
+ """
package androidx.annotation;
import kotlin.annotation.Retention
@@ -263,7 +264,8 @@
ERROR
}
}
- """.trimIndent())
+ """.trimIndent()
+ )
/**
* [TestFile] containing OptIn.kt from the experimental annotation library.
@@ -271,7 +273,8 @@
* This is a workaround for IntelliJ failing to recognize source files if they are also
* included as resources.
*/
- val ANDROIDX_OPT_IN_KT: TestFile = kotlin("""
+ val ANDROIDX_OPT_IN_KT: TestFile = kotlin(
+ """
package androidx.annotation;
import kotlin.annotation.Retention
@@ -294,7 +297,8 @@
annotation class OptIn(
vararg val markerClass: KClass<out Annotation>
)
- """.trimIndent())
+ """.trimIndent()
+ )
/**
* [TestFile] containing OptIn.kt from the Kotlin standard library.
@@ -302,7 +306,8 @@
* This is a workaround for the Kotlin standard library used by the Lint test harness not
* including the Experimental annotation by default.
*/
- val OPT_IN_KT: TestFile = kotlin("""
+ val OPT_IN_KT: TestFile = kotlin(
+ """
package kotlin
import kotlin.annotation.AnnotationRetention.BINARY
@@ -335,7 +340,8 @@
public annotation class OptIn(
vararg val markerClass: KClass<out Annotation>
)
- """.trimIndent())
+ """.trimIndent()
+ )
/**
* [TestFile] containing the package-level annotation for the sample.optin.foo package.
diff --git a/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AnnotationProcessorTest.java b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AnnotationProcessorTest.java
index d0cb430..44d2c53 100644
--- a/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AnnotationProcessorTest.java
+++ b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AnnotationProcessorTest.java
@@ -18,7 +18,7 @@
import static androidx.appsearch.app.AppSearchTestUtils.checkIsBatchResultSuccess;
import static androidx.appsearch.app.AppSearchTestUtils.checkIsResultSuccess;
-import static androidx.appsearch.app.AppSearchTestUtils.doQuery;
+import static androidx.appsearch.app.AppSearchTestUtils.convertSearchResultsToDocuments;
import static com.google.common.truth.Truth.assertThat;
@@ -211,15 +211,18 @@
// Index the Gift document and query it.
checkIsBatchResultSuccess(mAppSearchManager.putDocuments(
new PutDocumentsRequest.Builder().addDataClass(inputDataClass).build()));
- List<GenericDocument> searchResults = doQuery(mAppSearchManager, "");
- assertThat(searchResults).hasSize(1);
+ SearchResults searchResults = mAppSearchManager.query("", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
// Create DataClassFactory for Gift.
DataClassFactoryRegistry registry = DataClassFactoryRegistry.getInstance();
DataClassFactory<Gift> factory = registry.getOrCreateFactory(Gift.class);
// Convert GenericDocument to Gift and check values.
- Gift outputDataClass = factory.fromGenericDocument(searchResults.get((0)));
+ Gift outputDataClass = factory.fromGenericDocument(documents.get((0)));
assertThat(outputDataClass).isEqualTo(inputDataClass);
}
}
diff --git a/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AppSearchManagerTest.java b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AppSearchManagerTest.java
index 4ae3246..1d6fc80 100644
--- a/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AppSearchManagerTest.java
+++ b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AppSearchManagerTest.java
@@ -18,8 +18,8 @@
import static androidx.appsearch.app.AppSearchTestUtils.checkIsBatchResultSuccess;
import static androidx.appsearch.app.AppSearchTestUtils.checkIsResultSuccess;
+import static androidx.appsearch.app.AppSearchTestUtils.convertSearchResultsToDocuments;
import static androidx.appsearch.app.AppSearchTestUtils.doGet;
-import static androidx.appsearch.app.AppSearchTestUtils.doQuery;
import static com.google.common.truth.Truth.assertThat;
@@ -412,14 +412,20 @@
new PutDocumentsRequest.Builder().addGenericDocument(inEmail).build()));
// Query for the document
- List<GenericDocument> results = doQuery(mDb1, "body");
- assertThat(results).hasSize(1);
- assertThat(results.get(0)).isEqualTo(inEmail);
+ SearchResults searchResults = mDb1.query("body", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
+ assertThat(documents.get(0)).isEqualTo(inEmail);
// Multi-term query
- results = doQuery(mDb1, "body email");
- assertThat(results).hasSize(1);
- assertThat(results.get(0)).isEqualTo(inEmail);
+ searchResults = mDb1.query("body email", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
+ assertThat(documents.get(0)).isEqualTo(inEmail);
}
@Test
@@ -499,17 +505,21 @@
new PutDocumentsRequest.Builder().addGenericDocument(inEmail, inDoc).build()));
// Query for the documents
- List<GenericDocument> results = doQuery(mDb1, "body");
- assertThat(results).hasSize(2);
- assertThat(results).containsExactly(inEmail, inDoc);
+ SearchResults searchResults = mDb1.query("body", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(2);
+ assertThat(documents).containsExactly(inEmail, inDoc);
// Query only for Document
- results = doQuery(mDb1, "body", new SearchSpec.Builder()
+ searchResults = mDb1.query("body", new SearchSpec.Builder()
.setSchemaTypes("Generic")
.setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
.build());
- assertThat(results).hasSize(1);
- assertThat(results).containsExactly(inDoc);
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
+ assertThat(documents).containsExactly(inDoc);
}
@Test
@@ -542,18 +552,22 @@
.addGenericDocument(expectedEmail, unexpectedEmail).build()));
// Query for all namespaces
- List<GenericDocument> results = doQuery(mDb1, "body");
- assertThat(results).hasSize(2);
- assertThat(results).containsExactly(expectedEmail, unexpectedEmail);
+ SearchResults searchResults = mDb1.query("body", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(2);
+ assertThat(documents).containsExactly(expectedEmail, unexpectedEmail);
// Query only for expectedNamespace
- results = doQuery(mDb1, "body",
+ searchResults = mDb1.query("body",
new SearchSpec.Builder()
.setNamespaces("expectedNamespace")
.setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
.build());
- assertThat(results).hasSize(1);
- assertThat(results).containsExactly(expectedEmail);
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
+ assertThat(documents).containsExactly(expectedEmail);
}
@Test
@@ -587,14 +601,20 @@
new PutDocumentsRequest.Builder().addGenericDocument(inEmail2).build()));
// Query for instance 1.
- List<GenericDocument> results = doQuery(mDb1, "body");
- assertThat(results).hasSize(1);
- assertThat(results).containsExactly(inEmail1);
+ SearchResults searchResults = mDb1.query("body", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
+ assertThat(documents).containsExactly(inEmail1);
// Query for instance 2.
- results = doQuery(mDb2, "body");
- assertThat(results).hasSize(1);
- assertThat(results).containsExactly(inEmail2);
+ searchResults = mDb2.query("body", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
+ assertThat(documents).containsExactly(inEmail2);
}
@Test
@@ -698,6 +718,56 @@
}
@Test
+ public void testRemoveByQuery() throws Exception {
+ // Schema registration
+ checkIsResultSuccess(mDb1.setSchema(
+ new SetSchemaRequest.Builder().addSchema(AppSearchEmail.SCHEMA).build()));
+
+ // Index documents
+ AppSearchEmail email1 =
+ new AppSearchEmail.Builder("uri1")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("foo")
+ .setBody("This is the body of the testPut email")
+ .build();
+ AppSearchEmail email2 =
+ new AppSearchEmail.Builder("uri2")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("bar")
+ .setBody("This is the body of the testPut second email")
+ .build();
+ checkIsBatchResultSuccess(mDb1.putDocuments(
+ new PutDocumentsRequest.Builder().addGenericDocument(email1, email2).build()));
+
+ // Check the presence of the documents
+ assertThat(doGet(mDb1, GenericDocument.DEFAULT_NAMESPACE, "uri1")).hasSize(1);
+ assertThat(doGet(mDb1, GenericDocument.DEFAULT_NAMESPACE, "uri2")).hasSize(1);
+
+ // Delete the email 1 by query "foo"
+ checkIsResultSuccess(mDb1.removeByQuery("foo",
+ new SearchSpec.Builder().setTermMatch(SearchSpec.TERM_MATCH_PREFIX).build()));
+ AppSearchBatchResult<String, GenericDocument> getResult = mDb1.getByUri(
+ new GetByUriRequest.Builder().addUris("uri1", "uri2").build())
+ .get();
+ assertThat(getResult.isSuccess()).isFalse();
+ assertThat(getResult.getFailures().get("uri1").getResultCode())
+ .isEqualTo(AppSearchResult.RESULT_NOT_FOUND);
+ assertThat(getResult.getSuccesses().get("uri2")).isEqualTo(email2);
+
+ // Delete the email 2 by query "bar"
+ checkIsResultSuccess(mDb1.removeByQuery("bar",
+ new SearchSpec.Builder().setTermMatch(SearchSpec.TERM_MATCH_PREFIX).build()));
+ getResult = mDb1.getByUri(
+ new GetByUriRequest.Builder().addUris("uri2").build())
+ .get();
+ assertThat(getResult.isSuccess()).isFalse();
+ assertThat(getResult.getFailures().get("uri2").getResultCode())
+ .isEqualTo(AppSearchResult.RESULT_NOT_FOUND);
+ }
+
+ @Test
public void testRemove_TwoInstances() throws Exception {
// Schema registration
checkIsResultSuccess(mDb1.setSchema(new SetSchemaRequest.Builder()
@@ -776,7 +846,11 @@
"uri3")).hasSize(3);
// Delete the email type
- checkIsBatchResultSuccess(mDb1.removeByType(AppSearchEmail.SCHEMA_TYPE));
+ checkIsResultSuccess(mDb1.removeByQuery("",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .setSchemaTypes(AppSearchEmail.SCHEMA_TYPE)
+ .build()));
// Make sure it's really gone
AppSearchBatchResult<String, GenericDocument> getResult = mDb1.getByUri(
@@ -823,7 +897,11 @@
assertThat(doGet(mDb2, GenericDocument.DEFAULT_NAMESPACE, "uri2")).hasSize(1);
// Delete the email type in instance 1
- checkIsBatchResultSuccess(mDb1.removeByType(AppSearchEmail.SCHEMA_TYPE));
+ checkIsResultSuccess(mDb1.removeByQuery("",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .setSchemaTypes(AppSearchEmail.SCHEMA_TYPE)
+ .build()));
// Make sure it's really gone in instance 1
AppSearchBatchResult<String, GenericDocument> getResult = mDb1.getByUri(
@@ -884,7 +962,11 @@
assertThat(doGet(mDb1, /*namespace=*/"document", "uri3")).hasSize(1);
// Delete the email namespace
- checkIsBatchResultSuccess(mDb1.removeByNamespace("email"));
+ checkIsResultSuccess(mDb1.removeByQuery("",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .setNamespaces("email")
+ .build()));
// Make sure it's really gone
AppSearchBatchResult<String, GenericDocument> getResult = mDb1.getByUri(
@@ -937,7 +1019,11 @@
assertThat(doGet(mDb2, /*namespace=*/"email", "uri2")).hasSize(1);
// Delete the email namespace in instance 1
- checkIsBatchResultSuccess(mDb1.removeByNamespace("email"));
+ checkIsResultSuccess(mDb1.removeByQuery("",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .setNamespaces("email")
+ .build()));
// Make sure it's really gone in instance 1
AppSearchBatchResult<String, GenericDocument> getResult = mDb1.getByUri(
@@ -988,7 +1074,10 @@
assertThat(doGet(mDb2, GenericDocument.DEFAULT_NAMESPACE, "uri2")).hasSize(1);
// Delete the all document in instance 1
- checkIsResultSuccess(mDb1.removeAll());
+ checkIsResultSuccess(mDb1.removeByQuery("",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .build()));
// Make sure it's really gone in instance 1
AppSearchBatchResult<String, GenericDocument> getResult = mDb1.getByUri(
@@ -1005,6 +1094,83 @@
}
@Test
+ public void testRemoveAll_TermMatchType() throws Exception {
+ // Schema registration
+ checkIsResultSuccess(mDb1.setSchema(new SetSchemaRequest.Builder()
+ .addSchema(AppSearchEmail.SCHEMA).build()));
+ checkIsResultSuccess(mDb2.setSchema(new SetSchemaRequest.Builder()
+ .addSchema(AppSearchEmail.SCHEMA).build()));
+
+ // Index documents
+ AppSearchEmail email1 =
+ new AppSearchEmail.Builder("uri1")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example")
+ .setBody("This is the body of the testPut email")
+ .build();
+ AppSearchEmail email2 =
+ new AppSearchEmail.Builder("uri2")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example 2")
+ .setBody("This is the body of the testPut second email")
+ .build();
+ AppSearchEmail email3 =
+ new AppSearchEmail.Builder("uri3")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example 3")
+ .setBody("This is the body of the testPut second email")
+ .build();
+ AppSearchEmail email4 =
+ new AppSearchEmail.Builder("uri4")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example 4")
+ .setBody("This is the body of the testPut second email")
+ .build();
+ checkIsBatchResultSuccess(mDb1.putDocuments(
+ new PutDocumentsRequest.Builder().addGenericDocument(email1, email2).build()));
+ checkIsBatchResultSuccess(mDb2.putDocuments(
+ new PutDocumentsRequest.Builder().addGenericDocument(email3, email4).build()));
+
+ // Check the presence of the documents
+ SearchResults searchResults = mDb1.query("", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(2);
+ searchResults = mDb2.query("", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(2);
+
+ // Delete the all document in instance 1 with TERM_MATCH_PREFIX
+ checkIsResultSuccess(mDb1.removeByQuery("",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .build()));
+ searchResults = mDb1.query("", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).isEmpty();
+
+ // Delete the all document in instance 2 with TERM_MATCH_EXACT_ONLY
+ checkIsResultSuccess(mDb2.removeByQuery("",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build()));
+ searchResults = mDb2.query("", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).isEmpty();
+ }
+
+ @Test
public void testRemoveAllAfterEmpty() throws Exception {
// Schema registration
checkIsResultSuccess(mDb1.setSchema(new SetSchemaRequest.Builder()
@@ -1038,7 +1204,10 @@
.isEqualTo(AppSearchResult.RESULT_NOT_FOUND);
// Delete the all documents
- checkIsResultSuccess(mDb1.removeAll());
+ checkIsResultSuccess(mDb1.removeByQuery("",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .build()));
// Make sure it's still gone
getResult = mDb1.getByUri(
diff --git a/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AppSearchTestUtils.java b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AppSearchTestUtils.java
index 448ee19..76015d2 100644
--- a/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AppSearchTestUtils.java
+++ b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/AppSearchTestUtils.java
@@ -49,10 +49,8 @@
return list;
}
- public static List<GenericDocument> doQuery(
- AppSearchManager instance, String queryExpression, SearchSpec spec)
+ public static List<GenericDocument> convertSearchResultsToDocuments(SearchResults searchResults)
throws Exception {
- SearchResults searchResults = instance.query(queryExpression, spec);
List<SearchResults.Result> results = checkIsResultSuccess(searchResults.getNextPage());
List<GenericDocument> documents = new ArrayList<>();
while (results.size() > 0) {
@@ -64,13 +62,6 @@
return documents;
}
- public static List<GenericDocument> doQuery(AppSearchManager instance, String queryExpression)
- throws Exception {
- return doQuery(instance, queryExpression, new SearchSpec.Builder()
- .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
- .build());
- }
-
public static <K, V> AppSearchBatchResult<K, V> checkIsBatchResultSuccess(
Future<AppSearchBatchResult<K, V>> future) throws Exception {
AppSearchBatchResult<K, V> result = future.get();
diff --git a/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/GlobalAppSearchManagerTest.java b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/GlobalAppSearchManagerTest.java
new file mode 100644
index 0000000..e3e1841
--- /dev/null
+++ b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/GlobalAppSearchManagerTest.java
@@ -0,0 +1,289 @@
+/*
+ * 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.appsearch.app;
+
+import static androidx.appsearch.app.AppSearchTestUtils.checkIsBatchResultSuccess;
+import static androidx.appsearch.app.AppSearchTestUtils.checkIsResultSuccess;
+import static androidx.appsearch.app.AppSearchTestUtils.convertSearchResultsToDocuments;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.appsearch.app.AppSearchSchema.PropertyConfig;
+import androidx.appsearch.localbackend.LocalBackend;
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class GlobalAppSearchManagerTest {
+ private AppSearchManager mDb1;
+ private AppSearchManager mDb2;
+
+ private GlobalAppSearchManager mGlobalAppSearchManager;
+
+ @Before
+ public void setUp() throws Exception {
+ Context context = ApplicationProvider.getApplicationContext();
+ LocalBackend backend = LocalBackend.getInstance(context).get().getResultValue();
+ mDb1 = checkIsResultSuccess(new AppSearchManager.Builder()
+ .setDatabaseName("testDb1").setBackend(backend).build());
+ mDb2 = checkIsResultSuccess(new AppSearchManager.Builder()
+ .setDatabaseName("testDb2").setBackend(backend).build());
+
+ mGlobalAppSearchManager = checkIsResultSuccess(new GlobalAppSearchManager.Builder()
+ .setBackend(backend).build());
+
+ // Remove all documents from any instances that may have been created in the tests.
+ backend.resetAllDatabases().get().getResultValue();
+ }
+
+ @Test
+ public void testGlobalQuery_OneInstance() throws Exception {
+ // Schema registration
+ checkIsResultSuccess(mDb1.setSchema(
+ new SetSchemaRequest.Builder().addSchema(AppSearchEmail.SCHEMA).build()));
+
+ // Index a document
+ AppSearchEmail inEmail =
+ new AppSearchEmail.Builder("uri1")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example")
+ .setBody("This is the body of the testPut email")
+ .build();
+ checkIsBatchResultSuccess(mDb1.putDocuments(
+ new PutDocumentsRequest.Builder().addGenericDocument(inEmail).build()));
+
+ // Query for the document
+ SearchResults searchResults = mGlobalAppSearchManager.globalQuery("body",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
+ assertThat(documents).containsExactly(inEmail);
+
+ // Multi-term query
+ searchResults = mGlobalAppSearchManager.globalQuery("body email", new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).containsExactly(inEmail);
+ }
+
+ @Test
+ public void testGlobalQuery_TwoInstances() throws Exception {
+ // Schema registration
+ checkIsResultSuccess(mDb1.setSchema(new SetSchemaRequest.Builder()
+ .addSchema(AppSearchEmail.SCHEMA).build()));
+ checkIsResultSuccess(mDb2.setSchema(new SetSchemaRequest.Builder()
+ .addSchema(AppSearchEmail.SCHEMA).build()));
+
+ // Index a document to instance 1.
+ AppSearchEmail inEmail1 =
+ new AppSearchEmail.Builder("uri1")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example")
+ .setBody("This is the body of the testPut email")
+ .build();
+ checkIsBatchResultSuccess(mDb1.putDocuments(
+ new PutDocumentsRequest.Builder().addGenericDocument(inEmail1).build()));
+
+ // Index a document to instance 2.
+ AppSearchEmail inEmail2 =
+ new AppSearchEmail.Builder("uri2")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example")
+ .setBody("This is the body of the testPut email")
+ .build();
+ checkIsBatchResultSuccess(mDb2.putDocuments(
+ new PutDocumentsRequest.Builder().addGenericDocument(inEmail2).build()));
+
+ // Query across all instances
+ SearchResults searchResults = mGlobalAppSearchManager.globalQuery("body",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).containsExactly(inEmail1, inEmail2);
+ }
+
+ @Test
+ public void testGlobalQuery_GetNextPage() throws Exception {
+ // Schema registration
+ checkIsResultSuccess(mDb1.setSchema(
+ new SetSchemaRequest.Builder().addSchema(AppSearchEmail.SCHEMA).build()));
+ Set<AppSearchEmail> emailSet = new HashSet<>();
+ PutDocumentsRequest.Builder putDocumentsRequestBuilder = new PutDocumentsRequest.Builder();
+
+ // Index 31 documents
+ for (int i = 0; i < 31; i++) {
+ AppSearchEmail inEmail =
+ new AppSearchEmail.Builder("uri" + i)
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example")
+ .setBody("This is the body of the testPut email")
+ .build();
+ emailSet.add(inEmail);
+ putDocumentsRequestBuilder.addGenericDocument(inEmail);
+ }
+ checkIsBatchResultSuccess(mDb1.putDocuments(putDocumentsRequestBuilder.build()));
+
+ // Set number of results per page is 7.
+ SearchResults searchResults = mGlobalAppSearchManager.globalQuery("body",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .setNumPerPage(7)
+ .build());
+ List<GenericDocument> documents = new ArrayList<>();
+
+ int pageNumber = 0;
+ List<SearchResults.Result> results;
+
+ // keep loading next page until it's empty.
+ do {
+ results = checkIsResultSuccess(searchResults.getNextPage());
+ ++pageNumber;
+ for (SearchResults.Result result : results) {
+ documents.add(result.getDocument());
+ }
+ } while (results.size() > 0);
+
+ // check all document presents
+ assertThat(documents).containsExactlyElementsIn(emailSet);
+ assertThat(pageNumber).isEqualTo(6); // 5 (upper(31/7)) + 1 (final empty page)
+ }
+
+ @Test
+ public void testGlobalQuery_AcrossTypes() throws Exception {
+ // Schema registration
+ AppSearchSchema genericSchema = new AppSearchSchema.Builder("Generic")
+ .addProperty(new PropertyConfig.Builder("foo")
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build()
+ ).build();
+
+ // db1 has both "Generic" and "builtin:Email"
+ checkIsResultSuccess(mDb1.setSchema(new SetSchemaRequest.Builder()
+ .addSchema(genericSchema).addSchema(AppSearchEmail.SCHEMA).build()));
+
+ // db2 only has "builtin:Email"
+ checkIsResultSuccess(mDb2.setSchema(new SetSchemaRequest.Builder()
+ .addSchema(AppSearchEmail.SCHEMA).build()));
+
+ // Index a generic document into db1
+ GenericDocument genericDocument =
+ new GenericDocument.Builder<>("uri2", "Generic").setProperty("foo", "body").build();
+ checkIsBatchResultSuccess(mDb1.putDocuments(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocument(genericDocument).build()));
+
+ AppSearchEmail email =
+ new AppSearchEmail.Builder("uri1")
+ .setNamespace("namespace")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example")
+ .setBody("This is the body of the testPut email")
+ .build();
+
+ // Put the email in both databases
+ checkIsBatchResultSuccess((mDb1.putDocuments(
+ new PutDocumentsRequest.Builder().addGenericDocument(email).build())));
+ checkIsBatchResultSuccess(mDb2.putDocuments(
+ new PutDocumentsRequest.Builder().addGenericDocument(email).build()));
+
+ // Query for all documents across types
+ SearchResults searchResults = mGlobalAppSearchManager.globalQuery("body",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).containsExactly(genericDocument, email, email);
+
+ // Query only for email documents
+ searchResults = mGlobalAppSearchManager.globalQuery("body", new SearchSpec.Builder()
+ .setSchemaTypes(AppSearchEmail.SCHEMA_TYPE)
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).containsExactly(email, email);
+ }
+
+ @Test
+ public void testGlobalQuery_NamespaceFilter() throws Exception {
+ // Schema registration
+ checkIsResultSuccess(mDb1.setSchema(new SetSchemaRequest.Builder()
+ .addSchema(AppSearchEmail.SCHEMA).build()));
+ checkIsResultSuccess(mDb2.setSchema(new SetSchemaRequest.Builder()
+ .addSchema(AppSearchEmail.SCHEMA).build()));
+
+ // Index two documents
+ AppSearchEmail document1 =
+ new AppSearchEmail.Builder("uri1")
+ .setNamespace("namespace1")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example")
+ .setBody("This is the body of the testPut email")
+ .build();
+ checkIsBatchResultSuccess(mDb1.putDocuments(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocument(document1).build()));
+
+ AppSearchEmail document2 =
+ new AppSearchEmail.Builder("uri1")
+ .setNamespace("namespace2")
+ .setFrom("[email protected]")
+ .setTo("[email protected]", "[email protected]")
+ .setSubject("testPut example")
+ .setBody("This is the body of the testPut email")
+ .build();
+ checkIsBatchResultSuccess(mDb2.putDocuments(
+ new PutDocumentsRequest.Builder().addGenericDocument(document2).build()));
+
+ // Query for all namespaces
+ SearchResults searchResults = mGlobalAppSearchManager.globalQuery("body",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).containsExactly(document1, document2);
+
+ // Query only for "namespace1"
+ searchResults = mGlobalAppSearchManager.globalQuery("body",
+ new SearchSpec.Builder()
+ .setNamespaces("namespace1")
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).containsExactly(document1);
+ }
+}
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBackend.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBackend.java
index c65b874..88a74fe 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBackend.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBackend.java
@@ -74,6 +74,17 @@
@NonNull SearchSpec searchSpec);
/**
+ * Searches for all documents in the backend based on a given query string.
+ * <p> This method is lightweight. The heavy work will be done in
+ * {@link AppSearchBackend.BackendSearchResults#getNextPage}.
+ * @see GlobalAppSearchManager#globalQuery
+ */
+ @NonNull
+ AppSearchBackend.BackendSearchResults globalQuery(
+ @NonNull String queryExpression,
+ @NonNull SearchSpec searchSpec);
+
+ /**
* Removes {@link GenericDocument}s from the index by URI.
*
* @see AppSearchManager#removeByUri
@@ -83,30 +94,15 @@
@NonNull String databaseName, @NonNull RemoveByUriRequest request);
/**
- * Removes {@link GenericDocument}s from the index by schema type.
+ * Removes {@link GenericDocument}s from the index by query.
*
- * @see AppSearchManager#removeByType
+ * @see AppSearchManager#removeByQuery
*/
@NonNull
- ListenableFuture<AppSearchBatchResult<String, Void>> removeByType(
- @NonNull String databaseName, @NonNull List<String> schemaTypes);
-
- /**
- * Removes {@link GenericDocument}s from the index by namespace.
- *
- * @see AppSearchManager#removeByNamespace
- */
- @NonNull
- ListenableFuture<AppSearchBatchResult<String, Void>> removeByNamespace(
- @NonNull String databaseName, @NonNull List<String> namespaces);
-
- /**
- * Removes all documents owned by this database.
- *
- * @see AppSearchManager#removeAll
- */
- @NonNull
- ListenableFuture<AppSearchResult<Void>> removeAll(@NonNull String databaseName);
+ ListenableFuture<AppSearchResult<Void>> removeByQuery(
+ @NonNull String databaseName,
+ @NonNull String queryExpression,
+ @NonNull SearchSpec searchSpec);
/** Clears all {@link GenericDocument}s, {@link AppSearchSchema}s and all other information
* owned by this app. */
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchManager.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchManager.java
index 4212a45..53147e2 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchManager.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchManager.java
@@ -22,9 +22,6 @@
import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Arrays;
-import java.util.List;
-
/**
* This class provides access to the centralized AppSearch index maintained by the system.
*
@@ -262,88 +259,25 @@
}
/**
- * Removes {@link GenericDocument}s from the index by schema type.
+ * Removes {@link GenericDocument}s from the index by Query. Documents will be removed if they
+ * match the query expression in given namespaces and schemaTypes.
*
- * @param schemaTypes Schema types whose documents to delete.
- * @return The pending result of performing this operation. The keys of the returned
- * {@link AppSearchBatchResult} are the input schema types. The values are {@code null} on
- * success, or a failed {@link AppSearchResult} otherwise. Types that are not found will
- * return a failed {@link AppSearchResult} with a result code of
- * {@link AppSearchResult#RESULT_NOT_FOUND}.
- * @hide
- */
- @NonNull
- public ListenableFuture<AppSearchBatchResult<String, Void>> removeByType(
- @NonNull String... schemaTypes) {
- Preconditions.checkNotNull(schemaTypes);
- return removeByType(Arrays.asList(schemaTypes));
- }
-
- /**
- * Removes {@link GenericDocument}s from the index by schema type.
+ * <p> An empty query matches all documents.
*
- * @param schemaTypes Schema types whose documents to delete.
- * @return The pending result of performing this operation. The keys of the returned
- * {@link AppSearchBatchResult} are the input schema types. The values are {@code null} on
- * success, or a failed {@link AppSearchResult} otherwise. Types that are not found will
- * return a failed {@link AppSearchResult} with a result code of
- * {@link AppSearchResult#RESULT_NOT_FOUND}.
- * @hide
- */
- @NonNull
- public ListenableFuture<AppSearchBatchResult<String, Void>> removeByType(
- @NonNull List<String> schemaTypes) {
- Preconditions.checkNotNull(schemaTypes);
- return mBackend.removeByType(mDatabaseName, schemaTypes);
- }
-
- /**
- * Removes {@link GenericDocument}s from the index by namespace.
+ * <p> An empty set of namespaces or of schemaTypes matches all namespaces or schemaTypes in
+ * the current database.
*
- * @param namespaces Namespaces whose documents to delete.
- * @return The pending result of performing this operation. The keys of the returned
- * {@link AppSearchBatchResult} are the input namespaces. The values are {@code null} on
- * success, or a failed {@link AppSearchResult} otherwise. Namespaces that are not found
- * will return a failed {@link AppSearchResult} with a result code of
- * {@link AppSearchResult#RESULT_NOT_FOUND}.
- * @hide
- */
- @NonNull
- public ListenableFuture<AppSearchBatchResult<String, Void>> removeByNamespace(
- @NonNull String... namespaces) {
- Preconditions.checkNotNull(namespaces);
- return removeByNamespace(Arrays.asList(namespaces));
- }
-
- /**
- * Removes {@link GenericDocument}s from the index by namespace.
- *
- * @param namespaces Namespaces whose documents to delete.
- * @return The pending result of performing this operation. The keys of the returned
- * {@link AppSearchBatchResult} are the input namespaces. The values are {@code null} on
- * success, or a failed {@link AppSearchResult} otherwise. Namespaces that are not found
- * will return a failed {@link AppSearchResult} with a result code of
- * {@link AppSearchResult#RESULT_NOT_FOUND}.
- * @hide
- */
- @NonNull
- public ListenableFuture<AppSearchBatchResult<String, Void>> removeByNamespace(
- @NonNull List<String> namespaces) {
- Preconditions.checkNotNull(namespaces);
- return mBackend.removeByNamespace(mDatabaseName, namespaces);
- }
-
- /**
- * Removes all documents owned by this instance.
- *
- * <p>The schemas will remain. To clear everything including schemas, please call
- * {@link #setSchema} with an empty schema and {@code forceOverride} set to true.
- *
+ * @param queryExpression Query String to search.
+ * @param searchSpec Spec containing schemaTypes, namespaces and query expression
+ * indicates how document will be removed. All specific about how to
+ * scoring, ordering, snippeting and resulting will be ignored.
* @return The pending result of performing this operation.
* @hide
*/
@NonNull
- public ListenableFuture<AppSearchResult<Void>> removeAll() {
- return mBackend.removeAll(mDatabaseName);
+ public ListenableFuture<AppSearchResult<Void>> removeByQuery(
+ @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
+ Preconditions.checkNotNull(searchSpec);
+ return mBackend.removeByQuery(mDatabaseName, queryExpression, searchSpec);
}
}
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/GlobalAppSearchManager.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/GlobalAppSearchManager.java
new file mode 100644
index 0000000..c54d4d3
--- /dev/null
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/GlobalAppSearchManager.java
@@ -0,0 +1,125 @@
+/*
+ * 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.appsearch.app;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.concurrent.futures.ResolvableFuture;
+import androidx.core.util.Preconditions;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * This class provides global access to the centralized AppSearch index maintained by the system.
+ *
+ * <p>Apps can retrieve indexed documents through the query API.
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+// TODO(b/148046169): This class header needs a detailed example/tutorial.
+public class GlobalAppSearchManager {
+
+ private final AppSearchBackend mBackend;
+
+ /** Builder class for {@link GlobalAppSearchManager} objects. */
+ public static final class Builder {
+ private AppSearchBackend mBackend;
+ private boolean mBuilt = false;
+
+ /**
+ * Sets the backend where this {@link GlobalAppSearchManager} will retrieve data from.
+ */
+ @NonNull
+ public Builder setBackend(@NonNull AppSearchBackend backend) {
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ Preconditions.checkNotNull(backend);
+ mBackend = backend;
+ return this;
+ }
+
+ /**
+ * Asynchronously connects to the AppSearch backend and returns the initialized instance.
+ */
+ @NonNull
+ public ListenableFuture<AppSearchResult<GlobalAppSearchManager>> build() {
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ Preconditions.checkState(mBackend != null, "setBackend() has never been called");
+ mBuilt = true;
+ ResolvableFuture<AppSearchResult<GlobalAppSearchManager>> result =
+ ResolvableFuture.create();
+ result.set(AppSearchResult.newSuccessfulResult(new GlobalAppSearchManager(mBackend)));
+ return result;
+ }
+ }
+
+ GlobalAppSearchManager(@NonNull AppSearchBackend backend) {
+ mBackend = backend;
+ }
+
+ /**
+ * Searches across all documents in the backend based on a given query string.
+ *
+ * <p>Currently we support following features in the raw query format:
+ * <ul>
+ * <li>AND
+ * <p>AND joins (e.g. “match documents that have both the terms ‘dog’ and
+ * ‘cat’”).
+ * Example: hello world matches documents that have both ‘hello’ and ‘world’
+ * <li>OR
+ * <p>OR joins (e.g. “match documents that have either the term ‘dog’ or
+ * ‘cat’”).
+ * Example: dog OR puppy
+ * <li>Exclusion
+ * <p>Exclude a term (e.g. “match documents that do
+ * not have the term ‘dog’”).
+ * Example: -dog excludes the term ‘dog’
+ * <li>Grouping terms
+ * <p>Allow for conceptual grouping of subqueries to enable hierarchical structures (e.g.
+ * “match documents that have either ‘dog’ or ‘puppy’, and either ‘cat’ or ‘kitten’”).
+ * Example: (dog puppy) (cat kitten) two one group containing two terms.
+ * <li>Property restricts
+ * <p> Specifies which properties of a document to specifically match terms in (e.g.
+ * “match documents where the ‘subject’ property contains ‘important’”).
+ * Example: subject:important matches documents with the term ‘important’ in the
+ * ‘subject’ property
+ * <li>Schema type restricts
+ * <p>This is similar to property restricts, but allows for restricts on top-level document
+ * fields, such as schema_type. Clients should be able to limit their query to documents of
+ * a certain schema_type (e.g. “match documents that are of the ‘Email’ schema_type”).
+ * Example: { schema_type_filters: “Email”, “Video”,query: “dog” } will match documents
+ * that contain the query term ‘dog’ and are of either the ‘Email’ schema type or the
+ * ‘Video’ schema type.
+ * </ul>
+ *
+ * <p> This method is lightweight. The heavy work will be done in
+ * {@link SearchResults#getNextPage()}.
+ *
+ * @param queryExpression Query String to search.
+ * @param searchSpec Spec for setting filters, raw query etc.
+ * @return The search result of performing this operation.
+ */
+ @NonNull
+ public SearchResults globalQuery(
+ @NonNull String queryExpression,
+ @NonNull SearchSpec searchSpec) {
+ Preconditions.checkNotNull(queryExpression);
+ Preconditions.checkNotNull(searchSpec);
+ AppSearchBackend.BackendSearchResults backendSearchResults =
+ mBackend.globalQuery(queryExpression, searchSpec);
+ return new SearchResults(backendSearchResults);
+ }
+}
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/SetVisibilityRequest.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/SetVisibilityRequest.java
new file mode 100644
index 0000000..09e5a13
--- /dev/null
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/SetVisibilityRequest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.appsearch.app;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.collection.ArraySet;
+import androidx.core.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Encapsulates a request to update the visibility settings of an {@link AppSearchManager} database.
+ *
+ * // TODO(b/169883602): Move these comments to the actual setVisibilityRequest(request) API.
+ * <p>Visibility settings are not carried over from previous {@code SetVisibilityRequest}s. The
+ * entire set of visibility settings must be specified on each {@code SetVisibilityRequest}.
+ *
+ * <p>The visibility settings apply to the schema instance that currently exists. If a schema is
+ * deleted and then re-added, the visibility setting will no longer apply to the new instance of
+ * the schema.
+ *
+ * <p>An {@link AppSearchException} will be thrown if a specified schema doesn't exist.
+ *
+ * <p>The default visibility settings are that all documents can be shown on platform surfaces.
+ * Documents can be opted out of being shown on platform surfaces by specifying their schema type
+ * in {@link SetVisibilityRequest.Builder#setHiddenFromPlatformSurfaces}.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public final class SetVisibilityRequest {
+ private final Set<AppSearchSchema> mSchemasHiddenFromPlatformSurfaces;
+
+ SetVisibilityRequest(Set<AppSearchSchema> schemasHiddenFromPlatformSurfaces) {
+ mSchemasHiddenFromPlatformSurfaces = schemasHiddenFromPlatformSurfaces;
+ }
+
+ /** @hide */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @NonNull
+ public Set<AppSearchSchema> getSchemasHiddenFromPlatformSurfaces() {
+ return mSchemasHiddenFromPlatformSurfaces;
+ }
+
+ /** Builder for {@link SetVisibilityRequest} objects. */
+ public static final class Builder {
+ private final Set<AppSearchSchema> mSchemasHiddenFromPlatformSurfaces = new ArraySet<>();
+ private boolean mBuilt = false;
+
+ /** Set documents of type {@code schemas} to be hidden from platform surfaces. */
+ @NonNull
+ public Builder setHiddenFromPlatformSurfaces(@NonNull AppSearchSchema... schemas) {
+ Preconditions.checkNotNull(schemas);
+ return setHiddenFromPlatformSurfaces(Arrays.asList(schemas));
+ }
+
+ /** Set documents of type {@code schemas} to be hidden from platform surfaces. */
+ @NonNull
+ public Builder setHiddenFromPlatformSurfaces(@NonNull Collection<AppSearchSchema> schemas) {
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ Preconditions.checkNotNull(schemas);
+ mSchemasHiddenFromPlatformSurfaces.addAll(schemas);
+ return this;
+ }
+
+ /** Builds a new {@link SetVisibilityRequest}. */
+ @NonNull
+ public SetVisibilityRequest build() {
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ mBuilt = true;
+ return new SetVisibilityRequest(mSchemasHiddenFromPlatformSurfaces);
+ }
+ }
+}
diff --git a/appsearch/local-backend/src/androidTest/java/androidx/appsearch/localbackend/AppSearchImplTest.java b/appsearch/local-backend/src/androidTest/java/androidx/appsearch/localbackend/AppSearchImplTest.java
index e4fae37..661fea0 100644
--- a/appsearch/local-backend/src/androidTest/java/androidx/appsearch/localbackend/AppSearchImplTest.java
+++ b/appsearch/local-backend/src/androidTest/java/androidx/appsearch/localbackend/AppSearchImplTest.java
@@ -35,12 +35,14 @@
import com.google.android.icing.proto.SearchSpecProto;
import com.google.android.icing.proto.StatusProto;
import com.google.android.icing.proto.TermMatchType;
+import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import java.util.Collections;
import java.util.Set;
public class AppSearchImplTest {
@@ -93,7 +95,7 @@
SchemaProto expectedSchema = SchemaProto.newBuilder()
.addTypes(SchemaTypeConfigProto.newBuilder()
- .setSchemaType("databaseName/Foo").build())
+ .setSchemaType("databaseName/Foo").build())
.addTypes(SchemaTypeConfigProto.newBuilder()
.setSchemaType("databaseName/TestType")
.addProperties(PropertyConfigProto.newBuilder()
@@ -120,7 +122,7 @@
}
@Test
- public void testRewriteDocumentProto() {
+ public void testAddDocumentTypePrefix() {
DocumentProto insideDocument = DocumentProto.newBuilder()
.setUri("inside-uri")
.setSchema("type")
@@ -146,10 +148,40 @@
.build();
DocumentProto.Builder actualDocument = documentProto.toBuilder();
- mAppSearchImpl.rewriteDocumentTypes("databaseName/", actualDocument, /*add=*/true);
+ mAppSearchImpl.addPrefixToDocument(actualDocument, "databaseName/");
assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
- mAppSearchImpl.rewriteDocumentTypes("databaseName/", actualDocument, /*add=*/false);
- assertThat(actualDocument.build()).isEqualTo(documentProto);
+ }
+
+ @Test
+ public void testRemoveDocumentTypePrefixes() {
+ DocumentProto insideDocument = DocumentProto.newBuilder()
+ .setUri("inside-uri")
+ .setSchema("databaseName1/type")
+ .setNamespace("databaseName2/namespace")
+ .build();
+ DocumentProto documentProto = DocumentProto.newBuilder()
+ .setUri("uri")
+ .setSchema("databaseName2/type")
+ .setNamespace("databaseName3/namespace")
+ .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
+ .build();
+
+ DocumentProto expectedInsideDocument = DocumentProto.newBuilder()
+ .setUri("inside-uri")
+ .setSchema("type")
+ .setNamespace("namespace")
+ .build();
+ // Since we don't pass in "databaseName3/" as a prefix to remove, it stays on the Document.
+ DocumentProto expectedDocumentProto = DocumentProto.newBuilder()
+ .setUri("uri")
+ .setSchema("type")
+ .setNamespace("namespace")
+ .addProperties(PropertyProto.newBuilder().addDocumentValues(expectedInsideDocument))
+ .build();
+
+ DocumentProto.Builder actualDocument = documentProto.toBuilder();
+ mAppSearchImpl.removeDatabasesFromDocument(actualDocument);
+ assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
}
@Test
@@ -201,7 +233,7 @@
}
@Test
- public void testRewriteSearchSpec() throws Exception {
+ public void testRewriteSearchSpec_OneInstance() throws Exception {
SearchSpecProto.Builder searchSpecProto =
SearchSpecProto.newBuilder().setQuery("");
@@ -212,21 +244,60 @@
.build();
mAppSearchImpl.setSchema("database", schema, /*forceOverride=*/false);
// Insert document
- DocumentProto insideDocument = DocumentProto.newBuilder()
+ DocumentProto document = DocumentProto.newBuilder()
.setUri("inside-uri")
.setSchema("type")
.setNamespace("namespace")
.build();
- mAppSearchImpl.putDocument("database", insideDocument);
+ mAppSearchImpl.putDocument("database", document);
// Rewrite SearchSpec
- mAppSearchImpl.rewriteSearchSpecForNonEmptyDatabase(
- "database", searchSpecProto);
+ mAppSearchImpl.rewriteSearchSpecForDatabases(searchSpecProto, Collections.singleton(
+ "database"));
assertThat(searchSpecProto.getSchemaTypeFiltersList()).containsExactly("database/type");
assertThat(searchSpecProto.getNamespaceFiltersList()).containsExactly("database/namespace");
}
@Test
+ public void testRewriteSearchSpec_TwoInstances() throws Exception {
+ SearchSpecProto.Builder searchSpecProto =
+ SearchSpecProto.newBuilder().setQuery("");
+
+ // Insert schema
+ SchemaProto schema = SchemaProto.newBuilder()
+ .addTypes(SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("typeA").build())
+ .addTypes(SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("typeB").build())
+ .build();
+ mAppSearchImpl.setSchema("database1", schema, /*forceOverride=*/false);
+ mAppSearchImpl.setSchema("database2", schema, /*forceOverride=*/false);
+
+ // Insert documents
+ DocumentProto document1 = DocumentProto.newBuilder()
+ .setUri("inside-uri")
+ .setSchema("typeA")
+ .setNamespace("namespace")
+ .build();
+ mAppSearchImpl.putDocument("database1", document1);
+
+ DocumentProto document2 = DocumentProto.newBuilder()
+ .setUri("inside-uri")
+ .setSchema("typeB")
+ .setNamespace("namespace")
+ .build();
+ mAppSearchImpl.putDocument("database2", document2);
+
+ // Rewrite SearchSpec
+ mAppSearchImpl.rewriteSearchSpecForDatabases(searchSpecProto,
+ ImmutableSet.of("database1", "database2"));
+ assertThat(searchSpecProto.getSchemaTypeFiltersList()).containsExactly(
+ "database1/typeA", "database1/typeB", "database2/typeA", "database2/typeB");
+ assertThat(searchSpecProto.getNamespaceFiltersList()).containsExactly(
+ "database1/namespace", "database2/namespace");
+ }
+
+ @Test
public void testQueryEmptyDatabase() throws Exception {
SearchResultProto searchResultProto = mAppSearchImpl.query("EmptyDatabase",
SearchSpecProto.getDefaultInstance(),
@@ -236,10 +307,24 @@
}
@Test
+ public void testGlobalQueryEmptyDatabase() throws Exception {
+ SearchResultProto searchResultProto = mAppSearchImpl.globalQuery(
+ SearchSpecProto.getDefaultInstance(),
+ ResultSpecProto.getDefaultInstance(), ScoringSpecProto.getDefaultInstance());
+ assertThat(searchResultProto.getResultsCount()).isEqualTo(0);
+ assertThat(searchResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK);
+ }
+
+ @Test
public void testRemoveEmptyDatabase_NoExceptionThrown() throws Exception {
- mAppSearchImpl.removeByType("EmptyDatabase", "FakeType");
- mAppSearchImpl.removeByNamespace("EmptyDatabase", "FakeNamespace");
- mAppSearchImpl.removeAll("EmptyDatabase");
+ mAppSearchImpl.removeByQuery("EmptyDatabase",
+ SearchSpecProto.newBuilder().addSchemaTypeFilters("FakeType")
+ .setTermMatchType(TermMatchType.Code.PREFIX).build());
+ mAppSearchImpl.removeByQuery("EmptyDatabase",
+ SearchSpecProto.newBuilder().addNamespaceFilters("FakeNamespace")
+ .setTermMatchType(TermMatchType.Code.PREFIX).build());
+ mAppSearchImpl.removeByQuery("EmptyDatabase", SearchSpecProto.newBuilder()
+ .setTermMatchType(TermMatchType.Code.PREFIX).build());
}
@Test
@@ -326,7 +411,7 @@
// Save only Email to database1 this time.
SchemaProto emailSchemaProto = SchemaProto.newBuilder()
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("Email"))
+ .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("Email"))
.build();
mAppSearchImpl.setSchema("database1", emailSchemaProto, /*forceOverride=*/true);
diff --git a/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/AppSearchImpl.java b/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/AppSearchImpl.java
index ed8d299..fa6a3f4 100644
--- a/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/AppSearchImpl.java
+++ b/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/AppSearchImpl.java
@@ -29,8 +29,6 @@
import androidx.core.util.Preconditions;
import com.google.android.icing.IcingSearchEngine;
-import com.google.android.icing.proto.DeleteByNamespaceResultProto;
-import com.google.android.icing.proto.DeleteBySchemaTypeResultProto;
import com.google.android.icing.proto.DeleteResultProto;
import com.google.android.icing.proto.DocumentProto;
import com.google.android.icing.proto.GetAllNamespacesResultProto;
@@ -54,8 +52,10 @@
import com.google.android.icing.proto.StatusProto;
import java.io.File;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
@@ -89,12 +89,14 @@
* </ul>
*
* <p>This class is thread safe.
+ *
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@WorkerThread
public final class AppSearchImpl {
private static final String TAG = "AppSearchImpl";
+ private static final char DATABASE_DELIMITER = '/';
@VisibleForTesting
static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000;
@@ -242,7 +244,7 @@
public void putDocument(@NonNull String databaseName, @NonNull DocumentProto document)
throws AppSearchException {
DocumentProto.Builder documentBuilder = document.toBuilder();
- rewriteDocumentTypes(getDatabasePrefix(databaseName), documentBuilder, /*add=*/ true);
+ addPrefixToDocument(documentBuilder, getDatabasePrefix(databaseName));
PutResultProto putResultProto;
mReadWriteLock.writeLock().lock();
@@ -283,7 +285,7 @@
checkSuccess(getResultProto.getStatus());
DocumentProto.Builder documentBuilder = getResultProto.getDocument().toBuilder();
- rewriteDocumentTypes(getDatabasePrefix(databaseName), documentBuilder, /*add=*/ false);
+ removeDatabasesFromDocument(documentBuilder);
return documentBuilder.build();
}
@@ -306,14 +308,43 @@
@NonNull SearchSpecProto searchSpec,
@NonNull ResultSpecProto resultSpec,
@NonNull ScoringSpecProto scoringSpec) throws AppSearchException {
+ return doQuery(searchSpec, resultSpec, scoringSpec, Collections.singleton(databaseName));
+ }
+
+ /**
+ * Executes a global query, i.e. over all permitted databases, against the AppSearch index and
+ * returns results.
+ *
+ * <p>This method belongs to query group.
+ *
+ * @param searchSpec Defines what and how to search
+ * @param resultSpec Defines what results to show
+ * @param scoringSpec Defines how to order results
+ * @return The results of performing this search The proto might have no {@code results} if no
+ * documents matched the query.
+ * @throws AppSearchException on IcingSearchEngine error.
+ */
+ @NonNull
+ public SearchResultProto globalQuery(
+ @NonNull SearchSpecProto searchSpec,
+ @NonNull ResultSpecProto resultSpec,
+ @NonNull ScoringSpecProto scoringSpec) throws AppSearchException {
+ return doQuery(searchSpec, resultSpec, scoringSpec, mNamespaceMap.keySet());
+ }
+
+ private SearchResultProto doQuery(@NonNull SearchSpecProto searchSpec,
+ @NonNull ResultSpecProto resultSpec,
+ @NonNull ScoringSpecProto scoringSpec, Set<String> databases)
+ throws AppSearchException {
SearchSpecProto.Builder searchSpecBuilder = searchSpec.toBuilder();
SearchResultProto searchResultProto;
mReadWriteLock.readLock().lock();
try {
- // Only rewrite SearchSpec for non empty database.
- // rewriteSearchSpecForNonEmptyDatabase will return false for empty database, we
- // should just return an empty SearchResult and skip sending request to Icing.
- if (!rewriteSearchSpecForNonEmptyDatabase(databaseName, searchSpecBuilder)) {
+ // rewriteSearchSpecForDatabases will return false if none of the databases have
+ // documents, so we can return an empty SearchResult and skip sending request to Icing.
+ // We use the mNamespaceMap.keySet here because it's the smaller set of valid databases
+ // that could exist.
+ if (!rewriteSearchSpecForDatabases(searchSpecBuilder, databases)) {
return SearchResultProto.newBuilder()
.setStatus(StatusProto.newBuilder()
.setCode(StatusProto.Code.OK)
@@ -329,7 +360,7 @@
if (searchResultProto.getResultsCount() == 0) {
return searchResultProto;
}
- return rewriteSearchResultProto(databaseName, searchResultProto);
+ return rewriteSearchResultProto(searchResultProto);
}
/**
@@ -338,20 +369,19 @@
*
* <p>This method belongs to query group.
*
- * @param databaseName The databaseName of the previously executed query.
* @param nextPageToken The token of pre-loaded results of previously executed query.
* @return The next page of results of previously executed query.
* @throws AppSearchException on IcingSearchEngine error.
*/
@NonNull
- public SearchResultProto getNextPage(@NonNull String databaseName, long nextPageToken)
+ public SearchResultProto getNextPage(long nextPageToken)
throws AppSearchException {
SearchResultProto searchResultProto = mIcingSearchEngine.getNextPage(nextPageToken);
checkSuccess(searchResultProto.getStatus());
if (searchResultProto.getResultsCount() == 0) {
return searchResultProto;
}
- return rewriteSearchResultProto(databaseName, searchResultProto);
+ return rewriteSearchResultProto(searchResultProto);
}
/**
@@ -391,93 +421,38 @@
}
/**
- * Removes all documents having the given {@code schemaType} in given database.
+ * Removes documents by given query.
*
* <p>This method belongs to mutate group.
*
- * @param databaseName The databaseName that contains documents of schemaType.
- * @param schemaType The schemaType of documents to remove.
+ * @param databaseName The databaseName the document is in.
+ * @param searchSpec Defines what and how to remove
* @throws AppSearchException on IcingSearchEngine error.
*/
- public void removeByType(@NonNull String databaseName, @NonNull String schemaType)
+ public void removeByQuery(@NonNull String databaseName, @NonNull SearchSpecProto searchSpec)
throws AppSearchException {
- String qualifiedType = getDatabasePrefix(databaseName) + schemaType;
- DeleteBySchemaTypeResultProto deleteBySchemaTypeResultProto;
- mReadWriteLock.writeLock().lock();
- try {
- Set<String> existingSchemaTypes = mSchemaMap.get(databaseName);
- if (existingSchemaTypes == null || !existingSchemaTypes.contains(qualifiedType)) {
- return;
- }
- deleteBySchemaTypeResultProto = mIcingSearchEngine.deleteBySchemaType(qualifiedType);
- checkForOptimize(/* force= */true);
- } finally {
- mReadWriteLock.writeLock().unlock();
- }
- checkSuccess(deleteBySchemaTypeResultProto.getStatus());
- }
- /**
- * Removes all documents having the given {@code namespace} in given database.
- *
- * <p>This method belongs to mutate group.
- *
- * @param databaseName The databaseName that contains documents of namespace.
- * @param namespace The namespace of documents to remove.
- * @throws AppSearchException on IcingSearchEngine error.
- */
- public void removeByNamespace(@NonNull String databaseName, @NonNull String namespace)
- throws AppSearchException {
- String qualifiedNamespace = getDatabasePrefix(databaseName) + namespace;
- DeleteByNamespaceResultProto deleteByNamespaceResultProto;
+ SearchSpecProto.Builder searchSpecBuilder = searchSpec.toBuilder();
+ DeleteResultProto deleteResultProto;
mReadWriteLock.writeLock().lock();
try {
- Set<String> existingNamespaces = mNamespaceMap.get(databaseName);
- if (existingNamespaces == null || !existingNamespaces.contains(qualifiedNamespace)) {
+ // Only rewrite SearchSpec for non empty database.
+ // rewriteSearchSpecForNonEmptyDatabase will return false for empty database, we
+ // should skip sending request to Icing and return in here.
+ if (!rewriteSearchSpecForDatabases(searchSpecBuilder,
+ Collections.singleton(databaseName))) {
return;
}
- deleteByNamespaceResultProto = mIcingSearchEngine.deleteByNamespace(qualifiedNamespace);
+ deleteResultProto = mIcingSearchEngine.deleteByQuery(
+ searchSpecBuilder.build());
checkForOptimize(/* force= */true);
} finally {
mReadWriteLock.writeLock().unlock();
}
- checkSuccess(deleteByNamespaceResultProto.getStatus());
- }
-
- /**
- * Clears the given database by removing all documents and types.
- *
- * <p>The schemas will remain. To clear everything including schemas, please call
- * {@link #setSchema} with an empty schema and {@code forceOverride} set to true.
- *
- * <p>This method belongs to mutate group.
- *
- * @param databaseName The databaseName to remove all documents from.
- * @throws AppSearchException on IcingSearchEngine error.
- */
- public void removeAll(@NonNull String databaseName)
- throws AppSearchException {
- mReadWriteLock.writeLock().lock();
- try {
- Set<String> existingNamespaces = mNamespaceMap.get(databaseName);
- if (existingNamespaces == null) {
- return;
- }
- for (String namespace : existingNamespaces) {
- DeleteByNamespaceResultProto deleteByNamespaceResultProto =
- mIcingSearchEngine.deleteByNamespace(namespace);
- // There's no way for AppSearch to know that all documents in a particular
- // namespace have been deleted, but if you try to delete an empty namespace, Icing
- // returns NOT_FOUND. Just ignore that code.
- checkCodeOneOf(
- deleteByNamespaceResultProto.getStatus(),
- StatusProto.Code.OK, StatusProto.Code.NOT_FOUND);
- }
- mNamespaceMap.remove(databaseName);
- checkForOptimize(/* force= */true);
- } finally {
- mReadWriteLock.writeLock().unlock();
- }
+ // it seems that the caller wants to get success if the data matching the query is not in
+ // the DB because it was not there or was successfully deleted.
+ checkCodeOneOf(deleteResultProto.getStatus(),
+ StatusProto.Code.OK, StatusProto.Code.NOT_FOUND);
}
/**
@@ -570,36 +545,63 @@
}
/**
- * Rewrites all types and namespaces mentioned anywhere in {@code documentBuilder} to prepend
- * or remove {@code prefix}.
+ * Prepends {@code prefix} to all types and namespaces mentioned anywhere in
+ * {@code documentBuilder}.
*
- * @param prefix The prefix to add or remove
* @param documentBuilder The document to mutate
- * @param add Whether to add prefix to the types and namespaces. If {@code false},
- * prefix will be removed.
- * @throws IllegalStateException If {@code add=false} and the document has a type or namespace
- * that doesn't start with {@code prefix}.
+ * @param prefix The prefix to add
*/
@VisibleForTesting
- void rewriteDocumentTypes(
- @NonNull String prefix,
+ void addPrefixToDocument(
@NonNull DocumentProto.Builder documentBuilder,
- boolean add) {
+ @NonNull String prefix) {
// Rewrite the type name to include/remove the prefix.
- String newSchema;
- if (add) {
- newSchema = prefix + documentBuilder.getSchema();
- } else {
- newSchema = removePrefix(prefix, "schemaType", documentBuilder.getSchema());
- }
+ String newSchema = prefix + documentBuilder.getSchema();
documentBuilder.setSchema(newSchema);
// Rewrite the namespace to include/remove the prefix.
- if (add) {
- documentBuilder.setNamespace(prefix + documentBuilder.getNamespace());
- } else {
- documentBuilder.setNamespace(
- removePrefix(prefix, "namespace", documentBuilder.getNamespace()));
+ documentBuilder.setNamespace(prefix + documentBuilder.getNamespace());
+
+ // Recurse into derived documents
+ for (int propertyIdx = 0;
+ propertyIdx < documentBuilder.getPropertiesCount();
+ propertyIdx++) {
+ int documentCount = documentBuilder.getProperties(propertyIdx).getDocumentValuesCount();
+ if (documentCount > 0) {
+ PropertyProto.Builder propertyBuilder =
+ documentBuilder.getProperties(propertyIdx).toBuilder();
+ for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) {
+ DocumentProto.Builder derivedDocumentBuilder =
+ propertyBuilder.getDocumentValues(documentIdx).toBuilder();
+ addPrefixToDocument(derivedDocumentBuilder, prefix);
+ propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder);
+ }
+ documentBuilder.setProperties(propertyIdx, propertyBuilder);
+ }
+ }
+ }
+
+ /**
+ * Removes any database names from types and namespaces mentioned anywhere in
+ * {@code documentBuilder}.
+ *
+ * @param documentBuilder The document to mutate
+ */
+ @VisibleForTesting
+ void removeDatabasesFromDocument(@NonNull DocumentProto.Builder documentBuilder) {
+ int delimiterIndex;
+ if ((delimiterIndex = documentBuilder.getSchema().indexOf(DATABASE_DELIMITER)) != -1) {
+ // Rewrite the type name to remove the prefix.
+ // Add 1 to include the char size of the DATABASE_DELIMITER
+ String newSchema = documentBuilder.getSchema().substring(delimiterIndex + 1);
+ documentBuilder.setSchema(newSchema);
+ }
+
+ if ((delimiterIndex = documentBuilder.getNamespace().indexOf(DATABASE_DELIMITER)) != -1) {
+ // Rewrite the namespace to remove the prefix.
+ // Add 1 to include the char size of the DATABASE_DELIMITER
+ String newNamespace = documentBuilder.getNamespace().substring(delimiterIndex + 1);
+ documentBuilder.setNamespace(newNamespace);
}
// Recurse into derived documents
@@ -613,7 +615,7 @@
for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) {
DocumentProto.Builder derivedDocumentBuilder =
propertyBuilder.getDocumentValues(documentIdx).toBuilder();
- rewriteDocumentTypes(prefix, derivedDocumentBuilder, add);
+ removeDatabasesFromDocument(derivedDocumentBuilder);
propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder);
}
documentBuilder.setProperties(propertyIdx, propertyBuilder);
@@ -622,51 +624,68 @@
}
/**
- * Rewrites searchSpec by adding schemaTypeFilter and namespacesFilter
+ * Rewrites the schemaTypeFilters and namespacesFilters that exist in {@code databaseNames}.
*
- * <p>If user input empty filter lists, will look up {@link #mSchemaMap} and
- * {@link #mNamespaceMap} and put all values belong to current database to narrow down Icing
- * search area.
+ * <p>If the searchSpec has empty filter lists, all existing databases from
+ * {@code databaseNames} will be added.
* <p>This method should be only called in query methods and get the READ lock to keep thread
* safety.
- * @return false if the current database is brand new and contains nothing. We should just
- * return an empty query result to user.
+ *
+ * @return false if none of the requested databases exist.
*/
@VisibleForTesting
@GuardedBy("mReadWriteLock")
- boolean rewriteSearchSpecForNonEmptyDatabase(@NonNull String databaseName,
- @NonNull SearchSpecProto.Builder searchSpecBuilder) {
- Set<String> existingSchemaTypes = mSchemaMap.get(databaseName);
- Set<String> existingNamespaces = mNamespaceMap.get(databaseName);
- if (existingSchemaTypes == null || existingSchemaTypes.isEmpty()
- || existingNamespaces == null || existingNamespaces.isEmpty()) {
+ boolean rewriteSearchSpecForDatabases(
+ @NonNull SearchSpecProto.Builder searchSpecBuilder,
+ @NonNull Set<String> databaseNames) {
+ // Create a copy since retainAll() modifies the original set.
+ Set<String> existingDatabases = new HashSet<>(mNamespaceMap.keySet());
+ existingDatabases.retainAll(databaseNames);
+
+ if (existingDatabases.isEmpty()) {
+ // None of the databases exist, empty query.
return false;
}
- // Rewrite any existing schema types specified in the searchSpec, or add schema types to
- // limit the search to this database instance.
- if (searchSpecBuilder.getSchemaTypeFiltersCount() > 0) {
- for (int i = 0; i < searchSpecBuilder.getSchemaTypeFiltersCount(); i++) {
- String qualifiedType = getDatabasePrefix(databaseName)
- + searchSpecBuilder.getSchemaTypeFilters(i);
- if (existingSchemaTypes.contains(qualifiedType)) {
- searchSpecBuilder.setSchemaTypeFilters(i, qualifiedType);
+
+ // Cache the schema type filters and namespaces before clearing everything.
+ List<String> schemaTypeFilters = searchSpecBuilder.getSchemaTypeFiltersList();
+ searchSpecBuilder.clearSchemaTypeFilters();
+
+ List<String> namespaceFilters = searchSpecBuilder.getNamespaceFiltersList();
+ searchSpecBuilder.clearNamespaceFilters();
+
+ // Rewrite filters to include a database prefix.
+ for (String databaseName : existingDatabases) {
+ Set<String> existingSchemaTypes = mSchemaMap.get(databaseName);
+ if (schemaTypeFilters.isEmpty()) {
+ // Include all schema types
+ searchSpecBuilder.addAllSchemaTypeFilters(existingSchemaTypes);
+ } else {
+ // Qualify the given schema types
+ for (String schemaType : schemaTypeFilters) {
+ String qualifiedType = getDatabasePrefix(databaseName) + schemaType;
+ if (existingSchemaTypes.contains(qualifiedType)) {
+ searchSpecBuilder.addSchemaTypeFilters(qualifiedType);
+ }
+
}
}
- } else {
- searchSpecBuilder.addAllSchemaTypeFilters(existingSchemaTypes);
+
+ Set<String> existingNamespaces = mNamespaceMap.get(databaseName);
+ if (namespaceFilters.isEmpty()) {
+ // Include all namespaces
+ searchSpecBuilder.addAllNamespaceFilters(existingNamespaces);
+ } else {
+ // Qualify the given namespaces.
+ for (String namespace : namespaceFilters) {
+ String qualifiedNamespace = getDatabasePrefix(databaseName) + namespace;
+ if (existingNamespaces.contains(qualifiedNamespace)) {
+ searchSpecBuilder.addNamespaceFilters(qualifiedNamespace);
+ }
+ }
+ }
}
- // Rewrite any existing namespaces specified in the searchSpec, or add namespaces to
- // limit the search to this database instance.
- if (searchSpecBuilder.getNamespaceFiltersCount() > 0) {
- for (int i = 0; i < searchSpecBuilder.getNamespaceFiltersCount(); i++) {
- String qualifiedNamespace = getDatabasePrefix(databaseName)
- + searchSpecBuilder.getNamespaceFilters(i);
- searchSpecBuilder.setNamespaceFilters(i, qualifiedNamespace);
- }
- } else {
- searchSpecBuilder.addAllNamespaceFilters(existingNamespaces);
- }
return true;
}
@@ -681,12 +700,13 @@
@NonNull
private String getDatabasePrefix(@NonNull String databaseName) {
- return databaseName + "/";
+ // TODO(b/170370381): Reconsider the way we separate database names for security reasons.
+ return databaseName + DATABASE_DELIMITER;
}
@NonNull
private String getDatabaseName(@NonNull String prefixedValue) throws AppSearchException {
- int delimiterIndex = prefixedValue.indexOf('/');
+ int delimiterIndex = prefixedValue.indexOf(DATABASE_DELIMITER);
if (delimiterIndex == -1) {
throw new AppSearchException(AppSearchResult.RESULT_UNKNOWN_ERROR,
"The databaseName prefixed value doesn't contains a valid database name.");
@@ -694,17 +714,6 @@
return prefixedValue.substring(0, delimiterIndex);
}
- @NonNull
- private static String removePrefix(@NonNull String prefix, @NonNull String inputType,
- @NonNull String input) {
- if (!input.startsWith(prefix)) {
- throw new IllegalStateException(
- "Unexpected " + inputType + " \"" + input
- + "\" does not start with \"" + prefix + "\"");
- }
- return input.substring(prefix.length());
- }
-
@GuardedBy("mReadWriteLock")
private void addToMap(Map<String, Set<String>> map, String databaseName, String prefixedValue) {
Set<String> values = map.get(databaseName);
@@ -781,17 +790,17 @@
}
}
- /** Removes the rewritten schema types from any result documents.*/
- private SearchResultProto rewriteSearchResultProto(@NonNull String databaseName,
+ /** Remove the rewritten schema types from any result documents. */
+ private SearchResultProto rewriteSearchResultProto(
@NonNull SearchResultProto searchResultProto) {
SearchResultProto.Builder searchResultsBuilder = searchResultProto.toBuilder();
+
for (int i = 0; i < searchResultsBuilder.getResultsCount(); i++) {
if (searchResultProto.getResults(i).hasDocument()) {
SearchResultProto.ResultProto.Builder resultBuilder =
searchResultsBuilder.getResults(i).toBuilder();
DocumentProto.Builder documentBuilder = resultBuilder.getDocument().toBuilder();
- rewriteDocumentTypes(
- getDatabasePrefix(databaseName), documentBuilder, /*add=*/false);
+ removeDatabasesFromDocument(documentBuilder);
resultBuilder.setDocument(documentBuilder);
searchResultsBuilder.setResults(i, resultBuilder);
}
diff --git a/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/LocalBackend.java b/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/LocalBackend.java
index 3c9b97b..28f4eb8 100644
--- a/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/LocalBackend.java
+++ b/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/LocalBackend.java
@@ -151,6 +151,16 @@
@Override
@NonNull
+ public BackendSearchResults globalQuery(
+ @NonNull String queryExpression,
+ @NonNull SearchSpec searchSpec) {
+ Preconditions.checkNotNull(queryExpression);
+ Preconditions.checkNotNull(searchSpec);
+ return new GlobalSearchResultsImpl(mSyncImpl.globalQuery(queryExpression, searchSpec));
+ }
+
+ @Override
+ @NonNull
public ListenableFuture<AppSearchBatchResult<String, Void>> removeByUri(
@NonNull String databaseName,
@NonNull RemoveByUriRequest request) {
@@ -161,27 +171,13 @@
@Override
@NonNull
- public ListenableFuture<AppSearchBatchResult<String, Void>> removeByType(
- @NonNull String databaseName, @NonNull List<String> schemaTypes) {
+ public ListenableFuture<AppSearchResult<Void>> removeByQuery(@NonNull String databaseName,
+ @NonNull String queryExpression,
+ @NonNull SearchSpec searchSpec) {
Preconditions.checkNotNull(databaseName);
- Preconditions.checkNotNull(schemaTypes);
- return execute(() -> mSyncImpl.removeByType(databaseName, schemaTypes));
- }
-
- @Override
- @NonNull
- public ListenableFuture<AppSearchBatchResult<String, Void>> removeByNamespace(
- @NonNull String databaseName, @NonNull List<String> namespaces) {
- Preconditions.checkNotNull(databaseName);
- Preconditions.checkNotNull(namespaces);
- return execute(() -> mSyncImpl.removeByNamespace(databaseName, namespaces));
- }
-
- @Override
- @NonNull
- public ListenableFuture<AppSearchResult<Void>> removeAll(@NonNull String databaseName) {
- Preconditions.checkNotNull(databaseName);
- return execute(() -> mSyncImpl.removeAll(databaseName));
+ Preconditions.checkNotNull(queryExpression);
+ Preconditions.checkNotNull(searchSpec);
+ return execute(() -> mSyncImpl.removeByQuery(databaseName, queryExpression, searchSpec));
}
@VisibleForTesting
@@ -230,4 +226,29 @@
});
}
}
+
+ private class GlobalSearchResultsImpl implements BackendSearchResults {
+ private final LocalBackendSyncImpl.GlobalSearchResultsImpl mSyncResults;
+
+ GlobalSearchResultsImpl(@NonNull LocalBackendSyncImpl.GlobalSearchResultsImpl syncResults) {
+ mSyncResults = Preconditions.checkNotNull(syncResults);
+ }
+
+ @Override
+ @NonNull
+ public ListenableFuture<AppSearchResult<List<SearchResults.Result>>> getNextPage() {
+ return execute(mSyncResults::getNextPage);
+ }
+
+ @Override
+ @SuppressWarnings("FutureReturnValueIgnored")
+ public void close() {
+ // Close the SearchResult in the backend thread. No future is needed here since the
+ // method is void.
+ execute(() -> {
+ mSyncResults.close();
+ return null;
+ });
+ }
+ }
}
diff --git a/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/LocalBackendSyncImpl.java b/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/LocalBackendSyncImpl.java
index c6cc092..dcb3a3d 100644
--- a/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/LocalBackendSyncImpl.java
+++ b/appsearch/local-backend/src/main/java/androidx/appsearch/localbackend/LocalBackendSyncImpl.java
@@ -159,6 +159,18 @@
}
@NonNull
+ public GlobalSearchResultsImpl globalQuery(
+ @NonNull String queryExpression,
+ @NonNull SearchSpec searchSpec) {
+ Preconditions.checkNotNull(queryExpression);
+ Preconditions.checkNotNull(searchSpec);
+ // TODO(169883602): Consider moving database management into LocalBackendSyncImpl, leaving
+ // AppSearchImpl as a thin wrapper around. This would let us reuse SearchResultsImpl and
+ // minimize the duplication of APIs in AppSearchImpl.
+ return new GlobalSearchResultsImpl(queryExpression, searchSpec);
+ }
+
+ @NonNull
public AppSearchBatchResult<String, Void> removeByUri(
@NonNull String databaseName,
@NonNull RemoveByUriRequest request) {
@@ -178,48 +190,18 @@
}
@NonNull
- public AppSearchBatchResult<String, Void> removeByType(
- @NonNull String databaseName, @NonNull List<String> schemaTypes) {
+ public AppSearchResult<Void> removeByQuery(@NonNull String databaseName,
+ @NonNull String queryExpression,
+ @NonNull SearchSpec searchSpec) {
Preconditions.checkNotNull(databaseName);
- Preconditions.checkNotNull(schemaTypes);
- AppSearchBatchResult.Builder<String, Void> resultBuilder =
- new AppSearchBatchResult.Builder<>();
- for (int i = 0; i < schemaTypes.size(); i++) {
- String schemaType = schemaTypes.get(i);
- try {
- mAppSearchImpl.removeByType(databaseName, schemaType);
- resultBuilder.setSuccess(schemaType, /*result=*/ null);
- } catch (Throwable t) {
- resultBuilder.setResult(schemaType, throwableToFailedResult(t));
- }
- }
- return resultBuilder.build();
- }
-
- @NonNull
- public AppSearchBatchResult<String, Void> removeByNamespace(
- @NonNull String databaseName, @NonNull List<String> namespaces) {
- Preconditions.checkNotNull(databaseName);
- Preconditions.checkNotNull(namespaces);
- AppSearchBatchResult.Builder<String, Void> resultBuilder =
- new AppSearchBatchResult.Builder<>();
- for (int i = 0; i < namespaces.size(); i++) {
- String namespace = namespaces.get(i);
- try {
- mAppSearchImpl.removeByNamespace(databaseName, namespace);
- resultBuilder.setSuccess(namespace, /*result=*/ null);
- } catch (Throwable t) {
- resultBuilder.setResult(namespace, throwableToFailedResult(t));
- }
- }
- return resultBuilder.build();
- }
-
- @NonNull
- public AppSearchResult<Void> removeAll(@NonNull String databaseName) {
- Preconditions.checkNotNull(databaseName);
+ Preconditions.checkNotNull(queryExpression);
+ Preconditions.checkNotNull(searchSpec);
+ SearchSpecProto searchSpecProto =
+ SearchSpecToProtoConverter.toSearchSpecProto(searchSpec);
+ searchSpecProto = searchSpecProto.toBuilder()
+ .setQuery(queryExpression).build();
try {
- mAppSearchImpl.removeAll(databaseName);
+ mAppSearchImpl.removeByQuery(databaseName, searchSpecProto);
return AppSearchResult.newSuccessfulResult(null);
} catch (Throwable t) {
return throwableToFailedResult(t);
@@ -297,7 +279,57 @@
return AppSearchResult.newSuccessfulResult(
SearchResultToProtoConverter.convert(searchResultProto));
} else {
- SearchResultProto searchResultProto = mAppSearchImpl.getNextPage(mDatabaseName,
+ SearchResultProto searchResultProto = mAppSearchImpl.getNextPage(
+ mNextPageToken);
+ mNextPageToken = searchResultProto.getNextPageToken();
+ return AppSearchResult.newSuccessfulResult(
+ SearchResultToProtoConverter.convert(searchResultProto));
+ }
+ } catch (Throwable t) {
+ return throwableToFailedResult(t);
+ }
+ }
+
+ @Override
+ public void close() {
+ mAppSearchImpl.invalidateNextPageToken(mNextPageToken);
+ }
+ }
+
+ /** Presents global search results using a bundled version of the search native library. */
+ class GlobalSearchResultsImpl implements Closeable {
+ private long mNextPageToken;
+ private final SearchSpec mSearchSpec;
+ private final String mQueryExpression;
+ private boolean mIsFirstLoad = true;
+
+ GlobalSearchResultsImpl(
+ @NonNull String queryExpression,
+ @NonNull SearchSpec searchSpec) {
+ Preconditions.checkNotNull(queryExpression);
+ Preconditions.checkNotNull(searchSpec);
+ mQueryExpression = queryExpression;
+ mSearchSpec = searchSpec;
+ }
+
+ @NonNull
+ public AppSearchResult<List<SearchResults.Result>> getNextPage() {
+ try {
+ if (mIsFirstLoad) {
+ mIsFirstLoad = false;
+ SearchSpecProto searchSpecProto =
+ SearchSpecToProtoConverter.toSearchSpecProto(mSearchSpec);
+ searchSpecProto = searchSpecProto.toBuilder()
+ .setQuery(mQueryExpression).build();
+ SearchResultProto searchResultProto = mAppSearchImpl.globalQuery(
+ searchSpecProto,
+ SearchSpecToProtoConverter.toResultSpecProto(mSearchSpec),
+ SearchSpecToProtoConverter.toScoringSpecProto(mSearchSpec));
+ mNextPageToken = searchResultProto.getNextPageToken();
+ return AppSearchResult.newSuccessfulResult(
+ SearchResultToProtoConverter.convert(searchResultProto));
+ } else {
+ SearchResultProto searchResultProto = mAppSearchImpl.getNextPage(
mNextPageToken);
mNextPageToken = searchResultProto.getNextPageToken();
return AppSearchResult.newSuccessfulResult(
diff --git a/arch/core-common/api/restricted_current.ignore b/arch/core-common/api/restricted_current.ignore
new file mode 100644
index 0000000..2afd054
--- /dev/null
+++ b/arch/core-common/api/restricted_current.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedMethod: androidx.arch.core.internal.SafeIterableMap#put(K, V):
+ Removed method androidx.arch.core.internal.SafeIterableMap.put(K,V)
diff --git a/arch/core-common/api/restricted_current.txt b/arch/core-common/api/restricted_current.txt
index ad7b39c..b565cc8 100644
--- a/arch/core-common/api/restricted_current.txt
+++ b/arch/core-common/api/restricted_current.txt
@@ -15,12 +15,16 @@
method public java.util.Iterator<java.util.Map.Entry<K!,V!>!> iterator();
method public androidx.arch.core.internal.SafeIterableMap.IteratorWithAdditions! iteratorWithAdditions();
method public java.util.Map.Entry<K!,V!>! newest();
- method protected androidx.arch.core.internal.SafeIterableMap.Entry<K!,V!>! put(K, V);
method public V! putIfAbsent(K, V);
method public V! remove(K);
method public int size();
}
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class SafeIterableMap.IteratorWithAdditions implements java.util.Iterator<java.util.Map.Entry<K,V>> {
+ method public boolean hasNext();
+ method public java.util.Map.Entry<K!,V!>! next();
+ }
+
}
package androidx.arch.core.util {
diff --git a/arch/core-common/src/main/java/androidx/arch/core/internal/SafeIterableMap.java b/arch/core-common/src/main/java/androidx/arch/core/internal/SafeIterableMap.java
index a7bd54f..aedcd9f 100644
--- a/arch/core-common/src/main/java/androidx/arch/core/internal/SafeIterableMap.java
+++ b/arch/core-common/src/main/java/androidx/arch/core/internal/SafeIterableMap.java
@@ -71,7 +71,7 @@
return null;
}
- protected Entry<K, V> put(@NonNull K key, @NonNull V v) {
+ Entry<K, V> put(@NonNull K key, @NonNull V v) {
Entry<K, V> newEntry = new Entry<>(key, v);
mSize++;
if (mEnd == null) {
@@ -226,8 +226,8 @@
return builder.toString();
}
- private abstract static class ListIterator<K, V> implements Iterator<Map.Entry<K, V>>,
- SupportRemove<K, V> {
+ private abstract static class ListIterator<K, V> extends SupportRemove<K, V>
+ implements Iterator<Map.Entry<K, V>> {
Entry<K, V> mExpectedEnd;
Entry<K, V> mNext;
@@ -311,7 +311,12 @@
}
}
- private class IteratorWithAdditions implements Iterator<Map.Entry<K, V>>, SupportRemove<K, V> {
+ /**
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ public class IteratorWithAdditions extends SupportRemove<K, V>
+ implements Iterator<Map.Entry<K, V>> {
private Entry<K, V> mCurrent;
private boolean mBeforeStart = true;
@@ -320,7 +325,7 @@
@SuppressWarnings("ReferenceEquality")
@Override
- public void supportRemove(@NonNull Entry<K, V> entry) {
+ void supportRemove(@NonNull Entry<K, V> entry) {
if (entry == mCurrent) {
mCurrent = mCurrent.mPrevious;
mBeforeStart = mCurrent == null;
@@ -347,8 +352,8 @@
}
}
- interface SupportRemove<K, V> {
- void supportRemove(@NonNull Entry<K, V> entry);
+ abstract static class SupportRemove<K, V> {
+ abstract void supportRemove(@NonNull Entry<K, V> entry);
}
static class Entry<K, V> implements Map.Entry<K, V> {
diff --git a/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java b/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
index e729d20..592bd56 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
@@ -458,12 +458,36 @@
}
mViewModel.setCanceledFrom(CANCELED_FROM_INTERNAL);
+ authenticateWithFingerprint(fingerprintManagerCompat, context);
+ }
+ }
+
+ /**
+ * Requests authentication with fingerprint.
+ *
+ * @param fingerprintManagerCompat FingerprintManagerCompat that coordinates access to the
+ * fingerprint hardware.
+ * @param context The application or activity context.
+ */
+ @SuppressWarnings("deprecation")
+ @VisibleForTesting
+ void authenticateWithFingerprint(
+ @NonNull androidx.core.hardware.fingerprint.FingerprintManagerCompat
+ fingerprintManagerCompat,
+ @NonNull Context context) {
+ try {
fingerprintManagerCompat.authenticate(
CryptoObjectUtils.wrapForFingerprintManager(mViewModel.getCryptoObject()),
0 /* flags */,
mViewModel.getCancellationSignalProvider().getFingerprintCancellationSignal(),
mViewModel.getAuthenticationCallbackProvider().getFingerprintCallback(),
- null /* handler */);
+ null /* handler */
+ );
+ } catch (NullPointerException e) {
+ Log.e(TAG, "NullPointerException in fingerprintManagerCompat authenticate call", e);
+ sendErrorAndDismiss(BiometricPrompt.ERROR_HW_UNAVAILABLE,
+ ErrorUtils.getFingerprintErrorString(context,
+ BiometricPrompt.ERROR_HW_UNAVAILABLE));
}
}
diff --git a/biometric/biometric/src/test/java/androidx/biometric/BiometricFragmentTest.java b/biometric/biometric/src/test/java/androidx/biometric/BiometricFragmentTest.java
index 2349ae2..db249dc 100644
--- a/biometric/biometric/src/test/java/androidx/biometric/BiometricFragmentTest.java
+++ b/biometric/biometric/src/test/java/androidx/biometric/BiometricFragmentTest.java
@@ -19,14 +19,21 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.os.Build;
import android.os.Handler;
import androidx.annotation.NonNull;
+import androidx.core.os.CancellationSignal;
import androidx.test.filters.LargeTest;
import org.junit.Before;
@@ -57,6 +64,9 @@
@Mock private BiometricPrompt.AuthenticationCallback mAuthenticationCallback;
@Mock private Handler mHandler;
+ @Mock private androidx.core.hardware.fingerprint.FingerprintManagerCompat
+ mFingerprintManagerCompat;
+ @Mock private Context mContext;
@Captor private ArgumentCaptor<BiometricPrompt.AuthenticationResult> mResultCaptor;
@@ -123,6 +133,36 @@
null /* crypto */);
}
+ @Test
+ public void testAuthenticateWithFingerprint_DoesShowErrorAndDismiss_WhenNPEThrown() {
+ mViewModel.setClientExecutor(EXECUTOR);
+ mViewModel.setClientCallback(mAuthenticationCallback);
+ mViewModel.setAwaitingResult(true);
+
+ final int errMsgId = BiometricPrompt.ERROR_HW_UNAVAILABLE;
+ final String errString = "test string";
+
+ doThrow(NullPointerException.class).when(mFingerprintManagerCompat).authenticate(
+ nullable(androidx.core.hardware.fingerprint.FingerprintManagerCompat
+ .CryptoObject.class),
+ anyInt(),
+ any(CancellationSignal.class),
+ any(androidx.core.hardware.fingerprint.FingerprintManagerCompat
+ .AuthenticationCallback.class),
+ nullable(Handler.class)
+ );
+
+ // Configure mock context to return test string
+ when(mContext.getString(anyInt())).thenReturn(errString);
+
+ // Have authentication via BiometricPrompt run, and have it invoke the mFingerprintCompat
+ // authenticate call
+ mFragment.authenticateWithFingerprint(mFingerprintManagerCompat, mContext);
+
+ // Verify that authentication should fail and we should receive onError
+ verify(mAuthenticationCallback).onAuthenticationError(eq(errMsgId), anyString());
+ }
+
private static void prepareMockHandler(Handler mockHandler) {
// Immediately invoke any scheduled callbacks.
when(mockHandler.postDelayed(any(Runnable.class), anyLong()))
diff --git a/biometric/integration-tests/testapp/src/main/java/androidx/biometric/integration/testapp/BiometricTestActivity.kt b/biometric/integration-tests/testapp/src/main/java/androidx/biometric/integration/testapp/BiometricTestActivity.kt
index 240d41c..9797c43 100644
--- a/biometric/integration-tests/testapp/src/main/java/androidx/biometric/integration/testapp/BiometricTestActivity.kt
+++ b/biometric/integration-tests/testapp/src/main/java/androidx/biometric/integration/testapp/BiometricTestActivity.kt
@@ -300,9 +300,11 @@
*/
@RequiresApi(Build.VERSION_CODES.M)
private fun getCipher(): Cipher {
- return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" +
+ return Cipher.getInstance(
+ KeyProperties.KEY_ALGORITHM_AES + "/" +
KeyProperties.BLOCK_MODE_CBC + "/" +
- KeyProperties.ENCRYPTION_PADDING_PKCS7)
+ KeyProperties.ENCRYPTION_PADDING_PKCS7
+ )
}
/**
diff --git a/browser/browser/src/androidTest/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionPoolTest.java b/browser/browser/src/androidTest/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionPoolTest.java
index e465ab3..eb2f23a 100644
--- a/browser/browser/src/androidTest/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionPoolTest.java
+++ b/browser/browser/src/androidTest/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionPoolTest.java
@@ -36,6 +36,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -118,6 +119,7 @@
}
}
+ @Ignore("Test disabled due to flakiness, see b/153851530")
@Test
public void testMultipleExecutions() {
final AtomicInteger count = new AtomicInteger();
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXUiPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXUiPlugin.kt
index 5d8eff3..10018d8 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXUiPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXUiPlugin.kt
@@ -48,9 +48,12 @@
// TODO: figure out how to apply this to multiplatform modules
project.dependencies.add(
"lintChecks",
- project.dependencies.project(mapOf(
- "path" to ":compose:internal-lint-checks", "configuration" to "shadow"
- ))
+ project.dependencies.project(
+ mapOf(
+ "path" to ":compose:internal-lint-checks",
+ "configuration" to "shadow"
+ )
+ )
)
library.lintOptions.apply {
@@ -97,8 +100,10 @@
// Android Studio on versions >= 4.0canary8)
libraryExtension.apply {
sourceSets.findByName("main")?.apply {
- java.srcDirs("src/commonMain/kotlin", "src/jvmMain/kotlin",
- "src/androidMain/kotlin")
+ java.srcDirs(
+ "src/commonMain/kotlin", "src/jvmMain/kotlin",
+ "src/androidMain/kotlin"
+ )
res.srcDirs("src/androidMain/res")
}
sourceSets.findByName("test")?.apply {
diff --git a/buildSrc/src/main/kotlin/androidx/build/Ktlint.kt b/buildSrc/src/main/kotlin/androidx/build/Ktlint.kt
index 8294386..ee3d7c94 100644
--- a/buildSrc/src/main/kotlin/androidx/build/Ktlint.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/Ktlint.kt
@@ -26,7 +26,7 @@
private fun Project.getKtlintConfiguration(): Configuration {
return configurations.findByName("ktlint") ?: configurations.create("ktlint") {
- val dependency = dependencies.create("com.pinterest:ktlint:0.36.0")
+ val dependency = dependencies.create("com.pinterest:ktlint:0.39.0")
it.dependencies.add(dependency)
}
}
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryType.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryType.kt
index 81c129f..c4420cd 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryType.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryType.kt
@@ -57,12 +57,31 @@
val checkApi: RunApiTasks = RunApiTasks.No("Unknown Library Type"),
val compilationTarget: CompilationTarget = CompilationTarget.DEVICE
) {
- PUBLISHED_LIBRARY(Publish.SNAPSHOT_AND_RELEASE, true, true, RunApiTasks.Yes()),
- SAMPLES(Publish.SNAPSHOT_AND_RELEASE, true, false, RunApiTasks.No("Sample Library")),
- LINT(Publish.NONE, false, false, RunApiTasks.No("Lint Library"), CompilationTarget.HOST),
+ PUBLISHED_LIBRARY(
+ publish = Publish.SNAPSHOT_AND_RELEASE,
+ sourceJars = true,
+ generateDocs = true,
+ checkApi = RunApiTasks.Yes()
+ ),
+ SAMPLES(
+ publish = Publish.SNAPSHOT_AND_RELEASE,
+ sourceJars = true,
+ generateDocs = true,
+ checkApi = RunApiTasks.No("Sample Library")
+ ),
+ LINT(
+ publish = Publish.NONE,
+ sourceJars = false,
+ generateDocs = false,
+ checkApi = RunApiTasks.No("Lint Library"),
+ compilationTarget = CompilationTarget.HOST
+ ),
ANNOTATION_PROCESSOR(
- Publish.SNAPSHOT_AND_RELEASE, false, true,
- RunApiTasks.No("Annotation Processor"), CompilationTarget.HOST
+ publish = Publish.SNAPSHOT_AND_RELEASE,
+ sourceJars = false,
+ generateDocs = true,
+ checkApi = RunApiTasks.No("Annotation Processor"),
+ compilationTarget = CompilationTarget.HOST
),
UNSET()
}
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index b1a8e87..7e51a50 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -23,7 +23,7 @@
val ACTIVITY = Version("1.2.0-beta01")
val ADS_IDENTIFIER = Version("1.0.0-alpha04")
val ANNOTATION = Version("1.2.0-alpha02")
- val ANNOTATION_EXPERIMENTAL = Version("1.1.0-alpha01")
+ val ANNOTATION_EXPERIMENTAL = Version("1.1.0-alpha02")
val APPCOMPAT = Version("1.3.0-alpha03")
val APPSEARCH = Version("1.0.0-alpha01")
val ARCH_CORE = Version("2.2.0-alpha01")
@@ -43,8 +43,8 @@
val CARDVIEW = Version("1.1.0-alpha01")
val COLLECTION = Version("1.2.0-alpha01")
val CONTENTPAGER = Version("1.1.0-alpha01")
- val COMPOSE = Version("1.0.0-alpha05")
- val COMPOSE_NAVIGATION = Version("0.1.0-dev01")
+ val COMPOSE = Version("1.0.0-alpha06")
+ val COMPOSE_NAVIGATION = Version("1.0.0-alpha01")
val CONTENTACCESS = Version("1.0.0-alpha01")
val COORDINATORLAYOUT = Version("1.2.0-alpha01")
val CORE = Version("1.5.0-alpha05")
@@ -121,7 +121,6 @@
val WEAR = Version("1.2.0-alpha01")
val WEAR_COMPLICATIONS = Version("1.0.0-alpha01")
val WEAR_INPUT = Version("1.0.0-beta01")
- val WEAR_INPUT_TESTING = Version("1.0.0-alpha01")
val WEAR_WATCHFACE = Version("1.0.0-alpha01")
val WEAR_WATCHFACE_DATA = Version("1.0.0-alpha01")
val WEAR_WATCHFACE_STYLE = Version("1.0.0-alpha01")
diff --git a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
index 649fe6d..5b75433 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
@@ -93,11 +93,10 @@
fatal("VisibleForTests")
- // Workaround for integration branch using a newer AGP with a check that we don't want.
- // This will be removed when we update to that AGP (b/160261355).
- if (com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.startsWith("4.2.")) {
- disable("KtxExtensionAvailable")
- }
+ // Disable dependency checks that suggest to change them. We want libraries to be
+ // intentional with their dependency version bumps.
+ disable("KtxExtensionAvailable")
+ disable("GradleDependency")
if (extension.compilationTarget != CompilationTarget.HOST) {
fatal("Assert")
diff --git a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
index 92b7340..9bbecc3 100644
--- a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
@@ -38,7 +38,7 @@
prebuilts(LibraryGroups.APPCOMPAT, "1.3.0-alpha02")
prebuilts(LibraryGroups.ARCH_CORE, "2.1.0")
prebuilts(LibraryGroups.ASYNCLAYOUTINFLATER, "1.0.0")
- prebuilts(LibraryGroups.AUTOFILL, "1.1.0-alpha02")
+ prebuilts(LibraryGroups.AUTOFILL, "1.1.0-beta01")
ignore(LibraryGroups.BENCHMARK.group, "benchmark-gradle-plugin")
ignore(LibraryGroups.BENCHMARK.group, "benchmark-macro")
prebuilts(LibraryGroups.BENCHMARK, "1.1.0-alpha01")
@@ -50,10 +50,10 @@
ignore(LibraryGroups.CAMERA.group, "camera-extensions-stub")
ignore(LibraryGroups.CAMERA.group, "camera-testlib-extensions")
ignore(LibraryGroups.CAMERA.group, "camera-video")
- prebuilts(LibraryGroups.CAMERA, "camera-view", "1.0.0-alpha17")
- prebuilts(LibraryGroups.CAMERA, "camera-extensions", "1.0.0-alpha17")
+ prebuilts(LibraryGroups.CAMERA, "camera-view", "1.0.0-alpha18")
+ prebuilts(LibraryGroups.CAMERA, "camera-extensions", "1.0.0-alpha18")
.addStubs("camera/camera-extensions-stub/camera-extensions-stub.jar")
- prebuilts(LibraryGroups.CAMERA, "1.0.0-beta10")
+ prebuilts(LibraryGroups.CAMERA, "1.0.0-beta11")
prebuilts(LibraryGroups.CARDVIEW, "1.0.0")
prebuilts(LibraryGroups.COLLECTION, "1.1.0")
prebuilts(LibraryGroups.CONCURRENT, "1.1.0")
@@ -69,14 +69,14 @@
prebuilts(LibraryGroups.CUSTOMVIEW, "1.1.0")
ignore(LibraryGroups.DATASTORE.group, "datastore-preferences-proto")
ignore(LibraryGroups.DATASTORE.group, "datastore-proto")
- prebuilts(LibraryGroups.DATASTORE, "1.0.0-alpha01")
+ prebuilts(LibraryGroups.DATASTORE, "1.0.0-alpha02")
prebuilts(LibraryGroups.DOCUMENTFILE, "1.0.0")
prebuilts(LibraryGroups.DRAWERLAYOUT, "1.1.1")
prebuilts(LibraryGroups.DYNAMICANIMATION, "dynamicanimation-ktx", "1.0.0-alpha03")
prebuilts(LibraryGroups.DYNAMICANIMATION, "1.1.0-alpha02")
prebuilts(LibraryGroups.EMOJI, "1.2.0-alpha01")
- prebuilts(LibraryGroups.ENTERPRISE, "1.1.0-alpha02")
- prebuilts(LibraryGroups.EXIFINTERFACE, "1.3.0")
+ prebuilts(LibraryGroups.ENTERPRISE, "1.1.0-beta01")
+ prebuilts(LibraryGroups.EXIFINTERFACE, "1.3.1")
ignore(LibraryGroups.FRAGMENT.group, "fragment-lint")
ignore(LibraryGroups.FRAGMENT.group, "fragment-testing-lint")
ignore(LibraryGroups.FRAGMENT.group, "fragment-truth")
@@ -101,11 +101,11 @@
ignore(LibraryGroups.MEDIA2.group, "media2-exoplayer")
prebuilts(LibraryGroups.MEDIA2, "media2-widget", "1.1.0-beta01")
prebuilts(LibraryGroups.MEDIA2, "1.1.0-beta01")
- prebuilts(LibraryGroups.MEDIAROUTER, "1.2.0-rc02")
+ prebuilts(LibraryGroups.MEDIAROUTER, "1.2.0")
ignore(LibraryGroups.NAVIGATION.group, "navigation-runtime-truth")
ignore(LibraryGroups.NAVIGATION.group, "navigation-safe-args-generator")
ignore(LibraryGroups.NAVIGATION.group, "navigation-safe-args-gradle-plugin")
- prebuilts(LibraryGroups.NAVIGATION, "2.3.0")
+ prebuilts(LibraryGroups.NAVIGATION, "2.3.1")
// TODO: un-ignore this once we have a prebuilt for paging samples
ignore(LibraryGroups.PAGING.group, "paging-samples")
prebuilts(LibraryGroups.PAGING, "3.0.0-alpha07")
@@ -125,13 +125,13 @@
ignore(LibraryGroups.ROOM.group, "room-compiler-processing")
// TODO: Remove during release phase of rxjava3 artifact
ignore(LibraryGroups.ROOM.group, "room-rxjava3")
- prebuilts(LibraryGroups.ROOM, "2.3.0-alpha02")
+ prebuilts(LibraryGroups.ROOM, "2.3.0-alpha03")
prebuilts(LibraryGroups.SAVEDSTATE, "1.1.0-beta01")
// TODO: Remove this ignore once androidx.security:security-biometric:1.0.0-alpha01 is released
ignore(LibraryGroups.SECURITY.group, "security-biometric")
prebuilts(LibraryGroups.SECURITY, "security-identity-credential", "1.0.0-alpha01")
prebuilts(LibraryGroups.SECURITY, "1.1.0-alpha02")
- prebuilts(LibraryGroups.SHARETARGET, "1.0.0")
+ prebuilts(LibraryGroups.SHARETARGET, "1.1.0-beta01")
prebuilts(LibraryGroups.SLICE, "slice-builders", "1.1.0-alpha01")
prebuilts(LibraryGroups.SLICE, "slice-builders-ktx", "1.0.0-alpha07")
prebuilts(LibraryGroups.SLICE, "slice-core", "1.1.0-alpha01")
@@ -157,17 +157,17 @@
prebuilts(LibraryGroups.VIEWPAGER, "1.0.0")
prebuilts(LibraryGroups.VIEWPAGER2, "1.1.0-alpha01")
prebuilts(LibraryGroups.WEAR, "wear-input", "1.0.0-alpha01")
- prebuilts(LibraryGroups.WEAR, "wear", "1.1.0-rc03")
+ prebuilts(LibraryGroups.WEAR, "wear", "1.1.0")
.addStubs("wear/wear_stubs/com.google.android.wearable-stubs.jar")
ignore(LibraryGroups.WEAR.group, "wear-input-testing")
- prebuilts(LibraryGroups.WEBKIT, "1.4.0-alpha01")
+ prebuilts(LibraryGroups.WEBKIT, "1.4.0-beta01")
ignore(LibraryGroups.WINDOW.group, "window-sidecar")
prebuilts(LibraryGroups.WINDOW, "1.0.0-alpha01")
.addStubs("window/stubs/window-sidecar-release-0.1.0-alpha01.aar")
ignore(LibraryGroups.WORK.group, "work-inspection")
ignore(LibraryGroups.WORK.group, "work-gcm")
ignore(LibraryGroups.WORK.group, "work-runtime-lint")
- prebuilts(LibraryGroups.WORK, "2.5.0-alpha02")
+ prebuilts(LibraryGroups.WORK, "2.5.0-alpha03")
default(Ignore)
}
diff --git a/buildSrc/src/main/kotlin/androidx/build/SdkResourceGenerator.kt b/buildSrc/src/main/kotlin/androidx/build/SdkResourceGenerator.kt
index 28c7248..f312785 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SdkResourceGenerator.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SdkResourceGenerator.kt
@@ -53,7 +53,7 @@
val agpDependency: String = AGP_LATEST
@get:Input
- val navigationCommon: String = "androidx.navigation:navigation-common:2.3.0"
+ val navigationCommon: String = "androidx.navigation:navigation-common:2.0.0"
@get:Input
val kotlinStdlib: String = KOTLIN_STDLIB
diff --git a/busytown/androidx-studio-integration.sh b/busytown/androidx-studio-integration.sh
index b67d759..f0ee1c2 100755
--- a/busytown/androidx-studio-integration.sh
+++ b/busytown/androidx-studio-integration.sh
@@ -38,8 +38,8 @@
LOG_PROCESSOR="$SCRIPT_DIR/../development/build_log_processor.sh"
properties="-Pandroidx.summarizeStderr --no-daemon -Pandroidx.allWarningsAsErrors"
"$LOG_PROCESSOR" $gw $properties -p frameworks/support listTaskOutputs && \
- "$LOG_PROCESSOR" $gw $properties -p frameworks/support bOS --stacktrace -PverifyUpToDate && \
- DIST_SUBDIR="/ui" "$LOG_PROCESSOR" $gw $properties -p frameworks/support/ui bOS --stacktrace -PverifyUpToDate
+ "$LOG_PROCESSOR" $gw $properties -p frameworks/support bOS -x lintDebug --stacktrace -PverifyUpToDate && \
+ DIST_SUBDIR="/ui" "$LOG_PROCESSOR" $gw $properties -p frameworks/support/ui bOS -x lintDebug --stacktrace -PverifyUpToDate
}
function exportTransformsDir() {
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/CameraPipeConfig.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/CameraPipeConfig.kt
index 8f0915c..5b245d2 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/CameraPipeConfig.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/CameraPipeConfig.kt
@@ -16,9 +16,9 @@
package androidx.camera.camera2.pipe.integration
import androidx.camera.core.CameraXConfig
-import androidx.camera.core.impl.ExtendableUseCaseConfigFactory
import androidx.camera.camera2.pipe.integration.impl.CameraPipeCameraFactory
import androidx.camera.camera2.pipe.integration.impl.CameraPipeDeviceSurfaceManager
+import androidx.camera.camera2.pipe.integration.impl.CameraPipeUseCaseFactory
/**
* Convenience class for generating a pre-populated CameraPipe [CameraXConfig].
@@ -31,7 +31,7 @@
return CameraXConfig.Builder()
.setCameraFactoryProvider(::CameraPipeCameraFactory)
.setDeviceSurfaceManagerProvider(::CameraPipeDeviceSurfaceManager)
- .setUseCaseConfigFactoryProvider { ExtendableUseCaseConfigFactory() }
+ .setUseCaseConfigFactoryProvider(::CameraPipeUseCaseFactory)
.build()
}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraPipeDeviceSurfaceManager.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraPipeDeviceSurfaceManager.kt
index 72f6da0..4a8807e 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraPipeDeviceSurfaceManager.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraPipeDeviceSurfaceManager.kt
@@ -39,8 +39,9 @@
init {
if (DEBUG) {
Log.d(
- TAG, "Initialized CameraDeviceSurfaceManager [Context: $context, CameraManager:" +
- " $cameraManager, CameraPipe: $cameraPipe]"
+ TAG,
+ "Initialized CameraDeviceSurfaceManager [Context: $context, CameraManager:" +
+ " $cameraManager, CameraPipe: $cameraPipe]"
)
}
}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraPipeUseCaseFactory.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraPipeUseCaseFactory.kt
new file mode 100644
index 0000000..d3823ab
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/CameraPipeUseCaseFactory.kt
@@ -0,0 +1,53 @@
+/*
+ * 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.camera.camera2.pipe.integration.impl
+
+import android.content.Context
+import android.util.Log
+import androidx.camera.camera2.pipe.CameraPipe
+import androidx.camera.core.impl.Config
+import androidx.camera.core.impl.UseCaseConfigFactory
+
+/**
+ * CameraPipe implementation of UseCaseFactory.
+ * @constructor Creates a CameraPipeUseCaseFactory from the provided [Context].
+ */
+class CameraPipeUseCaseFactory(context: Context) : UseCaseConfigFactory {
+ companion object {
+ private const val TAG = "CameraPipeUseCaseFty"
+ private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
+ }
+
+ private val cameraPipe: CameraPipe = CameraPipe(CameraPipe.Config(context))
+
+ init {
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "Initialized CameraPipeUseCaseFactory [Context: $context, CameraPipe: $cameraPipe]"
+ )
+ }
+ }
+
+ /**
+ * Returns the configuration for the given capture type, or `null` if the
+ * configuration cannot be produced.
+ */
+ override fun getConfig(captureType: UseCaseConfigFactory.CaptureType): Config? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/build.gradle b/camera/camera-camera2-pipe/build.gradle
index f61ac0a..01a138c 100644
--- a/camera/camera-camera2-pipe/build.gradle
+++ b/camera/camera-camera2-pipe/build.gradle
@@ -100,7 +100,7 @@
androidx {
name = "Jetpack Camera Pipe"
- publish = Publish.NONE
+ publish = Publish.SNAPSHOT_ONLY
mavenGroup = LibraryGroups.CAMERA
mavenVersion = LibraryVersions.CAMERA_PIPE
inceptionYear = "2020"
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraPipeComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraPipeComponent.kt
index 5fc287e5..924f285 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraPipeComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraPipeComponent.kt
@@ -107,9 +107,11 @@
val cameraHandlerFn =
{
config.cameraThread?.let { Handler(it.looper) }
- ?: Handler(HandlerThread("CXCP-Camera2-H").also {
- it.start()
- }.looper)
+ ?: Handler(
+ HandlerThread("CXCP-Camera2-H").also {
+ it.start()
+ }.looper
+ )
}
val cameraExecutorFn = {
Executors.newFixedThreadPool(1) {
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
index 5e068a5..50460c4 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
@@ -17,7 +17,10 @@
package androidx.camera.camera2;
-import static androidx.camera.testing.CoreAppTestUtil.clearDeviceUI;
+import static androidx.camera.testing.CoreAppTestUtil.ForegroundOccupiedError;
+import static androidx.camera.testing.CoreAppTestUtil.assumeCanTestCameraDisconnect;
+import static androidx.camera.testing.CoreAppTestUtil.assumeCompatibleDevice;
+import static androidx.camera.testing.CoreAppTestUtil.prepareDeviceUI;
import static org.junit.Assume.assumeNotNull;
@@ -27,7 +30,6 @@
import androidx.camera.core.CameraX;
import androidx.camera.testing.CameraUtil;
-import androidx.camera.testing.CoreAppTestUtil;
import androidx.camera.testing.activity.Camera2TestActivity;
import androidx.camera.testing.activity.CameraXTestActivity;
import androidx.test.core.app.ApplicationProvider;
@@ -68,14 +70,15 @@
private CameraXTestActivity mCameraXTestActivity;
@Before
- public void setUp() {
- CoreAppTestUtil.assumeCompatibleDevice();
+ public void setUp() throws ForegroundOccupiedError {
+ assumeCompatibleDevice();
Context context = ApplicationProvider.getApplicationContext();
CameraX.initialize(context, Camera2Config.defaultConfig());
- // Clear the device UI before start each test.
- clearDeviceUI(InstrumentationRegistry.getInstrumentation());
+ // Clear the device UI and check if there is no dialog or lock screen on the top of the
+ // window before start the test.
+ prepareDeviceUI(InstrumentationRegistry.getInstrumentation());
mCameraXTestActivityRule.launchActivity(new Intent());
mCameraXTestActivity = mCameraXTestActivityRule.getActivity();
@@ -93,7 +96,7 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.M) // Known issue, checkout b/147393563.
public void testDisconnect_launchCamera2App() {
// Specific compatibility check for the test.
- CoreAppTestUtil.assumeCanTestCameraDisconnect();
+ assumeCanTestCameraDisconnect();
waitFor(mCameraXTestActivity.mPreviewReady);
String cameraId = mCameraXTestActivity.mCameraId;
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/Camera2Config.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/Camera2Config.java
index c97450d..4b02c8f 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/Camera2Config.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/Camera2Config.java
@@ -20,21 +20,13 @@
import androidx.annotation.RestrictTo;
import androidx.camera.camera2.internal.Camera2CameraFactory;
import androidx.camera.camera2.internal.Camera2DeviceSurfaceManager;
-import androidx.camera.camera2.internal.ImageAnalysisConfigProvider;
-import androidx.camera.camera2.internal.ImageCaptureConfigProvider;
-import androidx.camera.camera2.internal.PreviewConfigProvider;
-import androidx.camera.camera2.internal.VideoCaptureConfigProvider;
+import androidx.camera.camera2.internal.Camera2UseCaseConfigFactory;
import androidx.camera.core.CameraUnavailableException;
import androidx.camera.core.CameraXConfig;
import androidx.camera.core.InitializationException;
import androidx.camera.core.impl.CameraDeviceSurfaceManager;
import androidx.camera.core.impl.CameraFactory;
-import androidx.camera.core.impl.ExtendableUseCaseConfigFactory;
-import androidx.camera.core.impl.ImageAnalysisConfig;
-import androidx.camera.core.impl.ImageCaptureConfig;
-import androidx.camera.core.impl.PreviewConfig;
import androidx.camera.core.impl.UseCaseConfigFactory;
-import androidx.camera.core.impl.VideoCaptureConfig;
/**
* Convenience class for generating a pre-populated Camera2 {@link CameraXConfig}.
@@ -64,18 +56,8 @@
};
// Create default configuration factory
- UseCaseConfigFactory.Provider configFactoryProvider = context -> {
- ExtendableUseCaseConfigFactory factory = new ExtendableUseCaseConfigFactory();
- factory.installDefaultProvider(
- ImageAnalysisConfig.class, new ImageAnalysisConfigProvider(context));
- factory.installDefaultProvider(
- ImageCaptureConfig.class, new ImageCaptureConfigProvider(context));
- factory.installDefaultProvider(
- VideoCaptureConfig.class, new VideoCaptureConfigProvider(context));
- factory.installDefaultProvider(
- PreviewConfig.class, new PreviewConfigProvider(context));
- return factory;
- };
+ UseCaseConfigFactory.Provider configFactoryProvider =
+ context -> new Camera2UseCaseConfigFactory(context);
CameraXConfig.Builder appConfigBuilder =
new CameraXConfig.Builder()
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java
new file mode 100644
index 0000000..5ac81c3
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java
@@ -0,0 +1,123 @@
+/*
+ * 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.camera.camera2.internal;
+
+import static androidx.camera.core.impl.ImageOutputConfig.OPTION_MAX_RESOLUTION;
+import static androidx.camera.core.impl.ImageOutputConfig.OPTION_TARGET_ROTATION;
+import static androidx.camera.core.impl.UseCaseConfig.OPTION_CAPTURE_CONFIG_UNPACKER;
+import static androidx.camera.core.impl.UseCaseConfig.OPTION_DEFAULT_CAPTURE_CONFIG;
+import static androidx.camera.core.impl.UseCaseConfig.OPTION_DEFAULT_SESSION_CONFIG;
+import static androidx.camera.core.impl.UseCaseConfig.OPTION_SESSION_CONFIG_UNPACKER;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.hardware.camera2.CameraDevice;
+import android.util.Size;
+import android.view.WindowManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.camera.core.impl.CaptureConfig;
+import androidx.camera.core.impl.Config;
+import androidx.camera.core.impl.MutableOptionsBundle;
+import androidx.camera.core.impl.OptionsBundle;
+import androidx.camera.core.impl.SessionConfig;
+import androidx.camera.core.impl.UseCaseConfigFactory;
+
+/**
+ * Implementation of UseCaseConfigFactory to provide the default camera2 configurations for use
+ * cases.
+ */
+public final class Camera2UseCaseConfigFactory implements UseCaseConfigFactory {
+ private static final Size MAX_PREVIEW_SIZE = new Size(1920, 1080);
+ final WindowManager mWindowManager;
+
+ public Camera2UseCaseConfigFactory(@NonNull Context context) {
+ mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ }
+
+ /**
+ * Returns the configuration for the given capture type, or <code>null</code> if the
+ * configuration cannot be produced.
+ */
+ @Nullable
+ @Override
+ @SuppressWarnings("deprecation") /* getDefaultDisplay */
+ public Config getConfig(@NonNull CaptureType captureType) {
+ final MutableOptionsBundle mutableConfig = MutableOptionsBundle.create();
+
+ SessionConfig.Builder sessionBuilder = new SessionConfig.Builder();
+ // TODO(b/114762170): Must set to preview here until we allow for multiple template
+ // types
+ sessionBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
+ mutableConfig.insertOption(OPTION_DEFAULT_SESSION_CONFIG, sessionBuilder.build());
+
+ mutableConfig.insertOption(OPTION_SESSION_CONFIG_UNPACKER,
+ Camera2SessionOptionUnpacker.INSTANCE);
+
+ CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
+
+ // Only CAPTURE_TYPE_IMAGE_CAPTURE uses CameraDevice.TEMPLATE_STILL_CAPTURE. Other
+ // capture types all use CameraDevice.TEMPLATE_PREVIEW.
+ switch (captureType) {
+ case IMAGE_CAPTURE:
+ captureBuilder.setTemplateType(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ break;
+ case PREVIEW:
+ case IMAGE_ANALYSIS:
+ case VIDEO_CAPTURE:
+ captureBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
+ break;
+ }
+ mutableConfig.insertOption(OPTION_DEFAULT_CAPTURE_CONFIG, captureBuilder.build());
+
+ // Only CAPTURE_TYPE_IMAGE_CAPTURE has its own ImageCaptureOptionUnpacker. Other
+ // capture types all use the standard Camera2CaptureOptionUnpacker.
+ mutableConfig.insertOption(OPTION_CAPTURE_CONFIG_UNPACKER,
+ captureType == CaptureType.IMAGE_CAPTURE ? ImageCaptureOptionUnpacker.INSTANCE
+ : Camera2CaptureOptionUnpacker.INSTANCE);
+
+ if (captureType == CaptureType.PREVIEW) {
+ mutableConfig.insertOption(OPTION_MAX_RESOLUTION, getPreviewSize());
+ }
+
+ int targetRotation = mWindowManager.getDefaultDisplay().getRotation();
+ mutableConfig.insertOption(OPTION_TARGET_ROTATION, targetRotation);
+
+ return OptionsBundle.from(mutableConfig);
+ }
+
+ /**
+ * Returns the device's screen resolution, or 1080p, whichever is smaller.
+ */
+ @SuppressWarnings("deprecation") /* getDefaultDisplay */
+ private Size getPreviewSize() {
+ Point displaySize = new Point();
+ mWindowManager.getDefaultDisplay().getRealSize(displaySize);
+
+ Size displayViewSize;
+ if (displaySize.x > displaySize.y) {
+ displayViewSize = new Size(displaySize.x, displaySize.y);
+ } else {
+ displayViewSize = new Size(displaySize.y, displaySize.x);
+ }
+
+ return displayViewSize.getWidth() * displayViewSize.getHeight()
+ > MAX_PREVIEW_SIZE.getWidth() * MAX_PREVIEW_SIZE.getHeight() ? MAX_PREVIEW_SIZE
+ : displayViewSize;
+ }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ImageAnalysisConfigProvider.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ImageAnalysisConfigProvider.java
deleted file mode 100644
index 015e79c..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ImageAnalysisConfigProvider.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.camera.camera2.internal;
-
-import android.content.Context;
-import android.hardware.camera2.CameraDevice;
-import android.view.WindowManager;
-
-import androidx.annotation.NonNull;
-import androidx.camera.core.AspectRatio;
-import androidx.camera.core.ImageAnalysis;
-import androidx.camera.core.impl.CaptureConfig;
-import androidx.camera.core.impl.ConfigProvider;
-import androidx.camera.core.impl.ImageAnalysisConfig;
-import androidx.camera.core.impl.SessionConfig;
-
-/**
- * Provides defaults for {@link ImageAnalysisConfig} in the Camera2 implementation.
- */
-public final class ImageAnalysisConfigProvider implements ConfigProvider<ImageAnalysisConfig> {
- private static final String TAG = "ImageAnalysisProvider";
-
- private final WindowManager mWindowManager;
-
- public ImageAnalysisConfigProvider(@NonNull Context context) {
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- }
-
- @Override
- @NonNull
- @SuppressWarnings("deprecation") /* defaultDisplay */
- public ImageAnalysisConfig getConfig() {
- ImageAnalysis.Builder builder = ImageAnalysis.Builder.fromConfig(
- ImageAnalysis.DEFAULT_CONFIG.getConfig());
-
- // SessionConfig containing all intrinsic properties needed for ImageAnalysis
- SessionConfig.Builder sessionBuilder = new SessionConfig.Builder();
- // TODO(b/114762170): Must set to preview here until we allow for multiple template types
- sessionBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
-
- // Add options to UseCaseConfig
- builder.setDefaultSessionConfig(sessionBuilder.build());
- builder.setSessionOptionUnpacker(Camera2SessionOptionUnpacker.INSTANCE);
-
- CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
- captureBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
- builder.setDefaultCaptureConfig(captureBuilder.build());
- builder.setCaptureOptionUnpacker(Camera2CaptureOptionUnpacker.INSTANCE);
- builder.setTargetAspectRatio(AspectRatio.RATIO_4_3);
-
- // TODO(b/160477756): Make UseCase default config providers only provider static configs
- int targetRotation = mWindowManager.getDefaultDisplay().getRotation();
- builder.setTargetRotation(targetRotation);
-
- return builder.getUseCaseConfig();
- }
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ImageCaptureConfigProvider.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ImageCaptureConfigProvider.java
deleted file mode 100644
index c2b2556..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ImageCaptureConfigProvider.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.camera.camera2.internal;
-
-import android.content.Context;
-import android.hardware.camera2.CameraDevice;
-import android.view.WindowManager;
-
-import androidx.annotation.NonNull;
-import androidx.camera.core.AspectRatio;
-import androidx.camera.core.ImageCapture;
-import androidx.camera.core.impl.CaptureConfig;
-import androidx.camera.core.impl.ConfigProvider;
-import androidx.camera.core.impl.ImageCaptureConfig;
-import androidx.camera.core.impl.SessionConfig;
-
-/**
- * Provides defaults for {@link ImageCaptureConfig} in the Camera2 implementation.
- */
-public final class ImageCaptureConfigProvider implements ConfigProvider<ImageCaptureConfig> {
- private static final String TAG = "ImageCaptureProvider";
-
- private final WindowManager mWindowManager;
-
- public ImageCaptureConfigProvider(@NonNull Context context) {
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- }
-
- @Override
- @NonNull
- @SuppressWarnings("deprecation") /* defaultDisplay */
- public ImageCaptureConfig getConfig() {
- ImageCapture.Builder builder = ImageCapture.Builder.fromConfig(
- ImageCapture.DEFAULT_CONFIG.getConfig());
-
- // SessionConfig containing all intrinsic properties needed for ImageCapture
- SessionConfig.Builder sessionBuilder = new SessionConfig.Builder();
- // TODO(b/114762170): Must set to preview here until we allow for multiple template types
- sessionBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
-
- // Add options to UseCaseConfig
- builder.setDefaultSessionConfig(sessionBuilder.build());
- builder.setSessionOptionUnpacker(Camera2SessionOptionUnpacker.INSTANCE);
-
- CaptureConfig.Builder captureConfig = new CaptureConfig.Builder();
- captureConfig.setTemplateType(CameraDevice.TEMPLATE_STILL_CAPTURE);
- builder.setDefaultCaptureConfig(captureConfig.build());
- builder.setCaptureOptionUnpacker(ImageCaptureOptionUnpacker.INSTANCE);
- builder.setTargetAspectRatio(AspectRatio.RATIO_4_3);
-
- // TODO(b/160477756): Make UseCase default config providers only provider static configs
- int targetRotation = mWindowManager.getDefaultDisplay().getRotation();
- builder.setTargetRotation(targetRotation);
-
- return builder.getUseCaseConfig();
- }
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/PreviewConfigProvider.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/PreviewConfigProvider.java
deleted file mode 100644
index 4025db2..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/PreviewConfigProvider.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.camera.camera2.internal;
-
-import android.content.Context;
-import android.hardware.camera2.CameraDevice;
-import android.view.WindowManager;
-
-import androidx.annotation.NonNull;
-import androidx.camera.core.AspectRatio;
-import androidx.camera.core.Preview;
-import androidx.camera.core.impl.CaptureConfig;
-import androidx.camera.core.impl.ConfigProvider;
-import androidx.camera.core.impl.PreviewConfig;
-import androidx.camera.core.impl.SessionConfig;
-
-/**
- * Provides defaults for {@link PreviewConfig} in the Camera2 implementation.
- */
-public final class PreviewConfigProvider implements ConfigProvider<PreviewConfig> {
- private static final String TAG = "PreviewConfigProvider";
-
- private final WindowManager mWindowManager;
-
- public PreviewConfigProvider(@NonNull Context context) {
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- }
-
- @Override
- @NonNull
- @SuppressWarnings("deprecation") /* defaultDisplay */
- public PreviewConfig getConfig() {
- Preview.Builder builder = Preview.Builder.fromConfig(
- Preview.DEFAULT_CONFIG.getConfig());
-
- // SessionConfig containing all intrinsic properties needed for Preview
- SessionConfig.Builder sessionBuilder = new SessionConfig.Builder();
- sessionBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
-
- // Add options to UseCaseConfig
- builder.setDefaultSessionConfig(sessionBuilder.build());
- builder.setSessionOptionUnpacker(Camera2SessionOptionUnpacker.INSTANCE);
-
- CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
- captureBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
- builder.setDefaultCaptureConfig(captureBuilder.build());
- builder.setCaptureOptionUnpacker(Camera2CaptureOptionUnpacker.INSTANCE);
-
- builder.setMaxResolution(SupportedSurfaceCombination.getPreviewSize(mWindowManager));
- builder.setTargetAspectRatio(AspectRatio.RATIO_4_3);
-
- // TODO(b/160477756): Make UseCase default config providers only provider static configs
- int targetRotation = mWindowManager.getDefaultDisplay().getRotation();
- builder.setTargetRotation(targetRotation);
-
- return builder.getUseCaseConfig();
- }
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/VideoCaptureConfigProvider.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/VideoCaptureConfigProvider.java
deleted file mode 100644
index fefbf2c..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/VideoCaptureConfigProvider.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.camera.camera2.internal;
-
-import android.content.Context;
-import android.hardware.camera2.CameraDevice;
-import android.view.WindowManager;
-
-import androidx.annotation.NonNull;
-import androidx.camera.core.AspectRatio;
-import androidx.camera.core.VideoCapture;
-import androidx.camera.core.impl.CaptureConfig;
-import androidx.camera.core.impl.ConfigProvider;
-import androidx.camera.core.impl.SessionConfig;
-import androidx.camera.core.impl.VideoCaptureConfig;
-
-/**
- * Provides defaults for {@link VideoCaptureConfig} in the Camera2 implementation.
- */
-public final class VideoCaptureConfigProvider implements ConfigProvider<VideoCaptureConfig> {
- private static final String TAG = "VideoCaptureProvider";
-
- private final WindowManager mWindowManager;
-
- public VideoCaptureConfigProvider(@NonNull Context context) {
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- }
-
- @Override
- @NonNull
- @SuppressWarnings("deprecation") /* defaultDisplay */
- public VideoCaptureConfig getConfig() {
- VideoCapture.Builder builder = VideoCapture.Builder.fromConfig(
- VideoCapture.DEFAULT_CONFIG.getConfig());
-
- // SessionConfig containing all intrinsic properties needed for VideoCapture
- SessionConfig.Builder sessionBuilder = new SessionConfig.Builder();
- // TODO(b/114762170): Must set to preview here until we allow for multiple template types
- sessionBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
-
- // Add options to UseCaseConfig
- builder.setDefaultSessionConfig(sessionBuilder.build());
- builder.setSessionOptionUnpacker(Camera2SessionOptionUnpacker.INSTANCE);
-
- CaptureConfig.Builder captureBuilder = new CaptureConfig.Builder();
- captureBuilder.setTemplateType(CameraDevice.TEMPLATE_PREVIEW);
- builder.setDefaultCaptureConfig(captureBuilder.build());
- builder.setCaptureOptionUnpacker(Camera2CaptureOptionUnpacker.INSTANCE);
- builder.setTargetAspectRatio(AspectRatio.RATIO_16_9);
-
- // TODO(b/160477756): Make UseCase default config providers only provider static configs
- int targetRotation = mWindowManager.getDefaultDisplay().getRotation();
- builder.setTargetRotation(targetRotation);
-
- return builder.getUseCaseConfig();
- }
-}
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManagerTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManagerTest.java
index 20544b2..9650372 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManagerTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManagerTest.java
@@ -50,18 +50,13 @@
import androidx.camera.core.UseCase;
import androidx.camera.core.VideoCapture;
import androidx.camera.core.impl.CameraDeviceSurfaceManager;
-import androidx.camera.core.impl.ExtendableUseCaseConfigFactory;
-import androidx.camera.core.impl.ImageAnalysisConfig;
-import androidx.camera.core.impl.ImageCaptureConfig;
import androidx.camera.core.impl.ImageFormatConstants;
-import androidx.camera.core.impl.PreviewConfig;
import androidx.camera.core.impl.SurfaceCombination;
import androidx.camera.core.impl.SurfaceConfig;
import androidx.camera.core.impl.SurfaceConfig.ConfigSize;
import androidx.camera.core.impl.SurfaceConfig.ConfigType;
import androidx.camera.core.impl.UseCaseConfig;
import androidx.camera.core.impl.UseCaseConfigFactory;
-import androidx.camera.core.impl.VideoCaptureConfig;
import androidx.camera.testing.CameraUtil;
import androidx.camera.testing.Configs;
import androidx.camera.testing.fakes.FakeCamera;
@@ -619,18 +614,8 @@
};
// Create default configuration factory
- UseCaseConfigFactory.Provider factoryProvider = context -> {
- ExtendableUseCaseConfigFactory configFactory = new ExtendableUseCaseConfigFactory();
- configFactory.installDefaultProvider(
- ImageAnalysisConfig.class, new ImageAnalysisConfigProvider(context));
- configFactory.installDefaultProvider(
- ImageCaptureConfig.class, new ImageCaptureConfigProvider(context));
- configFactory.installDefaultProvider(
- VideoCaptureConfig.class, new VideoCaptureConfigProvider(context));
- configFactory.installDefaultProvider(
- PreviewConfig.class, new PreviewConfigProvider(context));
- return configFactory;
- };
+ UseCaseConfigFactory.Provider factoryProvider = context -> new Camera2UseCaseConfigFactory(
+ context);
CameraXConfig.Builder appConfigBuilder =
new CameraXConfig.Builder()
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
index 76398ba..a2d726d 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
@@ -25,7 +25,6 @@
import androidx.camera.core.impl.CameraControlInternal;
import androidx.camera.core.impl.CameraFactory;
import androidx.camera.core.impl.CameraInternal;
-import androidx.camera.core.impl.ExtendableUseCaseConfigFactory;
import androidx.camera.core.impl.UseCaseConfigFactory;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.testing.fakes.FakeCamera;
@@ -33,7 +32,7 @@
import androidx.camera.testing.fakes.FakeCameraFactory;
import androidx.camera.testing.fakes.FakeCameraInfoInternal;
import androidx.camera.testing.fakes.FakeLifecycleOwner;
-import androidx.camera.testing.fakes.FakeUseCaseConfig;
+import androidx.camera.testing.fakes.FakeUseCaseConfigFactory;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
@@ -68,10 +67,7 @@
public void setUp() {
mContext = ApplicationProvider.getApplicationContext();
- ExtendableUseCaseConfigFactory defaultConfigFactory = new ExtendableUseCaseConfigFactory();
- defaultConfigFactory.installDefaultProvider(FakeUseCaseConfig.class,
- () -> new FakeUseCaseConfig.Builder().getUseCaseConfig());
- mUseCaseConfigFactory = defaultConfigFactory;
+ mUseCaseConfigFactory = new FakeUseCaseConfigFactory();
mFakeCameraFactory = new FakeCameraFactory();
mCameraInternal = new FakeCamera(mock(CameraControlInternal.class),
new FakeCameraInfoInternal(0, CAMERA_LENS_FACING));
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCase.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCase.java
index 4dccf39..0e873a7 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCase.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCase.java
@@ -59,7 +59,8 @@
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Nullable
@Override
- public UseCaseConfig<?> getDefaultConfig(@NonNull UseCaseConfigFactory factory) {
+ public UseCaseConfig<?> getDefaultConfig(boolean applyDefaultConfig,
+ @NonNull UseCaseConfigFactory factory) {
return null;
}
@@ -75,12 +76,6 @@
throw new RuntimeException("Not implemented");
}
- @NonNull
- @Override
- public UseCaseConfig.Builder<?, ?, ?> getUseCaseConfigBuilder() {
- throw new RuntimeException("Not implemented");
- }
-
@Override
@NonNull
protected Size onSuggestedResolutionUpdated(@NonNull Size suggestedResolution) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
index adb7ceb..9554cff 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
@@ -440,8 +440,16 @@
@RestrictTo(Scope.LIBRARY_GROUP)
@Override
@Nullable
- public UseCaseConfig<?> getDefaultConfig(@NonNull UseCaseConfigFactory factory) {
- return factory.getConfig(ImageAnalysisConfig.class);
+ public UseCaseConfig<?> getDefaultConfig(boolean applyDefaultConfig,
+ @NonNull UseCaseConfigFactory factory) {
+ Config captureConfig = factory.getConfig(UseCaseConfigFactory.CaptureType.IMAGE_ANALYSIS);
+
+ if (applyDefaultConfig) {
+ captureConfig = Config.mergeConfigs(captureConfig, DEFAULT_CONFIG.getConfig());
+ }
+
+ return captureConfig == null ? null :
+ getUseCaseConfigBuilder(captureConfig).getUseCaseConfig();
}
/**
@@ -479,18 +487,6 @@
*
* @hide
*/
- @NonNull
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- public UseCaseConfig.Builder<?, ?, ?> getUseCaseConfigBuilder() {
- return Builder.fromConfig((ImageAnalysisConfig) getCurrentConfig());
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
@@ -593,6 +589,7 @@
private static final Size DEFAULT_TARGET_RESOLUTION = new Size(640, 480);
private static final Size DEFAULT_MAX_RESOLUTION = new Size(1920, 1080);
private static final int DEFAULT_SURFACE_OCCUPANCY_PRIORITY = 1;
+ private static final int DEFAULT_ASPECT_RATIO = AspectRatio.RATIO_4_3;
private static final ImageAnalysisConfig DEFAULT_CONFIG;
@@ -600,7 +597,8 @@
Builder builder = new Builder()
.setDefaultResolution(DEFAULT_TARGET_RESOLUTION)
.setMaxResolution(DEFAULT_MAX_RESOLUTION)
- .setSurfaceOccupancyPriority(DEFAULT_SURFACE_OCCUPANCY_PRIORITY);
+ .setSurfaceOccupancyPriority(DEFAULT_SURFACE_OCCUPANCY_PRIORITY)
+ .setTargetAspectRatio(DEFAULT_ASPECT_RATIO);
DEFAULT_CONFIG = builder.getUseCaseConfig();
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index 7392ef4..4144443 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -426,8 +426,16 @@
@RestrictTo(Scope.LIBRARY_GROUP)
@Override
@Nullable
- public UseCaseConfig<?> getDefaultConfig(@NonNull UseCaseConfigFactory factory) {
- return factory.getConfig(ImageCaptureConfig.class);
+ public UseCaseConfig<?> getDefaultConfig(boolean applyDefaultConfig,
+ @NonNull UseCaseConfigFactory factory) {
+ Config captureConfig = factory.getConfig(UseCaseConfigFactory.CaptureType.IMAGE_CAPTURE);
+
+ if (applyDefaultConfig) {
+ captureConfig = Config.mergeConfigs(captureConfig, DEFAULT_CONFIG.getConfig());
+ }
+
+ return captureConfig == null ? null :
+ getUseCaseConfigBuilder(captureConfig).getUseCaseConfig();
}
/**
@@ -478,18 +486,6 @@
}
/**
- * {@inheritDoc}
- *
- * @hide
- */
- @NonNull
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- public UseCaseConfig.Builder<?, ?, ?> getUseCaseConfigBuilder() {
- return Builder.fromConfig((ImageCaptureConfig) getCurrentConfig());
- }
-
- /**
* Configures flash mode to CameraControlInternal once it is ready.
*
* @hide
@@ -1619,12 +1615,13 @@
public static final class Defaults
implements ConfigProvider<ImageCaptureConfig> {
private static final int DEFAULT_SURFACE_OCCUPANCY_PRIORITY = 4;
+ private static final int DEFAULT_ASPECT_RATIO = AspectRatio.RATIO_4_3;
private static final ImageCaptureConfig DEFAULT_CONFIG;
static {
Builder builder = new Builder().setSurfaceOccupancyPriority(
- DEFAULT_SURFACE_OCCUPANCY_PRIORITY);
+ DEFAULT_SURFACE_OCCUPANCY_PRIORITY).setTargetAspectRatio(DEFAULT_ASPECT_RATIO);
DEFAULT_CONFIG = builder.getUseCaseConfig();
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
index dce219f..7d18ab7c 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
@@ -445,8 +445,16 @@
@RestrictTo(Scope.LIBRARY_GROUP)
@Override
@Nullable
- public UseCaseConfig<?> getDefaultConfig(@NonNull UseCaseConfigFactory factory) {
- return factory.getConfig(PreviewConfig.class);
+ public UseCaseConfig<?> getDefaultConfig(boolean applyDefaultConfig,
+ @NonNull UseCaseConfigFactory factory) {
+ Config captureConfig = factory.getConfig(UseCaseConfigFactory.CaptureType.PREVIEW);
+
+ if (applyDefaultConfig) {
+ captureConfig = Config.mergeConfigs(captureConfig, DEFAULT_CONFIG.getConfig());
+ }
+
+ return captureConfig == null ? null :
+ getUseCaseConfigBuilder(captureConfig).getUseCaseConfig();
}
/**
@@ -485,18 +493,6 @@
*
* @hide
*/
- @NonNull
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- public UseCaseConfig.Builder<?, ?, ?> getUseCaseConfigBuilder() {
- return Preview.Builder.fromConfig((PreviewConfig) getCurrentConfig());
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
@RestrictTo(Scope.LIBRARY_GROUP)
@Override
public void onDetached() {
@@ -614,13 +610,13 @@
@RestrictTo(Scope.LIBRARY_GROUP)
public static final class Defaults implements ConfigProvider<PreviewConfig> {
private static final int DEFAULT_SURFACE_OCCUPANCY_PRIORITY = 2;
+ private static final int DEFAULT_ASPECT_RATIO = AspectRatio.RATIO_4_3;
private static final PreviewConfig DEFAULT_CONFIG;
static {
- Builder builder =
- new Builder()
- .setSurfaceOccupancyPriority(DEFAULT_SURFACE_OCCUPANCY_PRIORITY);
+ Builder builder = new Builder().setSurfaceOccupancyPriority(
+ DEFAULT_SURFACE_OCCUPANCY_PRIORITY).setTargetAspectRatio(DEFAULT_ASPECT_RATIO);
DEFAULT_CONFIG = builder.getUseCaseConfig();
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
index c8dedcd..7f20c0b 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
@@ -141,13 +141,15 @@
/**
* Retrieve the default {@link UseCaseConfig} for the UseCase.
*
+ * @param applyDefaultConfig true if this is the base config applied to a UseCase.
* @param factory the factory that contains the default UseCases.
* @return The UseCaseConfig or null if there is no default Config.
* @hide
*/
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
- public abstract UseCaseConfig<?> getDefaultConfig(@NonNull UseCaseConfigFactory factory);
+ public abstract UseCaseConfig<?> getDefaultConfig(boolean applyDefaultConfig,
+ @NonNull UseCaseConfigFactory factory);
/**
* Create a {@link UseCaseConfig.Builder} for the UseCase.
@@ -450,15 +452,6 @@
}
/**
- * Returns a builder based on the current use case config.
- *
- * @hide
- */
- @NonNull
- @RestrictTo(Scope.LIBRARY_GROUP)
- public abstract UseCaseConfig.Builder<?, ?, ?> getUseCaseConfigBuilder();
-
- /**
* Returns the currently attached {@link Camera} or {@code null} if none is attached.
*
* @hide
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
index dfc1760..12fe5ea 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/VideoCapture.java
@@ -270,8 +270,16 @@
@RestrictTo(Scope.LIBRARY_GROUP)
@Override
@Nullable
- public UseCaseConfig<?> getDefaultConfig(@NonNull UseCaseConfigFactory factory) {
- return factory.getConfig(VideoCaptureConfig.class);
+ public UseCaseConfig<?> getDefaultConfig(boolean applyDefaultConfig,
+ @NonNull UseCaseConfigFactory factory) {
+ Config captureConfig = factory.getConfig(UseCaseConfigFactory.CaptureType.VIDEO_CAPTURE);
+
+ if (applyDefaultConfig) {
+ captureConfig = Config.mergeConfigs(captureConfig, DEFAULT_CONFIG.getConfig());
+ }
+
+ return captureConfig == null ? null :
+ getUseCaseConfigBuilder(captureConfig).getUseCaseConfig();
}
/**
@@ -525,18 +533,6 @@
*
* @hide
*/
- @NonNull
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- public UseCaseConfig.Builder<?, ?, ?> getUseCaseConfigBuilder() {
- return Builder.fromConfig(getCurrentConfig());
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
@RestrictTo(Scope.LIBRARY_GROUP)
@UiThread
@Override
@@ -1113,6 +1109,7 @@
private static final Size DEFAULT_MAX_RESOLUTION = new Size(1920, 1080);
/** Surface occupancy prioirty to this use case */
private static final int DEFAULT_SURFACE_OCCUPANCY_PRIORITY = 3;
+ private static final int DEFAULT_ASPECT_RATIO = AspectRatio.RATIO_16_9;
private static final VideoCaptureConfig DEFAULT_CONFIG;
@@ -1127,7 +1124,8 @@
.setAudioRecordSource(DEFAULT_AUDIO_RECORD_SOURCE)
.setAudioMinBufferSize(DEFAULT_AUDIO_MIN_BUFFER_SIZE)
.setMaxResolution(DEFAULT_MAX_RESOLUTION)
- .setSurfaceOccupancyPriority(DEFAULT_SURFACE_OCCUPANCY_PRIORITY);
+ .setSurfaceOccupancyPriority(DEFAULT_SURFACE_OCCUPANCY_PRIORITY)
+ .setTargetAspectRatio(DEFAULT_ASPECT_RATIO);
DEFAULT_CONFIG = builder.getUseCaseConfig();
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraConfigs.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraConfigs.java
index 150a8e3..0e33ce4 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraConfigs.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraConfigs.java
@@ -35,9 +35,13 @@
static final class EmptyCameraConfig implements CameraConfig {
private final UseCaseConfigFactory mUseCaseConfigFactory = new UseCaseConfigFactory() {
+ /**
+ * Returns the configuration for the given capture type, or <code>null</code> if the
+ * configuration cannot be produced.
+ */
@Nullable
@Override
- public <C extends UseCaseConfig<?>> C getConfig(@NonNull Class<C> configType) {
+ public Config getConfig(@NonNull CaptureType captureType) {
return null;
}
};
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/Config.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/Config.java
index b8c8078..e26c48f 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/Config.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/Config.java
@@ -289,4 +289,43 @@
return false;
}
+
+ /**
+ * Merges two configs
+ *
+ * @param extendedConfig the extended config. The options in the extendedConfig will be applied
+ * on top of the baseConfig based on the option priorities.
+ * @param baseConfig the base config
+ * @return a {@link MutableOptionsBundle} of the merged config
+ */
+ @NonNull
+ static Config mergeConfigs(@Nullable Config extendedConfig,
+ @Nullable Config baseConfig) {
+ if (extendedConfig == null && baseConfig == null) {
+ return OptionsBundle.emptyBundle();
+ }
+
+ MutableOptionsBundle mergedConfig;
+
+ if (baseConfig != null) {
+ mergedConfig = MutableOptionsBundle.from(baseConfig);
+ } else {
+ mergedConfig = MutableOptionsBundle.create();
+ }
+
+ if (extendedConfig != null) {
+ // If any options need special handling, this is the place to do it. For now we'll
+ // just copy over all options.
+ for (Config.Option<?> opt : extendedConfig.listOptions()) {
+ @SuppressWarnings("unchecked") // Options/values are being copied directly
+ Config.Option<Object> objectOpt = (Config.Option<Object>) opt;
+
+ mergedConfig.insertOption(objectOpt,
+ extendedConfig.getOptionPriority(opt),
+ extendedConfig.retrieveOption(objectOpt));
+ }
+ }
+
+ return OptionsBundle.from(mergedConfig);
+ }
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/ExtendableUseCaseConfigFactory.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/ExtendableUseCaseConfigFactory.java
deleted file mode 100644
index 06b8939..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/ExtendableUseCaseConfigFactory.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.camera.core.impl;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A {@link UseCaseConfigFactory} that uses {@link ConfigProvider}s to provide configurations.
- */
-
-public final class ExtendableUseCaseConfigFactory implements UseCaseConfigFactory {
- private final Map<Class<?>, ConfigProvider<?>> mDefaultProviders = new HashMap<>();
-
- /** Inserts or overrides the {@link ConfigProvider} for the given config type. */
- public <C extends Config> void installDefaultProvider(
- @NonNull Class<C> configType, @NonNull ConfigProvider<C> defaultProvider) {
- mDefaultProviders.put(configType, defaultProvider);
- }
-
- @Nullable
- @Override
- public <C extends UseCaseConfig<?>> C getConfig(@NonNull Class<C> configType) {
- @SuppressWarnings("unchecked") // Providers only could have been inserted with
- // installDefaultProvider(), so the class should return the correct type.
- ConfigProvider<C> provider = (ConfigProvider<C>) mDefaultProviders.get(configType);
- if (provider != null) {
- return provider.getConfig();
- }
- return null;
- }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseConfigFactory.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseConfigFactory.java
index 440d38b..3362559 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseConfigFactory.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseConfigFactory.java
@@ -27,6 +27,29 @@
*/
public interface UseCaseConfigFactory {
+ enum CaptureType {
+ /**
+ * Capture type for still image capture. A still capture which can be a single or
+ * multiple frames which are combined into a single image.
+ */
+ IMAGE_CAPTURE,
+
+ /**
+ * Capture type for preview. A use case of this type is consuming a stream of frames.
+ */
+ PREVIEW,
+
+ /**
+ * Capture type for image analysis. A use case of this type is consuming a stream of frames.
+ */
+ IMAGE_ANALYSIS,
+
+ /**
+ * Capture type for video capture. A use case of this type is consuming a stream of frames.
+ */
+ VIDEO_CAPTURE
+ }
+
/**
* Interface for deferring creation of a UseCaseConfigFactory.
*/
@@ -43,9 +66,9 @@
}
/**
- * Returns the configuration for the given type, or <code>null</code> if the configuration
- * cannot be produced.
+ * Returns the configuration for the given capture type, or <code>null</code> if the
+ * configuration cannot be produced.
*/
@Nullable
- <C extends UseCaseConfig<?>> C getConfig(@NonNull Class<C> configType);
+ Config getConfig(@NonNull CaptureType captureType);
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
index 22e60a1..836fb21 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
@@ -368,8 +368,8 @@
UseCaseConfigFactory extendedFactory, UseCaseConfigFactory cameraFactory) {
Map<UseCase, ConfigPair> configs = new HashMap<>();
for (UseCase useCase : useCases) {
- configs.put(useCase, new ConfigPair(useCase.getDefaultConfig(extendedFactory),
- useCase.getDefaultConfig(cameraFactory)));
+ configs.put(useCase, new ConfigPair(useCase.getDefaultConfig(false, extendedFactory),
+ useCase.getDefaultConfig(true, cameraFactory)));
}
return configs;
}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/impl/ExtendableUseCaseConfigFactoryTest.java b/camera/camera-core/src/test/java/androidx/camera/core/impl/ExtendableUseCaseConfigFactoryTest.java
deleted file mode 100644
index 2bea8e8..0000000
--- a/camera/camera-core/src/test/java/androidx/camera/core/impl/ExtendableUseCaseConfigFactoryTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.camera.core.impl;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Build;
-
-import androidx.annotation.NonNull;
-import androidx.camera.testing.fakes.FakeUseCase;
-import androidx.camera.testing.fakes.FakeUseCaseConfig;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.internal.DoNotInstrument;
-
-@SmallTest
-@RunWith(RobolectricTestRunner.class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-public class ExtendableUseCaseConfigFactoryTest {
-
- private ExtendableUseCaseConfigFactory mFactory;
-
- @Before
- public void setUp() {
- mFactory = new ExtendableUseCaseConfigFactory();
- }
-
- @Test
- public void canInstallProvider_andRetrieveConfig() {
- mFactory.installDefaultProvider(FakeUseCaseConfig.class, new FakeUseCaseConfigProvider());
-
- FakeUseCaseConfig config = mFactory.getConfig(FakeUseCaseConfig.class);
- assertThat(config).isNotNull();
- assertThat(config.getTargetClass(null)).isEqualTo(FakeUseCase.class);
- }
-
- private static class FakeUseCaseConfigProvider implements ConfigProvider<FakeUseCaseConfig> {
-
- @NonNull
- @Override
- public FakeUseCaseConfig getConfig() {
- return new FakeUseCaseConfig.Builder().getUseCaseConfig();
- }
- }
-}
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/Extensions.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/Extensions.java
index 873c733..71c05559 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/Extensions.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/Extensions.java
@@ -28,9 +28,6 @@
import androidx.camera.core.ExperimentalCameraFilter;
import androidx.camera.core.UseCase;
import androidx.camera.core.impl.CameraFilters;
-import androidx.camera.core.impl.ExtendableUseCaseConfigFactory;
-import androidx.camera.core.impl.ImageCaptureConfig;
-import androidx.camera.core.impl.PreviewConfig;
import androidx.camera.core.internal.CameraUseCaseAdapter;
import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.AutoPreviewExtenderImpl;
@@ -42,8 +39,7 @@
import androidx.camera.extensions.impl.HdrPreviewExtenderImpl;
import androidx.camera.extensions.impl.NightImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.NightPreviewExtenderImpl;
-import androidx.camera.extensions.internal.ImageCaptureConfigProvider;
-import androidx.camera.extensions.internal.PreviewConfigProvider;
+import androidx.camera.extensions.internal.ExtensionsUseCaseConfigFactory;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -148,11 +144,8 @@
new LinkedHashSet<>(camera.getCameraInternals())).iterator().next();
CameraInfo extensionsCameraInfo = extensionCamera.getCameraInfo();
- ExtendableUseCaseConfigFactory factory = new ExtendableUseCaseConfigFactory();
- factory.installDefaultProvider(ImageCaptureConfig.class,
- new ImageCaptureConfigProvider(mode, extensionsCameraInfo, mContext));
- factory.installDefaultProvider(PreviewConfig.class,
- new PreviewConfigProvider(mode, extensionsCameraInfo, mContext));
+ ExtensionsUseCaseConfigFactory factory = new ExtensionsUseCaseConfigFactory(mode,
+ extensionsCameraInfo, mContext);
// Set the Camera
ExtensionsConfig extensionsConfig =
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionsUseCaseConfigFactory.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionsUseCaseConfigFactory.java
new file mode 100644
index 0000000..213d621
--- /dev/null
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionsUseCaseConfigFactory.java
@@ -0,0 +1,68 @@
+/*
+ * 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.camera.extensions.internal;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.camera.core.CameraInfo;
+import androidx.camera.core.impl.Config;
+import androidx.camera.core.impl.MutableOptionsBundle;
+import androidx.camera.core.impl.OptionsBundle;
+import androidx.camera.core.impl.UseCaseConfigFactory;
+import androidx.camera.extensions.Extensions;
+
+/**
+ * Implementation of UseCaseConfigFactory to provide the default extensions configurations for use
+ * cases.
+ */
+public final class ExtensionsUseCaseConfigFactory implements UseCaseConfigFactory {
+ private final ImageCaptureConfigProvider mImageCaptureConfigProvider;
+ private final PreviewConfigProvider mPreviewConfigProvider;
+
+ public ExtensionsUseCaseConfigFactory(@Extensions.ExtensionMode int mode,
+ @NonNull CameraInfo cameraInfo, @NonNull Context context) {
+ mImageCaptureConfigProvider = new ImageCaptureConfigProvider(mode, cameraInfo, context);
+ mPreviewConfigProvider = new PreviewConfigProvider(mode, cameraInfo, context);
+ }
+
+ /**
+ * Returns the configuration for the given capture type, or <code>null</code> if the
+ * configuration cannot be produced.
+ */
+ @Nullable
+ @Override
+ public Config getConfig(@NonNull CaptureType captureType) {
+ MutableOptionsBundle mutableOptionsBundle;
+
+ switch (captureType) {
+ case IMAGE_CAPTURE:
+ mutableOptionsBundle =
+ MutableOptionsBundle.from(mImageCaptureConfigProvider.getConfig());
+ break;
+ case PREVIEW:
+ mutableOptionsBundle =
+ MutableOptionsBundle.from(mPreviewConfigProvider.getConfig());
+ break;
+ default:
+ return null;
+ }
+
+ return OptionsBundle.from(mutableOptionsBundle);
+ }
+}
diff --git a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
index ca7973a4..a19b116 100644
--- a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
+++ b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
@@ -26,13 +26,13 @@
import androidx.camera.core.Preview
import androidx.camera.core.impl.CameraFactory
import androidx.camera.core.impl.CameraThreadConfig
-import androidx.camera.core.impl.ExtendableUseCaseConfigFactory
import androidx.camera.testing.fakes.FakeAppConfig
import androidx.camera.testing.fakes.FakeCamera
import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager
import androidx.camera.testing.fakes.FakeCameraFactory
import androidx.camera.testing.fakes.FakeCameraInfoInternal
import androidx.camera.testing.fakes.FakeLifecycleOwner
+import androidx.camera.testing.fakes.FakeUseCaseConfigFactory
import androidx.concurrent.futures.await
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.SmallTest
@@ -441,7 +441,7 @@
val appConfigBuilder = CameraXConfig.Builder()
.setCameraFactoryProvider(cameraFactoryProvider)
.setDeviceSurfaceManagerProvider { _, _ -> FakeCameraDeviceSurfaceManager() }
- .setUseCaseConfigFactoryProvider { ExtendableUseCaseConfigFactory() }
+ .setUseCaseConfigFactoryProvider { FakeUseCaseConfigFactory() }
ProcessCameraProvider.configureInstance(appConfigBuilder.build())
diff --git a/camera/camera-testing/src/main/AndroidManifest.xml b/camera/camera-testing/src/main/AndroidManifest.xml
index abd2784..0710da9 100644
--- a/camera/camera-testing/src/main/AndroidManifest.xml
+++ b/camera/camera-testing/src/main/AndroidManifest.xml
@@ -14,4 +14,18 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<manifest package="androidx.camera.testing" />
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="androidx.camera.testing">
+
+ <application>
+ <activity
+ android:name="androidx.camera.testing.activity.ForegroundTestActivity"
+ android:label="ForegroundTestActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
+
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
index a12decf..8a05f60 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
@@ -565,12 +565,12 @@
* (3) Test the camera can be opened successfully.
*
* <p>This method will set {@link PreTestCamera} to throw an exception when the camera is
- * unavailable if PRETEST_CAMERA_TAG is loggable at the debug level (see
- * androidx.camera.core.Logger#isDebugEnabled()).
+ * unavailable if PRETEST_CAMERA_TAG is loggable at the debug level (see Log#isLoggable).
*/
@NonNull
public static RuleChain grantCameraPermissionAndPreTest() {
- return RuleChain.outerRule(GrantPermissionRule.grant(Manifest.permission.CAMERA)).around(
+ RuleChain rule =
+ RuleChain.outerRule(GrantPermissionRule.grant(Manifest.permission.CAMERA)).around(
(base, description) -> new Statement() {
@Override
public void evaluate() throws Throwable {
@@ -578,8 +578,23 @@
assumeTrue(deviceHasCamera());
base.evaluate();
}
- }).around(
- new CameraUtil.PreTestCamera(Log.isLoggable(PRETEST_CAMERA_TAG, Log.DEBUG)));
+ });
+ if (shouldRunPreTest()) {
+ rule.around(
+ new CameraUtil.PreTestCamera(Log.isLoggable(PRETEST_CAMERA_TAG, Log.DEBUG)));
+ }
+ return rule;
+ }
+
+ private static boolean shouldRunPreTest() {
+ if (Build.MODEL.contains("pixel 2") && Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
+ // TODO(b/170070248) Pixel 2 HAL died easily if the pretest and CameraX open the
+ // camera device at the same time. Remove the code after the pixel 2 issue fixed.
+ Logger.d(LOG_TAG, "Skip camera pretest (b/170070248)");
+ return false;
+ }
+
+ return true;
}
/**
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/Configs.java b/camera/camera-testing/src/main/java/androidx/camera/testing/Configs.java
index b6d69bb..951bd8f 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/Configs.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/Configs.java
@@ -38,7 +38,7 @@
for (UseCase useCase : useCases) {
// Combine with default configuration.
UseCaseConfig<?> combinedUseCaseConfig = useCase.mergeConfigs(null,
- useCase.getDefaultConfig(useCaseConfigFactory));
+ useCase.getDefaultConfig(true, useCaseConfigFactory));
useCaseToConfigMap.put(useCase, combinedUseCaseConfig);
}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeAppConfig.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeAppConfig.java
index 62b38d9..8a551a6 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeAppConfig.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeAppConfig.java
@@ -22,7 +22,6 @@
import androidx.camera.core.CameraXConfig;
import androidx.camera.core.impl.CameraDeviceSurfaceManager;
import androidx.camera.core.impl.CameraFactory;
-import androidx.camera.core.impl.ExtendableUseCaseConfigFactory;
/**
* Convenience class for generating a fake {@link CameraXConfig}.
@@ -59,8 +58,7 @@
new CameraXConfig.Builder()
.setCameraFactoryProvider(cameraFactoryProvider)
.setDeviceSurfaceManagerProvider(surfaceManagerProvider)
- .setUseCaseConfigFactoryProvider(ignored ->
- new ExtendableUseCaseConfigFactory());
+ .setUseCaseConfigFactoryProvider(ignored -> new FakeUseCaseConfigFactory());
return appConfigBuilder.build();
}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCase.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCase.java
index 19370b3..65970ed 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCase.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCase.java
@@ -67,8 +67,10 @@
@Nullable
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Override
- public UseCaseConfig<?> getDefaultConfig(@NonNull UseCaseConfigFactory factory) {
- return factory.getConfig(FakeUseCaseConfig.class);
+ public UseCaseConfig<?> getDefaultConfig(boolean applyDefaultConfig,
+ @NonNull UseCaseConfigFactory factory) {
+ Config config = factory.getConfig(UseCaseConfigFactory.CaptureType.PREVIEW);
+ return config == null ? null : getUseCaseConfigBuilder(config).getUseCaseConfig();
}
@Override
@@ -77,12 +79,6 @@
mIsDetached = true;
}
- @NonNull
- @Override
- public UseCaseConfig.Builder<?, ?, ?> getUseCaseConfigBuilder() {
- return null;
- }
-
@Override
@NonNull
protected Size onSuggestedResolutionUpdated(@NonNull Size suggestedResolution) {
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfigFactory.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfigFactory.java
index 58084cc..ffb795d 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfigFactory.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfigFactory.java
@@ -19,8 +19,8 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
-import androidx.camera.core.impl.MutableOptionsBundle;
-import androidx.camera.core.impl.UseCaseConfig;
+import androidx.camera.core.impl.Config;
+import androidx.camera.core.impl.OptionsBundle;
import androidx.camera.core.impl.UseCaseConfigFactory;
/**
@@ -29,13 +29,13 @@
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public final class FakeUseCaseConfigFactory implements UseCaseConfigFactory {
+ /**
+ * Returns the configuration for the given capture type, or <code>null</code> if the
+ * configuration cannot be produced.
+ */
@Nullable
@Override
- @SuppressWarnings("unchecked") // Ok to cast FakeUseCaseConfig since we know the type
- public <C extends UseCaseConfig<?>> C getConfig(@NonNull Class<C> configType) {
- if (configType.equals(FakeUseCaseConfig.class)) {
- return (C) new FakeUseCaseConfig(MutableOptionsBundle.create());
- }
- return null;
+ public Config getConfig(@NonNull CaptureType captureType) {
+ return OptionsBundle.emptyBundle();
}
}
diff --git a/camera/camera-view/build.gradle b/camera/camera-view/build.gradle
index 47bd454..6c950c1 100644
--- a/camera/camera-view/build.gradle
+++ b/camera/camera-view/build.gradle
@@ -40,6 +40,7 @@
testImplementation(MOCKITO_CORE)
testImplementation(ROBOLECTRIC)
testImplementation(TRUTH)
+ testImplementation(ANDROIDX_TEST_RULES)
testImplementation(ANDROIDX_TEST_CORE)
testImplementation project(":camera:camera-testing")
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewTransformationDeviceTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewTransformationDeviceTest.kt
index 9d15376..cf225ff 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewTransformationDeviceTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewTransformationDeviceTest.kt
@@ -203,7 +203,8 @@
CROP_RECT,
90,
ARBITRARY_ROTATION
- ), SURFACE_SIZE, BACK_CAMERA
+ ),
+ SURFACE_SIZE, BACK_CAMERA
)
// Act.
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewMeteringPointFactoryDeviceTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewMeteringPointFactoryDeviceTest.kt
index f68a25f..0e9e196 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewMeteringPointFactoryDeviceTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewMeteringPointFactoryDeviceTest.kt
@@ -22,6 +22,7 @@
import android.util.Size
import androidx.camera.core.SurfaceRequest
import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -191,6 +192,8 @@
}
}
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+
@Test
fun verifyMeteringPoint() {
// Arrange.
@@ -198,12 +201,15 @@
previewTransformation.scaleType = scaleType
previewTransformation.setTransformationInfo(
SurfaceRequest.TransformationInfo.of
- (cropRect, rotationDegrees, FAKE_TARGET_ROTATION), surfaceSize, isFrontCamera
+ (cropRect, rotationDegrees, FAKE_TARGET_ROTATION),
+ surfaceSize, isFrontCamera
)
val meteringPointFactory = PreviewViewMeteringPointFactory(previewTransformation)
// Act.
- meteringPointFactory.recalculate(previewViewSize, layoutDirection)
+ instrumentation.runOnMainSync {
+ meteringPointFactory.recalculate(previewViewSize, layoutDirection)
+ }
val meteringPoint = meteringPointFactory.convertPoint(uiPoint.x, uiPoint.y)
// Assert.
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt
index 442c980..0681ee6 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt
@@ -30,6 +30,7 @@
import androidx.test.filters.MediumTest
import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -77,6 +78,11 @@
mImplementation = SurfaceViewImplementation(mParent, PreviewTransformation())
}
+ @After
+ fun tearDown() {
+ mSurfaceRequest.deferrableSurface.close()
+ }
+
@Test
fun surfaceProvidedSuccessfully() {
CoreAppTestUtil.checkKeyguard(mContext)
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java b/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
index 33cb9c1..d95ea9e 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
@@ -27,11 +27,11 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.experimental.UseExperimental;
-import androidx.arch.core.util.Function;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraControl;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.CameraSelector;
+import androidx.camera.core.CameraUnavailableException;
import androidx.camera.core.ExperimentalUseCaseGroup;
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.ImageAnalysis;
@@ -50,10 +50,8 @@
import androidx.camera.core.ZoomState;
import androidx.camera.core.impl.utils.Threads;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
-import androidx.camera.core.impl.utils.futures.FutureCallback;
import androidx.camera.core.impl.utils.futures.Futures;
import androidx.camera.lifecycle.ProcessCameraProvider;
-import androidx.core.content.ContextCompat;
import androidx.core.util.Preconditions;
import androidx.lifecycle.LiveData;
@@ -65,9 +63,15 @@
/**
* The abstract base camera controller class.
*
- * <p> The controller is a high level API manages the entire CameraX stack. This base class is
- * responsible for 1) initializing camera stack and 2) creating use cases based on user inputs.
- * Subclass this class to bind the use cases to camera.
+ * <p> This a high level controller that provides most of the CameraX core features
+ * in a single class. It handles camera initialization, creates and configures {@link UseCase}s.
+ * It also listens to device motion sensor and set the target rotation for the use cases.
+ *
+ * <p> The controller is required to be used with a {@link PreviewView}. {@link PreviewView}
+ * provides the UI elements to display camera preview. The layout of the {@link PreviewView} is
+ * used to set the crop rect so the output from other use cases matches the preview display in a
+ * WYSIWYG way. The controller also listens to {@link PreviewView}'s touch events to handle
+ * tap-to-focus and pinch-to-zoom features.
*/
abstract class CameraController {
@@ -169,7 +173,7 @@
private final Context mAppContext;
@NonNull
- private final ListenableFuture<ProcessCameraProvider> mProcessCameraProviderListenableFuture;
+ private final ListenableFuture<Void> mInitializationFuture;
CameraController(@NonNull Context context) {
mAppContext = context.getApplicationContext();
@@ -179,24 +183,12 @@
mVideoCapture = new VideoCapture.Builder().build();
// Wait for camera to be initialized before binding use cases.
- mProcessCameraProviderListenableFuture = ProcessCameraProvider.getInstance(mAppContext);
- Futures.addCallback(
- mProcessCameraProviderListenableFuture,
- new FutureCallback<ProcessCameraProvider>() {
-
- @SuppressLint("MissingPermission")
- @Override
- public void onSuccess(@Nullable ProcessCameraProvider provider) {
- mCameraProvider = provider;
- startCameraAndTrackStates();
- }
-
- @Override
- public void onFailure(Throwable t) {
- // TODO(b/148791439): fail gracefully and notify caller.
- throw new RuntimeException("CameraX failed to initialize.", t);
- }
-
+ mInitializationFuture = Futures.transform(
+ ProcessCameraProvider.getInstance(mAppContext),
+ provider -> {
+ mCameraProvider = provider;
+ startCamera();
+ return null;
}, CameraXExecutors.mainThreadExecutor());
// Listen to display rotation and set target rotation for Preview.
@@ -214,25 +206,23 @@
}
/**
- * Gets a {@link ListenableFuture} that completes when camera initialization completes.
+ * Gets a {@link ListenableFuture} that completes when camera initialization completes and
+ * use cases are attached.
*
- * <p> Cancellation of this future is a no-op. This future may fail with an
- * {@link InitializationException} and associated cause that can be retrieved by
- * {@link Throwable#getCause()). The cause will be a
- * {@link androidx.camera.core.CameraUnavailableException} if it fails to access any
- * camera during initialization.
+ * <p> This future may fail with an {@link InitializationException} and associated cause that
+ * can be retrieved by {@link Throwable#getCause()). The cause will be a
+ * {@link CameraUnavailableException} if it fails to access any camera during initialization.
*
- * <p> In the rare case that the future fails, the camera will become unusable. This could
- * happen for various reasons, for example hardware failure or the camera being held by
- * another process. If the failure is temporary, killing and restarting the app might fix the
- * issue.
+ * <p> In the rare case that the future fails with {@link CameraUnavailableException}, the
+ * camera will become unusable. This could happen for various reasons, for example hardware
+ * failure or the camera being held by another process. If the failure is temporary, killing
+ * and restarting the app might fix the issue.
*
* @see ProcessCameraProvider#getInstance
*/
+ @NonNull
public ListenableFuture<Void> getInitializationFuture() {
- return Futures.transform(mProcessCameraProviderListenableFuture,
- (Function<ProcessCameraProvider, Void>) input -> null,
- ContextCompat.getMainExecutor(mAppContext));
+ return mInitializationFuture;
}
/**
@@ -279,6 +269,9 @@
mViewPort = viewPort;
mPreviewDisplay = display;
startListeningToRotationEvents();
+ // TODO(b/148791439): startCameraAndTrackStates can be triggered by Preview layout
+ // change and the exception cannot be caught by the app. We need to set Preview with a
+ // wrapped SurfaceProvider so that startCameraAndTrackStates() is not called here.
startCameraAndTrackStates();
}
@@ -324,6 +317,9 @@
/**
* Checks if {@link ImageCapture} is enabled.
*
+ * <p> {@link ImageCapture} is enabled by default. It has to be enabled before
+ * {@link #takePicture} can be called.
+ *
* @see ImageCapture
*/
@MainThread
@@ -340,6 +336,9 @@
@MainThread
public void setImageCaptureEnabled(boolean imageCaptureEnabled) {
Threads.checkMainThread();
+ if (mImageCaptureEnabled == imageCaptureEnabled) {
+ return;
+ }
mImageCaptureEnabled = imageCaptureEnabled;
startCameraAndTrackStates();
}
@@ -347,13 +346,12 @@
/**
* Gets the flash mode for {@link ImageCapture}.
*
- * @return the flashMode. Value is {@link ImageCapture.FlashMode##FLASH_MODE_AUTO},
- * {@link ImageCapture.FlashMode##FLASH_MODE_ON}, or
- * {@link ImageCapture.FlashMode##FLASH_MODE_OFF}.
- * @see ImageCapture.FlashMode
+ * @return the flashMode. Value is {@link ImageCapture#FLASH_MODE_AUTO},
+ * {@link ImageCapture#FLASH_MODE_ON}, or {@link ImageCapture#FLASH_MODE_OFF}.
+ * @see ImageCapture
*/
- @ImageCapture.FlashMode
@MainThread
+ @ImageCapture.FlashMode
public int getImageCaptureFlashMode() {
Threads.checkMainThread();
return mImageCapture.getFlashMode();
@@ -362,10 +360,9 @@
/**
* Sets the flash mode for {@link ImageCapture}.
*
- * <p>If not set, the flash mode will default to {@link ImageCapture.FlashMode#FLASH_MODE_OFF}.
+ * <p>If not set, the flash mode will default to {@link ImageCapture#FLASH_MODE_OFF}.
*
- * @param flashMode the {@link ImageCapture.FlashMode} for {@link ImageCapture}.
- * @see ImageCapture.FlashMode
+ * @param flashMode the flash mode for {@link ImageCapture}.
*/
public void setImageCaptureFlashMode(@ImageCapture.FlashMode int flashMode) {
Threads.checkMainThread();
@@ -386,9 +383,9 @@
*/
@MainThread
public void takePicture(
- ImageCapture.OutputFileOptions outputFileOptions,
- Executor executor,
- ImageCapture.OnImageSavedCallback imageSavedCallback) {
+ @NonNull ImageCapture.OutputFileOptions outputFileOptions,
+ @NonNull Executor executor,
+ @NonNull ImageCapture.OnImageSavedCallback imageSavedCallback) {
Threads.checkMainThread();
checkUseCasesAttachedToCamera();
Preconditions.checkState(mImageCaptureEnabled, IMAGE_CAPTURE_DISABLED);
@@ -412,8 +409,8 @@
*/
@MainThread
public void takePicture(
- Executor executor,
- ImageCapture.OnImageCapturedCallback callback) {
+ @NonNull Executor executor,
+ @NonNull ImageCapture.OnImageCapturedCallback callback) {
Threads.checkMainThread();
checkUseCasesAttachedToCamera();
Preconditions.checkState(mImageCaptureEnabled, IMAGE_CAPTURE_DISABLED);
@@ -444,6 +441,9 @@
@MainThread
public void setImageAnalysisEnabled(boolean imageAnalysisEnabled) {
Threads.checkMainThread();
+ if (mImageAnalysisEnabled == imageAnalysisEnabled) {
+ return;
+ }
mImageAnalysisEnabled = imageAnalysisEnabled;
startCameraAndTrackStates();
}
@@ -497,7 +497,6 @@
*
* @return The backpressure strategy applied to the image producer.
* @see ImageAnalysis.Builder#getBackpressureStrategy()
- * @see ImageAnalysis.BackpressureStrategy
*/
@MainThread
@ImageAnalysis.BackpressureStrategy
@@ -516,7 +515,6 @@
*
* @param strategy The strategy to use.
* @see ImageAnalysis.Builder#setBackpressureStrategy(int)
- * @see ImageAnalysis.BackpressureStrategy
*/
@MainThread
public void setImageAnalysisBackpressureStrategy(
@@ -581,9 +579,10 @@
// -----------------
/**
- * Checks if {@link VideoCapture} is use case.
+ * Checks if video capture is enabled.
*
- * @see ImageCapture
+ * <p> Video capture is disabled by default. It has to be enabled before
+ * {@link #startRecording} can be called.
*/
@MainThread
public boolean isVideoCaptureEnabled() {
@@ -592,17 +591,15 @@
}
/**
- * Enables or disables {@link VideoCapture} use case.
- *
- * <p> Note that using both {@link #setVideoCaptureEnabled} and
- * {@link #setImageCaptureEnabled} simultaneously true may not work on lower end devices.
- *
- * @see ImageCapture
+ * Enables or disables video capture use case.
*/
@MainThread
public void setVideoCaptureEnabled(boolean videoCaptureEnabled) {
Threads.checkMainThread();
- if (mVideoCaptureEnabled && !videoCaptureEnabled) {
+ if (mVideoCaptureEnabled == videoCaptureEnabled) {
+ return;
+ }
+ if (!videoCaptureEnabled) {
stopRecording();
}
mVideoCaptureEnabled = videoCaptureEnabled;
@@ -617,8 +614,8 @@
* @param callback Callback which will receive success or failure.
*/
@MainThread
- public void startRecording(VideoCapture.OutputFileOptions outputFileOptions,
- Executor executor, final VideoCapture.OnVideoSavedCallback callback) {
+ public void startRecording(@NonNull VideoCapture.OutputFileOptions outputFileOptions,
+ @NonNull Executor executor, final @NonNull VideoCapture.OnVideoSavedCallback callback) {
Threads.checkMainThread();
checkUseCasesAttachedToCamera();
Preconditions.checkState(mVideoCaptureEnabled, VIDEO_CAPTURE_DISABLED);
@@ -667,27 +664,36 @@
// -----------------
/**
- * Sets the {@link CameraSelector}. The default value is
- * {@link CameraSelector#DEFAULT_BACK_CAMERA}.
+ * Sets the {@link CameraSelector}.
+ *
+ * <p>The default value is{@link CameraSelector#DEFAULT_BACK_CAMERA}.
*
* @see CameraSelector
*/
@MainThread
public void setCameraSelector(@NonNull CameraSelector cameraSelector) {
Threads.checkMainThread();
- // Try to unbind everything if camera is switched.
- if (mCameraProvider != null && mCameraSelector != cameraSelector) {
- mCameraProvider.unbindAll();
+ if (mCameraSelector == cameraSelector) {
+ return;
}
mCameraSelector = cameraSelector;
+
+ if (mCameraProvider == null) {
+ return;
+ }
+ mCameraProvider.unbindAll();
+
startCameraAndTrackStates();
}
/**
* Gets the {@link CameraSelector}.
*
+ * <p>The default value is{@link CameraSelector#DEFAULT_BACK_CAMERA}.
+ *
* @see CameraSelector
*/
+ @NonNull
@MainThread
public CameraSelector getCameraSelector() {
Threads.checkMainThread();
@@ -861,6 +867,7 @@
* {@link IllegalArgumentException}. Cancellation of this future is a no-op.
* @see CameraControl#setLinearZoom(float)
*/
+ @NonNull
@MainThread
public ListenableFuture<Void> setLinearZoom(float linearZoom) {
Threads.checkMainThread();
@@ -880,6 +887,7 @@
* @return a {@link LiveData} containing current torch state.
* @see CameraInfo#getTorchState()
*/
+ @NonNull
@MainThread
public LiveData<Integer> getTorchState() {
Threads.checkMainThread();
@@ -897,6 +905,7 @@
* this future is a no-op.
* @see CameraControl#enableTorch(boolean)
*/
+ @NonNull
@MainThread
public ListenableFuture<Void> enableTorch(boolean torchEnabled) {
Threads.checkMainThread();
@@ -907,8 +916,6 @@
return mCamera.getCameraControl().enableTorch(torchEnabled);
}
- // TODO(b/148791439): Give user a way to tell if the camera provider is ready.
-
/**
* Binds use cases, gets a new {@link Camera} instance and tracks the state of the camera.
*/
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/LifecycleCameraController.java b/camera/camera-view/src/main/java/androidx/camera/view/LifecycleCameraController.java
index ffd035e..ddbac8a 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/LifecycleCameraController.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/LifecycleCameraController.java
@@ -16,6 +16,8 @@
package androidx.camera.view;
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -28,24 +30,39 @@
import androidx.annotation.RestrictTo;
import androidx.annotation.experimental.UseExperimental;
import androidx.camera.core.Camera;
+import androidx.camera.core.UseCase;
import androidx.camera.core.UseCaseGroup;
import androidx.camera.core.impl.utils.Threads;
import androidx.camera.lifecycle.ExperimentalUseCaseGroupLifecycle;
-import androidx.lifecycle.Lifecycle;
+import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.lifecycle.LifecycleOwner;
/**
- * The controller that manages CameraX stack.
+ * A controller that provides most of the CameraX features.
*
- * <p> The controller is a high level API manages the entire CameraX stack including camera
- * readiness, Android UI lifecycle and use cases.
+ * <p> This a high level controller that provides most of the CameraX core features
+ * in a single class. It handles camera initialization, creates and configures {@link UseCase}s,
+ * and bind them to a {@link LifecycleOwner} when ready. It also listens to device motion sensor
+ * and set the target rotation for the use cases.
*
- * <p> The controller is bound with the given {@link LifecycleOwner}. It starts use cases by
- * binding it to a {@link LifecycleOwner}, and cleans up once the {@link Lifecycle} is destroyed.
+ * <p> Code sample:
+ * <pre><code>
+ * // Setup.
+ * CameraController controller = new LifecycleCameraController(context);
+ * controller.bindToLifecycle(lifecycleOwner);
+ * PreviewView previewView = findViewById(R.id.preview_view);
+ * previewView.setController(controller);
+ *
+ * // Use case features
+ * controller.takePicture(...);
+ *
+ * // Camera control features
+ * controller.setZoomRatio(.5F);
+ * </code></pre>
*
* @hide
*/
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@RestrictTo(LIBRARY_GROUP)
public final class LifecycleCameraController extends CameraController {
private static final String TAG = "CamLifecycleController";
@@ -58,7 +75,13 @@
}
/**
- * Sets the {@link LifecycleOwner} to be bound when ready.
+ * Sets the {@link LifecycleOwner} to be bound with the controller.
+ *
+ * <p> The state of the lifecycle will determine when the cameras are open, started, stopped
+ * and closed. When the {@link LifecycleOwner}'s state is start or greater, the controller
+ * receives camera data. It stops once the {@link LifecycleOwner} is destroyed.
+ *
+ * @see ProcessCameraProvider#bindToLifecycle
*/
@SuppressLint("MissingPermission")
@MainThread
@@ -69,7 +92,9 @@
}
/**
- * Unbinds all use cases.
+ * Clears the previously set {@link LifecycleOwner} and stops the camera.
+ *
+ * @see ProcessCameraProvider#unbindAll
*/
@MainThread
public void unbind() {
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
index 096849c..53c43d6 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
@@ -16,6 +16,8 @@
package androidx.camera.view;
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
@@ -44,6 +46,7 @@
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.experimental.UseExperimental;
+import androidx.camera.core.CameraControl;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ExperimentalUseCaseGroup;
@@ -366,17 +369,20 @@
* Gets the {@link MeteringPointFactory} for the camera currently connected to the
* {@link PreviewView}, if any.
*
- * <p>The returned {@link MeteringPointFactory} is capable of creating {@link MeteringPoint}s
+ * <p> The returned {@link MeteringPointFactory} is capable of creating {@link MeteringPoint}s
* from (x, y) coordinates in the {@link PreviewView}. This conversion takes into account its
- * {@link ScaleType}.
+ * {@link ScaleType}. The {@link MeteringPointFactory} is automatically adjusted if the
+ * {@link PreviewView} layout or the {@link ScaleType} changes.
*
- * <p>When the PreviewView has a width and/or height equal to zero, or when a preview
- * {@link Surface} is not yet requested by the camera, the returned factory will always create
- * invalid {@link MeteringPoint}s which could lead to the failure of
- * {@link androidx.camera.core.CameraControl#startFocusAndMetering(FocusMeteringAction)}, but it
- * won't cause the application to crash.
+ * <p> The {@link MeteringPointFactory} returns invalid {@link MeteringPoint} if the
+ * preview is not ready, or the {@link PreviewView} dimension is zero. The invalid
+ * {@link MeteringPoint} will cause
+ * {@link CameraControl#startFocusAndMetering(FocusMeteringAction)} to fail but it won't
+ * crash the application. Wait for the {@link StreamState#STREAMING} state to make sure the
+ * preview is ready.
*
* @return a {@link MeteringPointFactory}
+ * @see #getPreviewStreamState()
*/
@UiThread
@NonNull
@@ -718,14 +724,16 @@
/**
* Sets the {@link CameraController}.
*
- * <p> The controller creates and manages the {@link Preview} that backs the
- * {@link PreviewView}. It also configures the {@link ViewPort} based on the {@link ScaleType}
- * and the dimension of the {@link PreviewView}.
+ * <p> Once set, the controller will use {@link PreviewView} to display camera preview feed.
+ * It also uses the {@link PreviewView}'s layout dimension to set the crop rect for all the use
+ * cases so that the output from other use cases match what the end user sees in
+ * {@link PreviewView}. It also enables features like tap-to-focus and pinch-to-zoom.
*
* @hide
+ * @see LifecycleCameraController
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@MainThread
+ @RestrictTo(LIBRARY_GROUP)
public void setController(@Nullable CameraController cameraController) {
Threads.checkMainThread();
if (mCameraController != null && mCameraController != cameraController) {
@@ -742,9 +750,9 @@
*
* @hide
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Nullable
@MainThread
+ @RestrictTo(LIBRARY_GROUP)
public CameraController getController() {
Threads.checkMainThread();
return mCameraController;
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewMeteringPointFactory.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewMeteringPointFactory.java
index 21cc836..80fe4e4 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewMeteringPointFactory.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewMeteringPointFactory.java
@@ -20,10 +20,14 @@
import android.graphics.PointF;
import android.util.Size;
+import androidx.annotation.AnyThread;
+import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
+import androidx.annotation.UiThread;
import androidx.camera.core.MeteringPointFactory;
+import androidx.camera.core.impl.utils.Threads;
/**
* {@link MeteringPointFactory} for {@link PreviewView}.
@@ -38,6 +42,7 @@
@NonNull
private final PreviewTransformation mPreviewTransformation;
+ @GuardedBy("this")
@Nullable
private Matrix mMatrix;
@@ -45,23 +50,31 @@
mPreviewTransformation = previewTransformation;
}
+ @AnyThread
@NonNull
@Override
protected PointF convertPoint(float x, float y) {
- if (mMatrix == null) {
- return INVALID_POINT;
- }
float[] point = new float[]{x, y};
- mMatrix.mapPoints(point);
+ synchronized (this) {
+ if (mMatrix == null) {
+ return INVALID_POINT;
+ }
+ mMatrix.mapPoints(point);
+ }
return new PointF(point[0], point[1]);
}
+ @UiThread
void recalculate(@NonNull Size previewViewSize, int layoutDirection) {
- if (previewViewSize.getWidth() == 0 || previewViewSize.getHeight() == 0) {
- mMatrix = null;
- return;
+ Threads.checkMainThread();
+ synchronized (this) {
+ if (previewViewSize.getWidth() == 0 || previewViewSize.getHeight() == 0) {
+ mMatrix = null;
+ return;
+ }
+ mMatrix = mPreviewTransformation.getPreviewViewToNormalizedSurfaceMatrix(
+ previewViewSize,
+ layoutDirection);
}
- mMatrix = mPreviewTransformation.getPreviewViewToNormalizedSurfaceMatrix(previewViewSize,
- layoutDirection);
}
}
diff --git a/camera/camera-view/src/test/java/androidx/camera/view/PreviewViewMeteringPointFactoryTest.java b/camera/camera-view/src/test/java/androidx/camera/view/PreviewViewMeteringPointFactoryTest.java
index f5769e48..5db0863 100644
--- a/camera/camera-view/src/test/java/androidx/camera/view/PreviewViewMeteringPointFactoryTest.java
+++ b/camera/camera-view/src/test/java/androidx/camera/view/PreviewViewMeteringPointFactoryTest.java
@@ -26,6 +26,7 @@
import android.view.Surface;
import androidx.camera.core.SurfaceRequest;
+import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
import org.junit.Test;
@@ -46,6 +47,7 @@
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
+ @UiThreadTest
@Test
public void transformationInfoNotSet_createsInvalidMeteringPoint() {
// Arrange.
@@ -60,6 +62,7 @@
assertThat(meteringPoint).isEqualTo(PreviewViewMeteringPointFactory.INVALID_POINT);
}
+ @UiThreadTest
@Test
public void previewViewSizeIs0_createsInvalidMeteringPoint() {
// Arrange.
@@ -78,6 +81,7 @@
assertThat(meteringPoint).isEqualTo(PreviewViewMeteringPointFactory.INVALID_POINT);
}
+ @UiThreadTest
@Test
public void canCreateValidMeteringPoint() {
// Arrange.
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/CameraPipeActivity.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/CameraPipeActivity.kt
index 5c7fe90..1ef90b7 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/CameraPipeActivity.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/CameraPipeActivity.kt
@@ -127,7 +127,7 @@
if (lastCameraId == null) {
return cameraPipe.cameras().findAll().firstOrNull {
cameraPipe.cameras().awaitMetadata(it)[CameraCharacteristics.LENS_FACING] ==
- CameraCharacteristics.LENS_FACING_BACK
+ CameraCharacteristics.LENS_FACING_BACK
} ?: cameraPipe.cameras().findAll().first()
}
@@ -156,11 +156,13 @@
// Hide navigation to make the app full screen
// TODO: Alter this to use window insets class when running on Android R
- val uiOptions = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ val uiOptions = (
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LOW_PROFILE
- or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
+ or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ )
window.decorView.systemUiVisibility = uiOptions
// Make portrait / landscape rotation seamless
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataGenerationDefaults.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataGenerationDefaults.kt
index 51320dd..e4c3800 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataGenerationDefaults.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataGenerationDefaults.kt
@@ -42,34 +42,37 @@
val change = (0..5).random()
val direction = (0..1).random()
val newValue = if (direction == 0) prev - change else prev.toFloat() + change
- max(min(this.valueUpperBound.toFloat(), newValue), this.valueLowerBound
- .toFloat())
- }
+ max(
+ min(this.valueUpperBound.toFloat(), newValue),
+ this.valueLowerBound
+ .toFloat()
+ )
}
- else -> prev
+ }
+ else -> prev
}
}
private fun DataGenerationParams1D.generateNewIntOrNull(prev: Any?): Int? {
- if (prev !is Int?) throw Exception("Can't generate new Int from $prev")
+ if (prev !is Int?) throw Exception("Can't generate new Int from $prev")
- return if ((1..this.changeModeOnceInHowMany).random() == 1 || prev == null) {
- if ((1..this.nullValueOnceInHowMany).random() == 1) null
- else (this.valueLowerBound..this.valueUpperBound).random()
- } else prev
+ return if ((1..this.changeModeOnceInHowMany).random() == 1 || prev == null) {
+ if ((1..this.nullValueOnceInHowMany).random() == 1) null
+ else (this.valueLowerBound..this.valueUpperBound).random()
+ } else prev
}
private fun DataGenerationParams1D.generateNewBoolOrNull(prev: Any?): Boolean? {
- if (prev !is Boolean?) throw Exception("Can't generate new Bool from $prev")
- return if ((1..this.changeModeOnceInHowMany).random() == 1 || prev == null) {
- val temp = if ((1..this.nullValueOnceInHowMany).random() == 1) null
- else (0..1).random()
- when (temp) {
- 0 -> false
- 1 -> true
- else -> null
- }
- } else prev
+ if (prev !is Boolean?) throw Exception("Can't generate new Bool from $prev")
+ return if ((1..this.changeModeOnceInHowMany).random() == 1 || prev == null) {
+ val temp = if ((1..this.nullValueOnceInHowMany).random() == 1) null
+ else (0..1).random()
+ when (temp) {
+ 0 -> false
+ 1 -> true
+ else -> null
+ }
+ } else prev
}
/** These parameters can be adjusted to simulate real camera data more */
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataGenerator.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataGenerator.kt
index 3bf7f8f..9440d76b 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataGenerator.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataGenerator.kt
@@ -41,7 +41,8 @@
val runnable = get1DRunnable(default) { point ->
/** For graphs both keyValue and graph DataHolders need to be updated */
if (visualizationDefaults.keysVisualizedAsValueGraph.contains(key) ||
- visualizationDefaults.keysVisualizedAsStateGraph.contains(key)) {
+ visualizationDefaults.keysVisualizedAsStateGraph.contains(key)
+ ) {
dataListener.newGraphData(
entry.key,
point.frameNumber,
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataVisualizations.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataVisualizations.kt
index 2278003..7a633c0 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataVisualizations.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/DataVisualizations.kt
@@ -114,7 +114,9 @@
val keyValueViewParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams
- .MATCH_PARENT, heightPixels)
+ .MATCH_PARENT,
+ heightPixels
+ )
keyValueView.layoutParams = keyValueViewParams
keyValueLayout.key_value_layout.value_layout.addView(keyValueView)
@@ -145,8 +147,10 @@
dataHolder,
paints = paints
)
- else -> throw Exception("Visualization is not supported for this graphDataHolder " +
- "implementation")
+ else -> throw Exception(
+ "Visualization is not supported for this graphDataHolder " +
+ "implementation"
+ )
}
val graphLayout = View.inflate(context, R.layout.graph_layout, null)
@@ -163,7 +167,9 @@
val graphLayoutParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams
- .WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ .WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
graphLayoutParams.setMargins(0, 0, 0, 20)
graphLayout.layoutParams = graphLayoutParams
@@ -180,7 +186,9 @@
val keyValueViewParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams
- .MATCH_PARENT, 30)
+ .MATCH_PARENT,
+ 30
+ )
keyValueView.layoutParams = keyValueViewParams
keyValueLayout.key_value_layout.value_layout.addView(keyValueView)
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/SimpleCamera.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/SimpleCamera.kt
index 5b2de68..9d18861 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/SimpleCamera.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/SimpleCamera.kt
@@ -104,12 +104,15 @@
val cameraGraph = cameraPipe.create(config)
val viewfinderStream = cameraGraph.streams[viewfinderStreamConfig]!!
- viewfinder.configure(viewfinderStream.size, object : Viewfinder.SurfaceListener {
- override fun onSurfaceChanged(surface: Surface?, size: Size?) {
- Log.i("CXCP-App", "Viewfinder surface changed to $surface at $size")
- cameraGraph.setSurface(viewfinderStream.id, surface)
+ viewfinder.configure(
+ viewfinderStream.size,
+ object : Viewfinder.SurfaceListener {
+ override fun onSurfaceChanged(surface: Surface?, size: Size?) {
+ Log.i("CXCP-App", "Viewfinder surface changed to $surface at $size")
+ cameraGraph.setSurface(viewfinderStream.id, surface)
+ }
}
- })
+ )
val yuvStream = cameraGraph.streams[yuvStreamConfig]!!
cameraGraph.acquireSessionOrNull()!!.use {
it.setRepeating(
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/Viewfinder.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/Viewfinder.kt
index 7c6ffef..d888044 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/Viewfinder.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/Viewfinder.kt
@@ -87,9 +87,12 @@
// Make the viewfinder work better in editors by defining a placeholder viewfinder size.
if (isInEditMode) {
- configure(Size(480, 640), object : SurfaceListener {
- override fun onSurfaceChanged(surface: Surface?, size: Size?) {}
- })
+ configure(
+ Size(480, 640),
+ object : SurfaceListener {
+ override fun onSurfaceChanged(surface: Surface?, size: Size?) {}
+ }
+ )
}
}
@@ -424,7 +427,7 @@
"center" -> CENTER
else -> throw IllegalStateException(
"Unknown viewfinderLayout: $layoutMode available values are: " +
- "[fit, fill, center]"
+ "[fit, fill, center]"
)
}
}
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolder.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolder.kt
index 5e40c1b..fa237cf 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolder.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolder.kt
@@ -33,6 +33,8 @@
/** Fetches data points in time window with the given end and of the given length */
fun getPointsInTimeWindow(timeWindowLengthNanos: Long, timeWindowEndNanos: Long):
- List<GraphDataPoint> = graphData.getPointsInTimeWindow(timeWindowLengthNanos,
- timeWindowEndNanos)
+ List<GraphDataPoint> = graphData.getPointsInTimeWindow(
+ timeWindowLengthNanos,
+ timeWindowEndNanos
+ )
}
\ No newline at end of file
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolderStateImpl.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolderStateImpl.kt
index 65982da..557c84b 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolderStateImpl.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolderStateImpl.kt
@@ -26,8 +26,10 @@
init {
if (stateMap.isEmpty()) throw IllegalArgumentException("Must have at least 1 state")
stateMap.forEach {
- if (it.value == "") throw IllegalArgumentException("State description must not be" +
- " empty string")
+ if (it.value == "") throw IllegalArgumentException(
+ "State description must not be" +
+ " empty string"
+ )
}
}
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolderValueImpl.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolderValueImpl.kt
index 84f6ca1..d1ee6c0 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolderValueImpl.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataHolderValueImpl.kt
@@ -33,10 +33,14 @@
private val absoluteRange: Number
init {
- if (absoluteMax::class != absoluteMin::class) throw IllegalArgumentException("Min and max" +
- " values must be of the same type")
- if (absoluteMax <= absoluteMin) throw IllegalArgumentException("Max value must be greater" +
- " than min value")
+ if (absoluteMax::class != absoluteMin::class) throw IllegalArgumentException(
+ "Min and max" +
+ " values must be of the same type"
+ )
+ if (absoluteMax <= absoluteMin) throw IllegalArgumentException(
+ "Max value must be greater" +
+ " than min value"
+ )
this.absoluteRange = absoluteMax - absoluteMin
}
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataSortedRingBuffer.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataSortedRingBuffer.kt
index d4f5d0c..99881c3 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataSortedRingBuffer.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/dataholders/GraphDataSortedRingBuffer.kt
@@ -52,7 +52,7 @@
if (timeWindowEndNanos <= dataPoints.first().timestampNanos)
throw IllegalArgumentException(
"Time window's end must be after the first point's " +
- "timestamp"
+ "timestamp"
)
val timeWindowStartNanos = timeWindowEndNanos - timeWindowLengthNanos
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/extensions/DataGenerationFunctions.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/extensions/DataGenerationFunctions.kt
index 2f1a81a..e613f1c 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/extensions/DataGenerationFunctions.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/extensions/DataGenerationFunctions.kt
@@ -66,13 +66,15 @@
* data points aren't added to the generated points. This simulates missing data
*/
val currentValue = params.generateNewValue(previousValue)
- currentValue?.let { points.add(
- GeneratedDataPoint1D(
- frame,
- timeStampNanos,
- it
+ currentValue?.let {
+ points.add(
+ GeneratedDataPoint1D(
+ frame,
+ timeStampNanos,
+ it
+ )
)
- ) }
+ }
previousValue = currentValue
frame++
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/extensions/NumberOperators.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/extensions/NumberOperators.kt
index 07d76a6..7fbe7ec 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/extensions/NumberOperators.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/extensions/NumberOperators.kt
@@ -24,8 +24,10 @@
is Short -> this - otherNum.toShort()
is Double -> this - otherNum.toDouble()
is Float -> this - otherNum.toFloat()
- else -> throw RuntimeException("Subtraction between ${this::class.java.simpleName} and " +
- "${otherNum.javaClass.simpleName} is not supported")
+ else -> throw RuntimeException(
+ "Subtraction between ${this::class.java.simpleName} and " +
+ "${otherNum.javaClass.simpleName} is not supported"
+ )
}
}
@@ -36,7 +38,9 @@
is Short -> this.compareTo(otherNum.toShort())
is Double -> this.compareTo(otherNum.toDouble())
is Float -> this.compareTo(otherNum.toFloat())
- else -> throw RuntimeException("Comparison between ${this::class.java.simpleName} and " +
- "${otherNum.javaClass.simpleName} is not supported")
+ else -> throw RuntimeException(
+ "Comparison between ${this::class.java.simpleName} and " +
+ "${otherNum.javaClass.simpleName} is not supported"
+ )
}
}
\ No newline at end of file
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/transformations/DataTransformations1D.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/transformations/DataTransformations1D.kt
index a11d0e38..5dca4a0 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/transformations/DataTransformations1D.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/transformations/DataTransformations1D.kt
@@ -48,50 +48,52 @@
*/
private val specificTransformationMap: HashMap<CameraMetadataKey, (Any?) -> Number?> =
hashMapOf(
- /**
- * LENS_FOCUS_DISTANCE has a specific transformation that maps Float inputs to their
- * reciprocals, maps null input to null, and throws an IllegalArgumentException if the input
- * is not of the expected type Float?
- */
- LENS_FOCUS_DISTANCE to { keyData: Any? ->
- when (keyData) {
- is Float -> 1 / keyData
- else -> nullOrInvalid(LENS_FOCUS_DISTANCE, keyData)
- }
- },
-
- /**
- * CONTROL_AE_MODE has a specific transformation that upon an Int input returns that input
- * as is since each Int corresponds to a mode (The strings describing these modes will be
- * passed as a map into the data source for the visualization directly). Upon a null input,
- * null will be returned, and upon any other input, an exception will be thrown
- */
- CONTROL_AE_MODE to { keyData: Any? ->
- when (keyData) {
- is Int -> keyData
- else -> nullOrInvalid(CONTROL_AE_MODE, keyData)
- }
- },
-
- /**
- * STATISTICS_FACES has a specific transformation that maps Array<Face> inputs to array
- * size of that input, maps null input to null, and throws an IllegalArgumentException if
- * the input is not an Array, or is an Array of the wrong type
- */
- STATISTICS_FACES to { keyData: Any? ->
- when (keyData) {
- is Array<*> -> {
- if (keyData.isArrayOf<Face>()) {
- keyData.size
- } else {
- throw IllegalArgumentException("keyData for $STATISTICS_FACES expected " +
- "to be Array<Face>, but was ${keyData::class.simpleName}")
- }
+ /**
+ * LENS_FOCUS_DISTANCE has a specific transformation that maps Float inputs to their
+ * reciprocals, maps null input to null, and throws an IllegalArgumentException if the input
+ * is not of the expected type Float?
+ */
+ LENS_FOCUS_DISTANCE to { keyData: Any? ->
+ when (keyData) {
+ is Float -> 1 / keyData
+ else -> nullOrInvalid(LENS_FOCUS_DISTANCE, keyData)
}
- else -> nullOrInvalid(STATISTICS_FACES, keyData)
+ },
+
+ /**
+ * CONTROL_AE_MODE has a specific transformation that upon an Int input returns that input
+ * as is since each Int corresponds to a mode (The strings describing these modes will be
+ * passed as a map into the data source for the visualization directly). Upon a null input,
+ * null will be returned, and upon any other input, an exception will be thrown
+ */
+ CONTROL_AE_MODE to { keyData: Any? ->
+ when (keyData) {
+ is Int -> keyData
+ else -> nullOrInvalid(CONTROL_AE_MODE, keyData)
+ }
+ },
+
+ /**
+ * STATISTICS_FACES has a specific transformation that maps Array<Face> inputs to array
+ * size of that input, maps null input to null, and throws an IllegalArgumentException if
+ * the input is not an Array, or is an Array of the wrong type
+ */
+ STATISTICS_FACES to { keyData: Any? ->
+ when (keyData) {
+ is Array<*> -> {
+ if (keyData.isArrayOf<Face>()) {
+ keyData.size
+ } else {
+ throw IllegalArgumentException(
+ "keyData for $STATISTICS_FACES expected " +
+ "to be Array<Face>, but was ${keyData::class.simpleName}"
+ )
+ }
+ }
+ else -> nullOrInvalid(STATISTICS_FACES, keyData)
+ }
}
- }
- )
+ )
/**
* When converting data, this function will be called only if the camera metadata key has no
@@ -112,7 +114,9 @@
*/
private fun nullOrInvalid(key: CameraMetadataKey, keyData: Any?): Number? {
if (keyData == null) return null
- throw IllegalArgumentException("keyData of type ${keyData::class.simpleName} for $key is" +
- " not supported")
+ throw IllegalArgumentException(
+ "keyData of type ${keyData::class.simpleName} for $key is" +
+ " not supported"
+ )
}
}
\ No newline at end of file
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/transformations/DataTransformationsKeyValue.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/transformations/DataTransformationsKeyValue.kt
index 871018a..254ba7e 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/transformations/DataTransformationsKeyValue.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/transformations/DataTransformationsKeyValue.kt
@@ -79,7 +79,9 @@
private fun nullOrInvalid(key: CameraMetadataKey, keyData: Any?): String? {
if (keyData == null) return "MISSING DATA"
- throw IllegalArgumentException("keyData of type ${keyData::class.simpleName} for $key is" +
- " not supported")
+ throw IllegalArgumentException(
+ "keyData of type ${keyData::class.simpleName} for $key is" +
+ " not supported"
+ )
}
}
\ No newline at end of file
diff --git a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/visualizations/GraphView.kt b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/visualizations/GraphView.kt
index 25bcec6..6296ad5 100644
--- a/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/visualizations/GraphView.kt
+++ b/camera/integration-tests/camerapipetestapp/src/main/java/androidx/camera/integration/camera2/pipe/visualizations/GraphView.kt
@@ -108,8 +108,8 @@
/** Calculate the y coordinate given a data point*/
private fun getYFromPoint(point: GraphDataPoint): Float = layoutState.dataGraphHeight -
- unitHeight *
- point.value.toFloat()
+ unitHeight *
+ point.value.toFloat()
private fun drawLatency(
canvas: Canvas,
@@ -118,9 +118,13 @@
x2: Float,
latency2: Float,
paint: Paint
- ) = canvas.drawLine(x1, layoutState.latencyBaseline - latency1 * 150, x2, layoutState
- .latencyBaseline - latency2 *
- 150, paint)
+ ) = canvas.drawLine(
+ x1, layoutState.latencyBaseline - latency1 * 150, x2,
+ layoutState
+ .latencyBaseline - latency2 *
+ 150,
+ paint
+ )
/** Draws all the data points within the time window */
private fun drawPoints(
@@ -151,7 +155,7 @@
val intervalsPassedSinceTimestamp = point.timestampNanos / TIME_INTERVAL_LENGTH_NANOS
.toFloat()
val intervalsPassedSinceArrivalTime = point.timeArrivedNanos /
- TIME_INTERVAL_LENGTH_NANOS.toFloat()
+ TIME_INTERVAL_LENGTH_NANOS.toFloat()
currentX = (intervalsPassedSinceTimestamp - xIntervalOffset) * width
@@ -163,8 +167,10 @@
else latencyMap[point] = currentLatency
if (lastLatency != null)
- drawLatency(canvas, lastX, lastLatency, currentX, currentLatency,
- paints.latencyDataPaint)
+ drawLatency(
+ canvas, lastX, lastLatency, currentX, currentLatency,
+ paints.latencyDataPaint
+ )
lastLatency = latencyMap[point]
@@ -179,8 +185,10 @@
val frameUnitWidth = (currentX - lastX) / (frameDifference)
(1 until frameDifference).forEach { i ->
val missingFrameX = lastX + i * frameUnitWidth
- canvas.drawLine(missingFrameX, 0f, missingFrameX, layoutState.dataGraphHeight,
- paints.missingDataPaint)
+ canvas.drawLine(
+ missingFrameX, 0f, missingFrameX, layoutState.dataGraphHeight,
+ paints.missingDataPaint
+ )
}
}
diff --git a/camera/integration-tests/camerapipetestapp/src/test/java/androidx/camera/integration/camera2/pipe/GraphDataHolderStateImplTest.kt b/camera/integration-tests/camerapipetestapp/src/test/java/androidx/camera/integration/camera2/pipe/GraphDataHolderStateImplTest.kt
index be8c40c..25ecfb3 100644
--- a/camera/integration-tests/camerapipetestapp/src/test/java/androidx/camera/integration/camera2/pipe/GraphDataHolderStateImplTest.kt
+++ b/camera/integration-tests/camerapipetestapp/src/test/java/androidx/camera/integration/camera2/pipe/GraphDataHolderStateImplTest.kt
@@ -58,7 +58,11 @@
GraphDataSortedRingBuffer()
)
- Truth.assertThat(graphDataHolderStateImpl.getStrings()).isEqualTo(listOf("one", "two",
- "three"))
+ Truth.assertThat(graphDataHolderStateImpl.getStrings()).isEqualTo(
+ listOf(
+ "one", "two",
+ "three"
+ )
+ )
}
}
\ No newline at end of file
diff --git a/camera/integration-tests/timingtestapp/src/androidTest/java/androidx/camera/integration/antelope/AntelopeInstrumentedTests.kt b/camera/integration-tests/timingtestapp/src/androidTest/java/androidx/camera/integration/antelope/AntelopeInstrumentedTests.kt
index d9ae29d..72e1b67 100644
--- a/camera/integration-tests/timingtestapp/src/androidTest/java/androidx/camera/integration/antelope/AntelopeInstrumentedTests.kt
+++ b/camera/integration-tests/timingtestapp/src/androidTest/java/androidx/camera/integration/antelope/AntelopeInstrumentedTests.kt
@@ -91,13 +91,16 @@
fun grantPermissions() {
getInstrumentation().getUiAutomation().executeShellCommand(
"pm grant " + activityRule.activity.applicationContext +
- " android.permission.CAMERA")
+ " android.permission.CAMERA"
+ )
getInstrumentation().getUiAutomation().executeShellCommand(
"pm grant " + activityRule.activity.applicationContext +
- " android.permission.READ_EXTERNAL_STORAGE")
+ " android.permission.READ_EXTERNAL_STORAGE"
+ )
getInstrumentation().getUiAutomation().executeShellCommand(
"pm grant " + activityRule.activity.applicationContext +
- " android.permission.WRITE_EXTERNAL_STORAGE")
+ " android.permission.WRITE_EXTERNAL_STORAGE"
+ )
}
/**
@@ -185,8 +188,10 @@
prefEditor.putString(res.getString(R.string.settings_single_test_api_key), "Camera2")
prefEditor.putString(res.getString(R.string.settings_single_test_imagesize_key), "Max")
prefEditor.putString(res.getString(R.string.settings_single_test_focus_key), "Auto")
- prefEditor.putString(res.getString(R.string.settings_single_test_camera_key),
- getFirstCamera())
+ prefEditor.putString(
+ res.getString(R.string.settings_single_test_camera_key),
+ getFirstCamera()
+ )
prefEditor.putString(res.getString(R.string.settings_previewbuffer_key), PREVIEW_BUFFER)
prefEditor.putBoolean(res.getString(R.string.settings_autodelete_key), true)
prefEditor.commit()
@@ -256,13 +261,17 @@
assumeTrue(hasAnyCamera())
// Set up capture
- prefEditor.putString(res.getString(R.string.settings_single_test_type_key),
- "MULTI_PHOTO_CHAIN")
+ prefEditor.putString(
+ res.getString(R.string.settings_single_test_type_key),
+ "MULTI_PHOTO_CHAIN"
+ )
prefEditor.putString(res.getString(R.string.settings_single_test_api_key), "Camera2")
prefEditor.putString(res.getString(R.string.settings_single_test_imagesize_key), "Min")
prefEditor.putString(res.getString(R.string.settings_single_test_focus_key), "Auto")
- prefEditor.putString(res.getString(R.string.settings_single_test_camera_key),
- getFirstCamera())
+ prefEditor.putString(
+ res.getString(R.string.settings_single_test_camera_key),
+ getFirstCamera()
+ )
prefEditor.putString(res.getString(R.string.settings_numtests_key), "3")
prefEditor.putString(res.getString(R.string.settings_previewbuffer_key), PREVIEW_BUFFER)
prefEditor.putBoolean(res.getString(R.string.settings_autodelete_key), true)
@@ -273,8 +282,11 @@
}
// Check if test was successful
- onView(withId(R.id.text_log)).check(matches(
- withSubstring("Multiple Captures (Chained)\nCamera")))
+ onView(withId(R.id.text_log)).check(
+ matches(
+ withSubstring("Multiple Captures (Chained)\nCamera")
+ )
+ )
assertThat(isLogDirEmpty()).isFalse()
}
@@ -298,8 +310,10 @@
prefEditor.putString(res.getString(R.string.settings_single_test_api_key), "Camera2")
prefEditor.putString(res.getString(R.string.settings_single_test_imagesize_key), "Max")
prefEditor.putString(res.getString(R.string.settings_single_test_focus_key), "Auto")
- prefEditor.putString(res.getString(R.string.settings_single_test_camera_key),
- getFirstCamera())
+ prefEditor.putString(
+ res.getString(R.string.settings_single_test_camera_key),
+ getFirstCamera()
+ )
prefEditor.putString(res.getString(R.string.settings_numtests_key), "30")
prefEditor.putString(res.getString(R.string.settings_previewbuffer_key), PREVIEW_BUFFER)
prefEditor.putBoolean(res.getString(R.string.settings_autodelete_key), true)
@@ -337,8 +351,10 @@
prefEditor.putString(res.getString(R.string.settings_single_test_api_key), "Camera2")
prefEditor.putString(res.getString(R.string.settings_single_test_imagesize_key), "Max")
prefEditor.putString(res.getString(R.string.settings_single_test_focus_key), "Auto")
- prefEditor.putString(res.getString(R.string.settings_single_test_camera_key),
- getFirstCamera())
+ prefEditor.putString(
+ res.getString(R.string.settings_single_test_camera_key),
+ getFirstCamera()
+ )
prefEditor.putString(res.getString(R.string.settings_previewbuffer_key), PREVIEW_BUFFER)
prefEditor.putBoolean(res.getString(R.string.settings_autodelete_key), true)
prefEditor.commit()
@@ -374,8 +390,10 @@
prefEditor.putString(res.getString(R.string.settings_single_test_api_key), "Camera2")
prefEditor.putString(res.getString(R.string.settings_single_test_imagesize_key), "Max")
prefEditor.putString(res.getString(R.string.settings_single_test_focus_key), "Auto")
- prefEditor.putString(res.getString(R.string.settings_single_test_camera_key),
- getFirstCamera())
+ prefEditor.putString(
+ res.getString(R.string.settings_single_test_camera_key),
+ getFirstCamera()
+ )
prefEditor.putString(res.getString(R.string.settings_previewbuffer_key), PREVIEW_BUFFER)
prefEditor.putBoolean(res.getString(R.string.settings_autodelete_key), false)
prefEditor.commit()
@@ -416,8 +434,10 @@
prefEditor.putString(res.getString(R.string.settings_single_test_api_key), "Camera1")
prefEditor.putString(res.getString(R.string.settings_single_test_imagesize_key), "Max")
prefEditor.putString(res.getString(R.string.settings_single_test_focus_key), "Auto")
- prefEditor.putString(res.getString(R.string.settings_single_test_camera_key),
- getFirstCamera())
+ prefEditor.putString(
+ res.getString(R.string.settings_single_test_camera_key),
+ getFirstCamera()
+ )
prefEditor.putString(res.getString(R.string.settings_numtests_key), "3")
prefEditor.putString(res.getString(R.string.settings_previewbuffer_key), PREVIEW_BUFFER)
prefEditor.putBoolean(res.getString(R.string.settings_autodelete_key), true)
@@ -453,8 +473,10 @@
prefEditor.putString(res.getString(R.string.settings_single_test_api_key), "CameraX")
prefEditor.putString(res.getString(R.string.settings_single_test_imagesize_key), "Max")
prefEditor.putString(res.getString(R.string.settings_single_test_focus_key), "Auto")
- prefEditor.putString(res.getString(R.string.settings_single_test_camera_key),
- getFirstCamera())
+ prefEditor.putString(
+ res.getString(R.string.settings_single_test_camera_key),
+ getFirstCamera()
+ )
prefEditor.putString(res.getString(R.string.settings_numtests_key), "3")
prefEditor.putString(res.getString(R.string.settings_previewbuffer_key), PREVIEW_BUFFER)
prefEditor.putBoolean(res.getString(R.string.settings_autodelete_key), true)
@@ -486,12 +508,18 @@
assumeTrue(hasAnyCamera())
// Set up maximum test coverage for Camera2
- prefEditor.putStringSet(res.getString(R.string.settings_autotest_api_key),
- hashSetOf("Camera2"))
- prefEditor.putStringSet(res.getString(R.string.settings_autotest_imagesize_key),
- res.getStringArray(R.array.array_settings_imagesize).toHashSet())
- prefEditor.putStringSet(res.getString(R.string.settings_autotest_focus_key),
- res.getStringArray(R.array.array_settings_focus).toHashSet())
+ prefEditor.putStringSet(
+ res.getString(R.string.settings_autotest_api_key),
+ hashSetOf("Camera2")
+ )
+ prefEditor.putStringSet(
+ res.getString(R.string.settings_autotest_imagesize_key),
+ res.getStringArray(R.array.array_settings_imagesize).toHashSet()
+ )
+ prefEditor.putStringSet(
+ res.getString(R.string.settings_autotest_focus_key),
+ res.getStringArray(R.array.array_settings_focus).toHashSet()
+ )
if (hasCameraZeroAndOne())
prefEditor.putBoolean(res.getString(R.string.settings_autotest_switchtest_key), true)
@@ -530,12 +558,18 @@
assumeTrue(hasAnyCamera())
// Set up maximum test coverage for CameraX
- prefEditor.putStringSet(res.getString(R.string.settings_autotest_api_key),
- hashSetOf("CameraX"))
- prefEditor.putStringSet(res.getString(R.string.settings_autotest_imagesize_key),
- res.getStringArray(R.array.array_settings_imagesize).toHashSet())
- prefEditor.putStringSet(res.getString(R.string.settings_autotest_focus_key),
- res.getStringArray(R.array.array_settings_focus).toHashSet())
+ prefEditor.putStringSet(
+ res.getString(R.string.settings_autotest_api_key),
+ hashSetOf("CameraX")
+ )
+ prefEditor.putStringSet(
+ res.getString(R.string.settings_autotest_imagesize_key),
+ res.getStringArray(R.array.array_settings_imagesize).toHashSet()
+ )
+ prefEditor.putStringSet(
+ res.getString(R.string.settings_autotest_focus_key),
+ res.getStringArray(R.array.array_settings_focus).toHashSet()
+ )
if (hasFrontAndBackCamera())
prefEditor.putBoolean(res.getString(R.string.settings_autotest_switchtest_key), true)
@@ -575,12 +609,18 @@
assumeTrue(hasAnyCamera())
// Set up maximum test coverage for Camera1
- prefEditor.putStringSet(res.getString(R.string.settings_autotest_api_key),
- hashSetOf("Camera1"))
- prefEditor.putStringSet(res.getString(R.string.settings_autotest_imagesize_key),
- res.getStringArray(R.array.array_settings_imagesize).toHashSet())
- prefEditor.putStringSet(res.getString(R.string.settings_autotest_focus_key),
- res.getStringArray(R.array.array_settings_focus).toHashSet())
+ prefEditor.putStringSet(
+ res.getString(R.string.settings_autotest_api_key),
+ hashSetOf("Camera1")
+ )
+ prefEditor.putStringSet(
+ res.getString(R.string.settings_autotest_imagesize_key),
+ res.getStringArray(R.array.array_settings_imagesize).toHashSet()
+ )
+ prefEditor.putStringSet(
+ res.getString(R.string.settings_autotest_focus_key),
+ res.getStringArray(R.array.array_settings_focus).toHashSet()
+ )
if (hasCameraZeroAndOne())
prefEditor.putBoolean(res.getString(R.string.settings_autotest_switchtest_key), true)
@@ -607,8 +647,12 @@
* Checks whether the default .csv log directory is empty
*/
private fun isLogDirEmpty(): Boolean {
- val csvDir = File(Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_DOCUMENTS), MainActivity.LOG_DIR)
+ val csvDir = File(
+ Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DOCUMENTS
+ ),
+ MainActivity.LOG_DIR
+ )
return if (csvDir.exists()) {
val children = csvDir.listFiles()
@@ -622,8 +666,12 @@
* Checks whether the default image directory is empty
*/
private fun isPhotoDirEmpty(): Boolean {
- val photoDir = File(Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_DCIM), MainActivity.PHOTOS_DIR)
+ val photoDir = File(
+ Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DCIM
+ ),
+ MainActivity.PHOTOS_DIR
+ )
return if (photoDir.exists()) {
val children = photoDir.listFiles()
@@ -679,7 +727,7 @@
* Checks if this devices has both a front and back camera
*/
private fun hasFrontAndBackCamera(): Boolean = hasCameraType(CameraMetadata.LENS_FACING_BACK) &&
- hasCameraType(CameraMetadata.LENS_FACING_FRONT)
+ hasCameraType(CameraMetadata.LENS_FACING_FRONT)
/**
* Determine what the first camera in the system is.
diff --git a/camera/integration-tests/timingtestapp/src/androidTest/java/androidx/camera/integration/antelope/RepeatRule.kt b/camera/integration-tests/timingtestapp/src/androidTest/java/androidx/camera/integration/antelope/RepeatRule.kt
index 4dee77c..728fefb 100644
--- a/camera/integration-tests/timingtestapp/src/androidTest/java/androidx/camera/integration/antelope/RepeatRule.kt
+++ b/camera/integration-tests/timingtestapp/src/androidTest/java/androidx/camera/integration/antelope/RepeatRule.kt
@@ -39,8 +39,10 @@
* <br></br><br></br>
*/
class RepeatRule : TestRule {
- @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER,
- AnnotationTarget.PROPERTY_SETTER)
+ @Target(
+ AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER,
+ AnnotationTarget.PROPERTY_SETTER
+ )
@Retention(AnnotationRetention.RUNTIME)
annotation class Repeat(val times: Int = 1)
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/CameraUtils.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/CameraUtils.kt
index d0f5811..32b4baf 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/CameraUtils.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/CameraUtils.kt
@@ -89,10 +89,12 @@
// Multi-camera
for (capability in cameraCapabilities) {
if (capability ==
- CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
+ ) {
hasMulti = true
} else if (capability ==
- CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) {
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR
+ ) {
hasManualControl = true
}
}
@@ -105,14 +107,16 @@
isFront = CameraCharacteristics.LENS_FACING_FRONT ==
cameraChars.get(CameraCharacteristics.LENS_FACING)
- isExternal = (Build.VERSION.SDK_INT >= 23 &&
- CameraCharacteristics.LENS_FACING_EXTERNAL ==
- cameraChars.get(CameraCharacteristics.LENS_FACING))
+ isExternal = (
+ Build.VERSION.SDK_INT >= 23 &&
+ CameraCharacteristics.LENS_FACING_EXTERNAL ==
+ cameraChars.get(CameraCharacteristics.LENS_FACING)
+ )
characteristics = cameraChars
focalLengths =
cameraChars.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)
- ?: FloatArray(0)
+ ?: FloatArray(0)
smallestFocalLength = smallestFocalLength(focalLengths)
minDeltaFromNormal = focalLengthMinDeltaFromNormal(focalLengths)
@@ -121,7 +125,7 @@
largestAperture = largestAperture(apertures)
minFocusDistance =
cameraChars.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE)
- ?: MainActivity.FIXED_FOCUS_DISTANCE
+ ?: MainActivity.FIXED_FOCUS_DISTANCE
for (focalLength in focalLengths) {
logd("In " + id + " found focalLength: " + focalLength)
@@ -152,7 +156,7 @@
logd("WE HAVE Mono!")
isLegacy = cameraChars.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ==
- CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
val activeSensorRect: Rect = cameraChars.get(SENSOR_INFO_ACTIVE_ARRAY_SIZE)!!
megapixels = (activeSensorRect.width() * activeSensorRect.height()) / 1000000
@@ -182,10 +186,12 @@
if (map != null) {
cam2MaxSize = Collections.max(
Arrays.asList(*map.getOutputSizes(ImageFormat.JPEG)),
- CompareSizesByArea())
+ CompareSizesByArea()
+ )
cam2MinSize = Collections.min(
Arrays.asList(*map.getOutputSizes(ImageFormat.JPEG)),
- CompareSizesByArea())
+ CompareSizesByArea()
+ )
// Use minimum image size for preview
previewSurfaceView?.holder?.setFixedSize(cam2MinSize.width, cam2MinSize.height)
@@ -247,8 +253,10 @@
fun setAutoFlash(params: CameraParams, requestBuilder: CaptureRequest.Builder?) {
try {
if (params.hasFlash) {
- requestBuilder?.set(CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
+ requestBuilder?.set(
+ CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH
+ )
// Force flash always on
// requestBuilder?.set(CaptureRequest.CONTROL_AE_MODE,
@@ -269,9 +277,11 @@
orientations.append(Surface.ROTATION_180, 270)
orientations.append(Surface.ROTATION_270, 180)
- logd("Orientation: sensor: " +
- params.characteristics?.get(CameraCharacteristics.SENSOR_ORIENTATION) +
- " and current rotation: " + orientations.get(rotation))
+ logd(
+ "Orientation: sensor: " +
+ params.characteristics?.get(CameraCharacteristics.SENSOR_ORIENTATION) +
+ " and current rotation: " + orientations.get(rotation)
+ )
val sensorRotation: Int =
params.characteristics?.get(CameraCharacteristics.SENSOR_ORIENTATION) ?: 0
return (orientations.get(rotation) + sensorRotation + 270) % 360
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/CustomLifecycle.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/CustomLifecycle.kt
index 75c2d95..10efb75 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/CustomLifecycle.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/CustomLifecycle.kt
@@ -47,8 +47,10 @@
}
if (lifecycleRegistry.currentState != Lifecycle.State.CREATED) {
- logd("CustomLifecycle start error: Prior state should be CREATED. Instead it is: " +
- lifecycleRegistry.currentState)
+ logd(
+ "CustomLifecycle start error: Prior state should be CREATED. Instead it is: " +
+ lifecycleRegistry.currentState
+ )
} else {
try {
lifecycleRegistry.currentState = Lifecycle.State.STARTED
@@ -66,8 +68,10 @@
}
if (lifecycleRegistry.currentState != Lifecycle.State.RESUMED) {
- logd("CustomLifecycle pause error: Prior state should be RESUMED. Instead it is: " +
- lifecycleRegistry.currentState)
+ logd(
+ "CustomLifecycle pause error: Prior state should be RESUMED. Instead it is: " +
+ lifecycleRegistry.currentState
+ )
} else {
try {
lifecycleRegistry.currentState = Lifecycle.State.STARTED
@@ -85,8 +89,10 @@
}
if (lifecycleRegistry.currentState != Lifecycle.State.CREATED) {
- logd("CustomLifecycle finish error: Prior state should be CREATED. Instead it is: " +
- lifecycleRegistry.currentState)
+ logd(
+ "CustomLifecycle finish error: Prior state should be CREATED. Instead it is: " +
+ lifecycleRegistry.currentState
+ )
} else {
try {
lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/ImageUtils.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/ImageUtils.kt
index 60c4280..ab92883 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/ImageUtils.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/ImageUtils.kt
@@ -57,8 +57,10 @@
) : ImageReader.OnImageAvailableListener {
override fun onImageAvailable(reader: ImageReader) {
- logd("onImageAvailable enter. Current test: " + testConfig.currentRunningTest +
- " state: " + params.state)
+ logd(
+ "onImageAvailable enter. Current test: " + testConfig.currentRunningTest +
+ " state: " + params.state
+ )
// Only save 1 photo each time
if (CameraState.IMAGE_REQUESTED != params.state)
@@ -81,8 +83,12 @@
val bytes = ByteArray(image.planes[0].buffer.remaining())
image.planes[0].buffer.get(bytes)
- params.backgroundHandler?.post(ImageSaver(activity, bytes, capturedImageRotation,
- params.isFront, params, testConfig))
+ params.backgroundHandler?.post(
+ ImageSaver(
+ activity, bytes, capturedImageRotation,
+ params.isFront, params, testConfig
+ )
+ )
}
// TODO: add RAW support
@@ -140,8 +146,10 @@
fun rotateBitmap(original: Bitmap, degrees: Float): Bitmap {
val matrix = Matrix()
matrix.postRotate(degrees)
- return Bitmap.createBitmap(original, 0, 0, original.width, original.height,
- matrix, true)
+ return Bitmap.createBitmap(
+ original, 0, 0, original.width, original.height,
+ matrix, true
+ )
}
/**
@@ -175,19 +183,25 @@
* Actually write a byteArray file to disk. Assume the file is a jpg and use that extension
*/
fun writeFile(activity: MainActivity, bytes: ByteArray) {
- val jpgFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
+ val jpgFile = File(
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
File.separatorChar + PHOTOS_DIR + File.separatorChar +
- "Antelope" + generateTimestamp() + ".jpg")
+ "Antelope" + generateTimestamp() + ".jpg"
+ )
- val photosDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
- PHOTOS_DIR)
+ val photosDir = File(
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
+ PHOTOS_DIR
+ )
if (!photosDir.exists()) {
val createSuccess = photosDir.mkdir()
if (!createSuccess) {
activity.runOnUiThread {
- Toast.makeText(activity, "DCIM/" + PHOTOS_DIR + " creation failed.",
- Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ activity, "DCIM/" + PHOTOS_DIR + " creation failed.",
+ Toast.LENGTH_SHORT
+ ).show()
}
logd("Photo storage directory DCIM/" + PHOTOS_DIR + " creation failed!!")
} else {
@@ -229,8 +243,10 @@
* Delete all the photos generated by testing from the default Antelope PHOTOS_DIR
*/
fun deleteTestPhotos(activity: MainActivity) {
- val photosDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
- PHOTOS_DIR)
+ val photosDir = File(
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
+ PHOTOS_DIR
+ )
if (photosDir.exists()) {
@@ -283,8 +299,10 @@
/** Image was captured successfully */
override fun onCaptureSuccess(image: ImageProxy) {
- logd("CameraXImageAvailableListener onCaptureSuccess. Current test: " +
- testConfig.currentRunningTest)
+ logd(
+ "CameraXImageAvailableListener onCaptureSuccess. Current test: " +
+ testConfig.currentRunningTest
+ )
when (image.format) {
ImageFormat.JPEG -> {
@@ -311,8 +329,12 @@
val bytes = ByteArray(image.planes[0].buffer.remaining())
image.planes[0].buffer.get(bytes)
- params.backgroundHandler?.post(ImageSaver(activity, bytes, capturedImageRotation,
- params.isFront, params, testConfig))
+ params.backgroundHandler?.post(
+ ImageSaver(
+ activity, bytes, capturedImageRotation,
+ params.isFront, params, testConfig
+ )
+ )
}
ImageFormat.RAW_SENSOR -> {
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/MainActivity.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/MainActivity.kt
index 5664862..433403d 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/MainActivity.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/MainActivity.kt
@@ -138,16 +138,20 @@
}
button_single.setOnClickListener {
- val testDiag = SettingsDialog.newInstance(SettingsDialog.DIALOG_TYPE_SINGLE,
+ val testDiag = SettingsDialog.newInstance(
+ SettingsDialog.DIALOG_TYPE_SINGLE,
getString(R.string.settings_single_test_dialog_title),
- cameras.toTypedArray(), cameraIds.toTypedArray())
+ cameras.toTypedArray(), cameraIds.toTypedArray()
+ )
testDiag.show(supportFragmentManager, SettingsDialog.DIALOG_TYPE_SINGLE)
}
button_multi.setOnClickListener {
- val testDiag = SettingsDialog.newInstance(SettingsDialog.DIALOG_TYPE_MULTI,
+ val testDiag = SettingsDialog.newInstance(
+ SettingsDialog.DIALOG_TYPE_MULTI,
getString(R.string.settings_multi_test_dialog_title),
- cameras.toTypedArray(), cameraIds.toTypedArray())
+ cameras.toTypedArray(), cameraIds.toTypedArray()
+ )
testDiag.show(supportFragmentManager, SettingsDialog.DIALOG_TYPE_MULTI)
}
@@ -219,8 +223,10 @@
as android.content.ClipboardManager
val clip = ClipData.newPlainText("Log", log)
clipboard.setPrimaryClip(clip)
- Toast.makeText(this, getString(R.string.log_copied),
- Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ this, getString(R.string.log_copied),
+ Toast.LENGTH_SHORT
+ ).show()
}
}
}
@@ -259,12 +265,16 @@
*/
fun checkCameraPermissions(): Boolean {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
- != PackageManager.PERMISSION_GRANTED) {
+ != PackageManager.PERMISSION_GRANTED
+ ) {
// Launch the permission request for CAMERA
requestPermission.launch(Manifest.permission.CAMERA)
return false
- } else if (ContextCompat.checkSelfPermission(this,
- Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
+ } else if (ContextCompat.checkSelfPermission(
+ this,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
// Launch the permission request for WRITE_EXTERNAL_STORAGE
requestPermission.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
return false
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/MeasureUtils.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/MeasureUtils.kt
index a85901e..d0b1a6a 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/MeasureUtils.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/MeasureUtils.kt
@@ -27,8 +27,10 @@
internal class CompareSizesByArea : Comparator<Size> {
override fun compare(lhs: Size, rhs: Size): Int {
// We cast here to ensure the multiplications won't overflow
- return java.lang.Long.signum(lhs.width.toLong() * lhs.height -
- rhs.width.toLong() * rhs.height)
+ return java.lang.Long.signum(
+ lhs.width.toLong() * lhs.height -
+ rhs.width.toLong() * rhs.height
+ )
}
}
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/PrefHelper.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/PrefHelper.kt
index ea8f545..9194ee3 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/PrefHelper.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/PrefHelper.kt
@@ -42,15 +42,24 @@
internal fun getNumTests(activity: MainActivity): Int {
val sharedPref: SharedPreferences =
PreferenceManager.getDefaultSharedPreferences(activity)
- return (sharedPref.getString(activity
- .getString(R.string.settings_numtests_key), "30") ?: "30").toInt()
+ return (
+ sharedPref.getString(
+ activity
+ .getString(R.string.settings_numtests_key),
+ "30"
+ ) ?: "30"
+ ).toInt()
}
internal fun getPreviewBuffer(activity: MainActivity): Long {
val sharedPref: SharedPreferences =
PreferenceManager.getDefaultSharedPreferences(activity)
- return (sharedPref.getString(activity.getString(R.string.settings_previewbuffer_key),
- "1500") ?: "1500").toLong()
+ return (
+ sharedPref.getString(
+ activity.getString(R.string.settings_previewbuffer_key),
+ "1500"
+ ) ?: "1500"
+ ).toLong()
}
internal fun getAPIs(activity: MainActivity): ArrayList<CameraAPI> {
@@ -60,8 +69,10 @@
HashSet(activity.resources.getStringArray(R.array.array_settings_api).asList())
val apiStrings: HashSet<String> =
- sharedPref.getStringSet(activity.getString(R.string.settings_autotest_api_key),
- defApis) as HashSet<String>
+ sharedPref.getStringSet(
+ activity.getString(R.string.settings_autotest_api_key),
+ defApis
+ ) as HashSet<String>
val apis: ArrayList<CameraAPI> = ArrayList()
@@ -80,12 +91,17 @@
internal fun getImageSizes(activity: MainActivity): ArrayList<ImageCaptureSize> {
val sharedPref: SharedPreferences =
PreferenceManager.getDefaultSharedPreferences(activity)
- val defSizes: HashSet<String> = HashSet(activity.resources
- .getStringArray(R.array.array_settings_imagesize).asList())
+ val defSizes: HashSet<String> = HashSet(
+ activity.resources
+ .getStringArray(R.array.array_settings_imagesize).asList()
+ )
val sizeStrings: HashSet<String> =
- sharedPref.getStringSet(activity
- .getString(R.string.settings_autotest_imagesize_key), defSizes)
+ sharedPref.getStringSet(
+ activity
+ .getString(R.string.settings_autotest_imagesize_key),
+ defSizes
+ )
as HashSet<String>
val sizes: ArrayList<ImageCaptureSize> = ArrayList()
@@ -108,8 +124,10 @@
HashSet(activity.resources.getStringArray(R.array.array_settings_focus).asList())
val modeStrings: HashSet<String> =
- sharedPref.getStringSet(activity.getString(R.string.settings_autotest_focus_key),
- defModes) as HashSet<String>
+ sharedPref.getStringSet(
+ activity.getString(R.string.settings_autotest_focus_key),
+ defModes
+ ) as HashSet<String>
val modes: ArrayList<FocusMode> = ArrayList()
@@ -128,8 +146,11 @@
internal fun getOnlyLogical(activity: MainActivity): Boolean {
val sharedPref: SharedPreferences =
PreferenceManager.getDefaultSharedPreferences(activity)
- return sharedPref.getBoolean(activity
- .getString(R.string.settings_autotest_cameras_key), true)
+ return sharedPref.getBoolean(
+ activity
+ .getString(R.string.settings_autotest_cameras_key),
+ true
+ )
}
internal fun getSwitchTest(activity: MainActivity): Boolean {
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/SettingsDialog.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/SettingsDialog.kt
index b7da3395..5d944fe 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/SettingsDialog.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/SettingsDialog.kt
@@ -32,8 +32,10 @@
override fun onStart() {
// If we show a dialog with a title, it doesn't take up the whole screen
// Adjust the window to take up the full screen
- dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT)
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT
+ )
super.onStart()
}
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/SingleTestSettingsFragment.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/SingleTestSettingsFragment.kt
index 6288ffb..6196051 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/SingleTestSettingsFragment.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/SingleTestSettingsFragment.kt
@@ -34,7 +34,8 @@
val cameraPref =
preferenceManager.findPreference<ListPreference>(
- getString(R.string.settings_single_test_camera_key))
+ getString(R.string.settings_single_test_camera_key)
+ )
cameraPref?.entries = cameraNames
cameraPref?.entryValues = cameraIds
if (cameraIds.isNotEmpty())
@@ -71,7 +72,8 @@
fun toggleNumTests() {
val typePref =
preferenceManager.findPreference<ListPreference>(
- getString(R.string.settings_single_test_type_key))
+ getString(R.string.settings_single_test_type_key)
+ )
val numberPref = preferenceManager
.findPreference<ListPreference>(getString(R.string.settings_numtests_key))
when (typePref?.value) {
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TestResults.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TestResults.kt
index e82f9c3..79fe505 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TestResults.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TestResults.kt
@@ -193,32 +193,46 @@
when (focusMode) {
FocusMode.CONTINUOUS -> {
- output += outputResultLine("Capture (continuous focus)", capture,
- numCommas, true)
+ output += outputResultLine(
+ "Capture (continuous focus)", capture,
+ numCommas, true
+ )
}
FocusMode.FIXED -> {
- output += outputResultLine("Capture (fixed-focus)", capture,
- numCommas, true)
+ output += outputResultLine(
+ "Capture (fixed-focus)", capture,
+ numCommas, true
+ )
}
else -> {
// CameraX doesn't allow us insight into autofocus
if (CameraAPI.CAMERAX == cameraAPI) {
- output += outputResultLine("Capture incl. autofocus", capture,
- numCommas, true)
+ output += outputResultLine(
+ "Capture incl. autofocus", capture,
+ numCommas, true
+ )
} else {
- output += outputResultLine("Autofocus", autofocus,
- numCommas, true)
- output += outputResultLine("Capture", captureNoAF,
- numCommas, true)
- output += outputResultLine("Capture incl. autofocus", capture,
- numCommas, true)
+ output += outputResultLine(
+ "Autofocus", autofocus,
+ numCommas, true
+ )
+ output += outputResultLine(
+ "Capture", captureNoAF,
+ numCommas, true
+ )
+ output += outputResultLine(
+ "Capture incl. autofocus", capture,
+ numCommas, true
+ )
}
}
}
output += outputResultLine("Image ready", imageready, numCommas, true)
- output += outputResultLine("Cap + img ready", capturePlusImageReady,
- numCommas, true)
+ output += outputResultLine(
+ "Cap + img ready", capturePlusImageReady,
+ numCommas, true
+ )
output += outputResultLine("Image save", imagesave, numCommas, true)
output += outputResultLine("Switch to 2nd", switchToSecond, numCommas, true)
output += outputResultLine("Switch to 1st", switchToFirst, numCommas, true)
@@ -226,8 +240,10 @@
output += outputResultLine("Camera close", cameraClose, numCommas, true)
output += outputBooleanResultLine("HDR+", isHDRPlus, numCommas, true)
output += outputResultLine("Total", total, numCommas, true)
- output += outputResultLine("Total w/o preview buffer", totalNoPreview,
- numCommas, true)
+ output += outputResultLine(
+ "Total w/o preview buffer", totalNoPreview,
+ numCommas, true
+ )
if (1 < capturePlusImageReady.size) {
val captureStats = Stats.of(capturePlusImageReady)
@@ -260,22 +276,35 @@
*/
fun writeCSV(activity: MainActivity, filePrefix: String, csv: String) {
- val csvFile = File(Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_DOCUMENTS),
+ val csvFile = File(
+ Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DOCUMENTS
+ ),
File.separatorChar + MainActivity.LOG_DIR + File.separatorChar +
- filePrefix + "_" + generateCSVTimestamp() + ".csv")
+ filePrefix + "_" + generateCSVTimestamp() + ".csv"
+ )
- val csvDir = File(Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_DOCUMENTS), MainActivity.LOG_DIR)
- val docsDir = File(Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_DOCUMENTS), "")
+ val csvDir = File(
+ Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DOCUMENTS
+ ),
+ MainActivity.LOG_DIR
+ )
+ val docsDir = File(
+ Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DOCUMENTS
+ ),
+ ""
+ )
if (!docsDir.exists()) {
val createSuccess = docsDir.mkdir()
if (!createSuccess) {
activity.runOnUiThread {
- Toast.makeText(activity, "Documents" + " creation failed.",
- Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ activity, "Documents" + " creation failed.",
+ Toast.LENGTH_SHORT
+ ).show()
}
MainActivity.logd("Log storage directory Documents" + " creation failed!!")
} else {
@@ -287,14 +316,22 @@
val createSuccess = csvDir.mkdir()
if (!createSuccess) {
activity.runOnUiThread {
- Toast.makeText(activity, "Documents/" + MainActivity.LOG_DIR +
- " creation failed.", Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ activity,
+ "Documents/" + MainActivity.LOG_DIR +
+ " creation failed.",
+ Toast.LENGTH_SHORT
+ ).show()
}
- MainActivity.logd("Log storage directory Documents/" +
- MainActivity.LOG_DIR + " creation failed!!")
+ MainActivity.logd(
+ "Log storage directory Documents/" +
+ MainActivity.LOG_DIR + " creation failed!!"
+ )
} else {
- MainActivity.logd("Log storage directory Documents/" +
- MainActivity.LOG_DIR + " did not exist. Created.")
+ MainActivity.logd(
+ "Log storage directory Documents/" +
+ MainActivity.LOG_DIR + " did not exist. Created."
+ )
}
}
@@ -323,8 +360,12 @@
* Delete all Antelope .csv files in the documents directory
*/
fun deleteCSVFiles(activity: MainActivity) {
- val csvDir = File(Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_DOCUMENTS), MainActivity.LOG_DIR)
+ val csvDir = File(
+ Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DOCUMENTS
+ ),
+ MainActivity.LOG_DIR
+ )
if (csvDir.exists()) {
@@ -339,7 +380,7 @@
activity.runOnUiThread {
Toast.makeText(activity, "CSV logs deleted", Toast.LENGTH_SHORT).show()
}
- logd("All csv logs in directory DOCUMENTS/" + MainActivity.LOG_DIR + " deleted.")
+ logd("All csv logs in directory DOCUMENTS/" + MainActivity.LOG_DIR + " deleted.")
}
}
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TestUtils.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TestUtils.kt
index 51e345a..5b00e8b 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TestUtils.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TestUtils.kt
@@ -301,30 +301,54 @@
val mainCamera = getMainCamera(activity, allTestResults)
- val c2Auto = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO)
- val c2AutoChain = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO_CHAIN)
- val c2Caf = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO)
- val c2CafChain = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO_CHAIN)
- val c2AutoMin = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MIN, FocusMode.AUTO, TestType.MULTI_PHOTO)
- val c2Switch = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH)
- val c1Auto = findTest(allTestResults, mainCamera, CameraAPI.CAMERA1,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO)
- val c1Caf = findTest(allTestResults, mainCamera, CameraAPI.CAMERA1,
- ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO)
- val c1Switch = findTest(allTestResults, mainCamera, CameraAPI.CAMERA1,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH)
- val cXAuto = findTest(allTestResults, mainCamera, CameraAPI.CAMERAX,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO)
- val cXCaf = findTest(allTestResults, mainCamera, CameraAPI.CAMERAX,
- ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO)
- val cXSwitch = findTest(allTestResults, mainCamera, CameraAPI.CAMERAX,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH)
+ val c2Auto = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO
+ )
+ val c2AutoChain = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO_CHAIN
+ )
+ val c2Caf = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO
+ )
+ val c2CafChain = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO_CHAIN
+ )
+ val c2AutoMin = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MIN, FocusMode.AUTO, TestType.MULTI_PHOTO
+ )
+ val c2Switch = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH
+ )
+ val c1Auto = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA1,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO
+ )
+ val c1Caf = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA1,
+ ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO
+ )
+ val c1Switch = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA1,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH
+ )
+ val cXAuto = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERAX,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO
+ )
+ val cXCaf = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERAX,
+ ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO
+ )
+ val cXSwitch = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERAX,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH
+ )
// Header
val dateFormatter = SimpleDateFormat("d MMM yyyy - kk'h'mm")
@@ -361,9 +385,11 @@
", Cam1 Open: " + meanOfSumOfTwoArrays(c1Auto.initialization, c1Auto.previewStart) +
"\nCam2 Close: " + meanOfSumOfTwoArrays(c2Auto.previewClose, c2Auto.cameraClose) +
", Cam1 Close: " + meanOfSumOfTwoArrays(c1Auto.previewClose, c1Auto.cameraClose) +
- "\n∆ Min to Max Size: " + (numericalMean(c2Auto.capture) +
- numericalMean(c2Auto.imageready) - numericalMean(c2AutoMin.capture) -
- numericalMean(c2AutoMin.imageready)) +
+ "\n∆ Min to Max Size: " + (
+ numericalMean(c2Auto.capture) +
+ numericalMean(c2Auto.imageready) - numericalMean(c2AutoMin.capture) -
+ numericalMean(c2AutoMin.imageready)
+ ) +
", Init->Image saved (Cam2): " + mean(c2Auto.totalNoPreview) +
"\n"
@@ -386,30 +412,54 @@
val mainCamera = getMainCamera(activity, allTestResults)
- val c2Auto = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO)
- val c2AutoChain = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO_CHAIN)
- val c2Caf = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO)
- val c2CafChain = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO_CHAIN)
- val c2AutoMin = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MIN, FocusMode.AUTO, TestType.MULTI_PHOTO)
- val c2Switch = findTest(allTestResults, mainCamera, CameraAPI.CAMERA2,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH)
- val c1Auto = findTest(allTestResults, mainCamera, CameraAPI.CAMERA1,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO)
- val c1Caf = findTest(allTestResults, mainCamera, CameraAPI.CAMERA1,
- ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO)
- val c1Switch = findTest(allTestResults, mainCamera, CameraAPI.CAMERA1,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH)
- val cXAuto = findTest(allTestResults, mainCamera, CameraAPI.CAMERAX,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO)
- val cXCaf = findTest(allTestResults, mainCamera, CameraAPI.CAMERAX,
- ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO)
- val cXSwitch = findTest(allTestResults, mainCamera, CameraAPI.CAMERAX,
- ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH)
+ val c2Auto = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO
+ )
+ val c2AutoChain = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO_CHAIN
+ )
+ val c2Caf = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO
+ )
+ val c2CafChain = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO_CHAIN
+ )
+ val c2AutoMin = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MIN, FocusMode.AUTO, TestType.MULTI_PHOTO
+ )
+ val c2Switch = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA2,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH
+ )
+ val c1Auto = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA1,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO
+ )
+ val c1Caf = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA1,
+ ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO
+ )
+ val c1Switch = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERA1,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH
+ )
+ val cXAuto = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERAX,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_PHOTO
+ )
+ val cXCaf = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERAX,
+ ImageCaptureSize.MAX, FocusMode.CONTINUOUS, TestType.MULTI_PHOTO
+ )
+ val cXSwitch = findTest(
+ allTestResults, mainCamera, CameraAPI.CAMERAX,
+ ImageCaptureSize.MAX, FocusMode.AUTO, TestType.MULTI_SWITCH
+ )
// Header
val dateFormatter = SimpleDateFormat("d MMM yyyy - kk'h'mm")
@@ -456,8 +506,10 @@
meanOfSumOfTwoArrays(c1Auto.initialization, c1Auto.previewStart)
output += "," + meanOfSumOfTwoArrays(c2Auto.previewClose, c2Auto.cameraClose) + "," +
meanOfSumOfTwoArrays(c1Auto.previewClose, c1Auto.cameraClose)
- output += "," + (numericalMean(c2Auto.capture) + numericalMean(c2Auto.imageready) -
- numericalMean(c2AutoMin.capture) - numericalMean(c2AutoMin.imageready))
+ output += "," + (
+ numericalMean(c2Auto.capture) + numericalMean(c2Auto.imageready) -
+ numericalMean(c2AutoMin.capture) - numericalMean(c2AutoMin.imageready)
+ )
output += "," + mean(c2Auto.totalNoPreview) + "\n"
output += "\n"
@@ -482,7 +534,8 @@
testResult.cameraAPI == api &&
testResult.imageCaptureSize == imageCaptureSize &&
(testResult.focusMode == focusMode || testResult.focusMode == FocusMode.FIXED) &&
- testResult.testType == testType) {
+ testResult.testType == testType
+ ) {
return testResult
}
}
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TimingTests.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TimingTests.kt
index 994519f..2e26b3a5 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TimingTests.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/TimingTests.kt
@@ -39,10 +39,13 @@
// Camera1 cannot directly access physical cameras. If we try, abort.
if ((CameraAPI.CAMERA1 == config.api) &&
- !(PrefHelper.getLogicalCameraIds(cameraParams).contains(config.camera))) {
+ !(PrefHelper.getLogicalCameraIds(cameraParams).contains(config.camera))
+ ) {
activity.resetUIAfterTest()
- activity.updateLog("ABORTED: Camera1 API cannot access camera with id:" + config.camera,
- false, false)
+ activity.updateLog(
+ "ABORTED: Camera1 API cannot access camera with id:" + config.camera,
+ false, false
+ )
return
}
@@ -91,10 +94,13 @@
// For switch test, always go from default back camera to default front camera and back 0->1->0
// TODO: Can we handle different permutations of physical cameras?
if (!PrefHelper.getLogicalCameraIds(cameraParams).contains("0") ||
- !PrefHelper.getLogicalCameraIds(cameraParams).contains("1")) {
+ !PrefHelper.getLogicalCameraIds(cameraParams).contains("1")
+ ) {
activity.resetUIAfterTest()
- activity.updateLog("ABORTED: Camera 0 and 1 needed for Switch test.",
- false, false)
+ activity.updateLog(
+ "ABORTED: Camera 0 and 1 needed for Switch test.",
+ false, false
+ )
return
}
@@ -120,10 +126,13 @@
// For switch test, always go from default back camera to default front camera and back 0->1->0
// TODO: Can we handle different permutations of physical cameras?
if (!PrefHelper.getLogicalCameraIds(cameraParams).contains("0") ||
- !PrefHelper.getLogicalCameraIds(cameraParams).contains("1")) {
+ !PrefHelper.getLogicalCameraIds(cameraParams).contains("1")
+ ) {
activity.resetUIAfterTest()
- activity.updateLog("ABORTED: Camera 0 and 1 needed for Switch test.",
- false, false)
+ activity.updateLog(
+ "ABORTED: Camera 0 and 1 needed for Switch test.",
+ false, false
+ )
return
}
@@ -209,8 +218,10 @@
activity.showProgressBar(true, 0)
multiCounter = PrefHelper.getNumTests(activity)
config.currentRunningTest = TestType.MULTI_PHOTO
- logd("About to start multi photo test. multi_counter: " + multiCounter + " and test: " +
- config.currentRunningTest.toString())
+ logd(
+ "About to start multi photo test. multi_counter: " + multiCounter + " and test: " +
+ config.currentRunningTest.toString()
+ )
} else {
// Add previous result
params.timer.testEnd = System.currentTimeMillis()
@@ -222,14 +233,18 @@
config.testResults.previewFill
.add(params.timer.previewFillEnd - params.timer.previewFillStart)
config.testResults.autofocus.add(params.timer.autofocusEnd - params.timer.autofocusStart)
- config.testResults.captureNoAF.add((params.timer.captureEnd - params.timer.captureStart) -
- (params.timer.autofocusEnd - params.timer.autofocusStart))
+ config.testResults.captureNoAF.add(
+ (params.timer.captureEnd - params.timer.captureStart) -
+ (params.timer.autofocusEnd - params.timer.autofocusStart)
+ )
config.testResults.capture.add(params.timer.captureEnd - params.timer.captureStart)
config.testResults.imageready
.add(params.timer.imageReaderEnd - params.timer.imageReaderStart)
config.testResults.capturePlusImageReady
- .add((params.timer.captureEnd - params.timer.captureStart) +
- (params.timer.imageReaderEnd - params.timer.imageReaderStart))
+ .add(
+ (params.timer.captureEnd - params.timer.captureStart) +
+ (params.timer.imageReaderEnd - params.timer.imageReaderStart)
+ )
config.testResults.imagesave
.add(params.timer.imageSaveEnd - params.timer.imageSaveStart)
config.testResults.isHDRPlus.add(params.timer.isHDRPlus)
@@ -238,8 +253,10 @@
config.testResults.cameraClose
.add(params.timer.cameraCloseEnd - params.timer.cameraCloseStart)
config.testResults.total.add(params.timer.testEnd - params.timer.testStart)
- config.testResults.totalNoPreview.add((params.timer.testEnd - params.timer.testStart) -
- (params.timer.previewFillEnd - params.timer.previewFillStart))
+ config.testResults.totalNoPreview.add(
+ (params.timer.testEnd - params.timer.testStart) -
+ (params.timer.previewFillEnd - params.timer.previewFillStart)
+ )
config.testFinished = false
config.isFirstOnActive = true
config.isFirstOnCaptureComplete = true
@@ -277,8 +294,10 @@
params.timer = CameraTimer()
params.timer.testStart = System.currentTimeMillis()
config.currentRunningTest = TestType.MULTI_PHOTO_CHAIN
- logd("About to start multi chain test. multi_counter: " + multiCounter + " and test: " +
- config.currentRunningTest.toString())
+ logd(
+ "About to start multi chain test. multi_counter: " + multiCounter + " and test: " +
+ config.currentRunningTest.toString()
+ )
setupImageReader(activity, params, config)
beginTest(activity, params, config)
@@ -294,14 +313,18 @@
config.testResults.autofocus
.add(params.timer.autofocusEnd - params.timer.autofocusStart)
config.testResults.captureNoAF
- .add((params.timer.captureEnd - params.timer.captureStart) -
- (params.timer.autofocusEnd - params.timer.autofocusStart))
+ .add(
+ (params.timer.captureEnd - params.timer.captureStart) -
+ (params.timer.autofocusEnd - params.timer.autofocusStart)
+ )
config.testResults.capture.add(params.timer.captureEnd - params.timer.captureStart)
config.testResults.imageready
.add(params.timer.imageReaderEnd - params.timer.imageReaderStart)
config.testResults.capturePlusImageReady
- .add((params.timer.captureEnd - params.timer.captureStart) +
- (params.timer.imageReaderEnd - params.timer.imageReaderStart))
+ .add(
+ (params.timer.captureEnd - params.timer.captureStart) +
+ (params.timer.imageReaderEnd - params.timer.imageReaderStart)
+ )
config.testResults.imagesave
.add(params.timer.imageSaveEnd - params.timer.imageSaveStart)
config.testResults.isHDRPlus.add(params.timer.isHDRPlus)
@@ -326,8 +349,10 @@
internal fun testEnded(activity: MainActivity, params: CameraParams?, config: TestConfig) {
if (null == params)
return
- logd("In testEnded. multi_counter: " + multiCounter + " and test: " +
- config.currentRunningTest.toString())
+ logd(
+ "In testEnded. multi_counter: " + multiCounter + " and test: " +
+ config.currentRunningTest.toString()
+ )
when (config.currentRunningTest) {
@@ -391,8 +416,10 @@
multiCounter = 0
} else {
- logd("Switch " + (Math.abs(multiCounter - PrefHelper.getNumTests(activity)) + 1) +
- " completed.")
+ logd(
+ "Switch " + (Math.abs(multiCounter - PrefHelper.getNumTests(activity)) + 1) +
+ " completed."
+ )
multiCounter--
runMultiSwitchTest(activity, params, config)
return
@@ -409,14 +436,18 @@
config.testResults.autofocus
.add(params.timer.autofocusEnd - params.timer.autofocusStart)
config.testResults.captureNoAF
- .add((params.timer.captureEnd - params.timer.captureStart) -
- (params.timer.autofocusEnd - params.timer.autofocusStart))
+ .add(
+ (params.timer.captureEnd - params.timer.captureStart) -
+ (params.timer.autofocusEnd - params.timer.autofocusStart)
+ )
config.testResults.capture.add(params.timer.captureEnd - params.timer.captureStart)
config.testResults.imageready
.add(params.timer.imageReaderEnd - params.timer.imageReaderStart)
config.testResults.capturePlusImageReady
- .add((params.timer.captureEnd - params.timer.captureStart) +
- (params.timer.imageReaderEnd - params.timer.imageReaderStart))
+ .add(
+ (params.timer.captureEnd - params.timer.captureStart) +
+ (params.timer.imageReaderEnd - params.timer.imageReaderStart)
+ )
config.testResults.imagesave
.add(params.timer.imageSaveEnd - params.timer.imageSaveStart)
config.testResults.isHDRPlus
@@ -426,8 +457,10 @@
config.testResults.cameraClose
.add(params.timer.cameraCloseEnd - params.timer.cameraCloseStart)
config.testResults.total.add(params.timer.testEnd - params.timer.testStart)
- config.testResults.totalNoPreview.add((params.timer.testEnd - params.timer.testStart) -
- (params.timer.previewFillEnd - params.timer.previewFillStart))
+ config.testResults.totalNoPreview.add(
+ (params.timer.testEnd - params.timer.testStart) -
+ (params.timer.previewFillEnd - params.timer.previewFillStart)
+ )
}
TestType.MULTI_PHOTO -> {
@@ -448,14 +481,18 @@
config.testResults.autofocus
.add(params.timer.autofocusEnd - params.timer.autofocusStart)
config.testResults.captureNoAF
- .add((params.timer.captureEnd - params.timer.captureStart) -
- (params.timer.autofocusEnd - params.timer.autofocusStart))
+ .add(
+ (params.timer.captureEnd - params.timer.captureStart) -
+ (params.timer.autofocusEnd - params.timer.autofocusStart)
+ )
config.testResults.capture.add(params.timer.captureEnd - params.timer.captureStart)
config.testResults.imageready
.add(params.timer.imageReaderEnd - params.timer.imageReaderStart)
config.testResults.capturePlusImageReady
- .add((params.timer.captureEnd - params.timer.captureStart) +
- (params.timer.imageReaderEnd - params.timer.imageReaderStart))
+ .add(
+ (params.timer.captureEnd - params.timer.captureStart) +
+ (params.timer.imageReaderEnd - params.timer.imageReaderStart)
+ )
config.testResults.imagesave
.add(params.timer.imageSaveEnd - params.timer.imageSaveStart)
config.testResults.isHDRPlus.add(params.timer.isHDRPlus)
@@ -465,13 +502,17 @@
.add(params.timer.cameraCloseEnd - params.timer.cameraCloseStart)
config.testResults.total.add(params.timer.testEnd - params.timer.testStart)
config.testResults.totalNoPreview
- .add((params.timer.testEnd - params.timer.testStart) -
- (params.timer.previewFillEnd - params.timer.previewFillStart))
+ .add(
+ (params.timer.testEnd - params.timer.testStart) -
+ (params.timer.previewFillEnd - params.timer.previewFillStart)
+ )
multiCounter = 0
} else {
- logd("Capture " + (Math.abs(multiCounter - PrefHelper.getNumTests(activity)) + 1) +
- " completed: " + lastResult + "ms")
+ logd(
+ "Capture " + (Math.abs(multiCounter - PrefHelper.getNumTests(activity)) + 1) +
+ " completed: " + lastResult + "ms"
+ )
multiCounter--
runMultiPhotoTest(activity, params, config)
return
@@ -496,39 +537,65 @@
activity.showProgressBar(true, precentageCompleted(activity, multiCounter))
- config.testResults.initialization.add(params.timer.openEnd -
- params.timer.openStart)
- config.testResults.previewStart.add(params.timer.previewEnd -
- params.timer.previewStart)
- config.testResults.previewFill.add(params.timer.previewFillEnd -
- params.timer.previewFillStart)
- config.testResults.autofocus.add(params.timer.autofocusEnd -
- params.timer.autofocusStart)
+ config.testResults.initialization.add(
+ params.timer.openEnd -
+ params.timer.openStart
+ )
+ config.testResults.previewStart.add(
+ params.timer.previewEnd -
+ params.timer.previewStart
+ )
+ config.testResults.previewFill.add(
+ params.timer.previewFillEnd -
+ params.timer.previewFillStart
+ )
+ config.testResults.autofocus.add(
+ params.timer.autofocusEnd -
+ params.timer.autofocusStart
+ )
config.testResults.captureNoAF
- .add((params.timer.captureEnd - params.timer.captureStart) -
- (params.timer.autofocusEnd - params.timer.autofocusStart))
+ .add(
+ (params.timer.captureEnd - params.timer.captureStart) -
+ (params.timer.autofocusEnd - params.timer.autofocusStart)
+ )
config.testResults.capture.add(params.timer.captureEnd - params.timer.captureStart)
- config.testResults.imageready.add(params.timer.imageReaderEnd -
- params.timer.imageReaderStart)
- config.testResults.capturePlusImageReady.add((params.timer.captureEnd -
- params.timer.captureStart) +
- (params.timer.imageReaderEnd - params.timer.imageReaderStart))
- config.testResults.imagesave.add(params.timer.imageSaveEnd -
- params.timer.imageSaveStart)
+ config.testResults.imageready.add(
+ params.timer.imageReaderEnd -
+ params.timer.imageReaderStart
+ )
+ config.testResults.capturePlusImageReady.add(
+ (
+ params.timer.captureEnd -
+ params.timer.captureStart
+ ) +
+ (params.timer.imageReaderEnd - params.timer.imageReaderStart)
+ )
+ config.testResults.imagesave.add(
+ params.timer.imageSaveEnd -
+ params.timer.imageSaveStart
+ )
config.testResults.isHDRPlus.add(params.timer.isHDRPlus)
- config.testResults.previewClose.add(params.timer.previewCloseEnd -
- params.timer.previewCloseStart)
- config.testResults.cameraClose.add(params.timer.cameraCloseEnd -
- params.timer.cameraCloseStart)
+ config.testResults.previewClose.add(
+ params.timer.previewCloseEnd -
+ params.timer.previewCloseStart
+ )
+ config.testResults.cameraClose.add(
+ params.timer.cameraCloseEnd -
+ params.timer.cameraCloseStart
+ )
config.testResults.total.add(params.timer.testEnd - params.timer.testStart)
config.testResults.totalNoPreview
- .add((params.timer.testEnd - params.timer.testStart) -
- (params.timer.previewFillEnd - params.timer.previewFillStart))
+ .add(
+ (params.timer.testEnd - params.timer.testStart) -
+ (params.timer.previewFillEnd - params.timer.previewFillStart)
+ )
multiCounter = 0
} else {
- logd("Capture " + (Math.abs(multiCounter - PrefHelper.getNumTests(activity)) + 1) +
- " completed: " + lastResult + "ms")
+ logd(
+ "Capture " + (Math.abs(multiCounter - PrefHelper.getNumTests(activity)) + 1) +
+ " completed: " + lastResult + "ms"
+ )
multiCounter--
runMultiPhotoChainTest(activity, params, config)
return
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera1Controller.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera1Controller.kt
index b3203be..a8c2c56 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera1Controller.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera1Controller.kt
@@ -50,7 +50,8 @@
logd("Camera1Switch Open camera: " + testConfig.switchTestCurrentCamera.toInt())
if ((testConfig.currentRunningTest == TestType.SWITCH_CAMERA) ||
- (testConfig.currentRunningTest == TestType.MULTI_SWITCH))
+ (testConfig.currentRunningTest == TestType.MULTI_SWITCH)
+ )
camera1 = Camera.open(testConfig.switchTestCurrentCamera.toInt())
else
camera1 = Camera.open(testConfig.camera.toInt())
@@ -61,7 +62,7 @@
val camera1Params: Camera.Parameters? = camera1?.parameters
params.cam1AFSupported =
camera1Params?.supportedFocusModes?.contains(Camera.Parameters.FOCUS_MODE_AUTO)
- ?: false
+ ?: false
when (testConfig.currentRunningTest) {
TestType.INIT -> {
@@ -148,8 +149,10 @@
closePreviewAndCamera(activity, params, testConfig)
}
} else {
- logd("Camera1Switch preview. On 2nd camera. Closing, ready to open first 1st " +
- "camera")
+ logd(
+ "Camera1Switch preview. On 2nd camera. Closing, ready to open first 1st " +
+ "camera"
+ )
params.timer.switchToSecondEnd = System.currentTimeMillis()
Thread.sleep(PrefHelper.getPreviewBuffer(activity)) // Let preview run
params.timer.switchToFirstStart = System.currentTimeMillis()
@@ -173,8 +176,10 @@
*/
fun camera1TakePicturePrep(activity: MainActivity, params: CameraParams, testConfig: TestConfig) {
if (params.timer.isFirstPhoto) {
- logd("camera1TakePicturePrep: 1st photo in multi-chain test. Pausing for " +
- PrefHelper.getPreviewBuffer(activity) + "ms to let preview run.")
+ logd(
+ "camera1TakePicturePrep: 1st photo in multi-chain test. Pausing for " +
+ PrefHelper.getPreviewBuffer(activity) + "ms to let preview run."
+ )
params.timer.previewFillStart = System.currentTimeMillis()
Thread.sleep(PrefHelper.getPreviewBuffer(activity))
params.timer.previewFillEnd = System.currentTimeMillis()
@@ -184,7 +189,8 @@
params.timer.captureStart = System.currentTimeMillis()
if (params.cam1AFSupported &&
- FocusMode.AUTO == testConfig.focusMode) {
+ FocusMode.AUTO == testConfig.focusMode
+ ) {
MainActivity.logd("camera1TakePicturePrep: starting autofocus.")
params.timer.autofocusStart = System.currentTimeMillis()
camera1?.autoFocus(Camera1AutofocusCallback(activity, params, testConfig))
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2CaptureCallback.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2CaptureCallback.kt
index 1712e32..8401722 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2CaptureCallback.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2CaptureCallback.kt
@@ -38,9 +38,11 @@
) : CameraCaptureSession.CaptureCallback() {
override fun onCaptureSequenceAborted(session: CameraCaptureSession, sequenceId: Int) {
- MainActivity.logd("captureStillPicture captureCallback: Sequence aborted. Current test: " +
- testConfig.currentRunningTest.toString())
- super.onCaptureSequenceAborted(session, sequenceId)
+ MainActivity.logd(
+ "captureStillPicture captureCallback: Sequence aborted. Current test: " +
+ testConfig.currentRunningTest.toString()
+ )
+ super.onCaptureSequenceAborted(session, sequenceId)
}
override fun onCaptureFailed(
@@ -53,8 +55,10 @@
return
}
- MainActivity.logd("captureStillPicture captureCallback: Capture Failed. Failure: " +
- failure.reason + " Current test: " + testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "captureStillPicture captureCallback: Capture Failed. Failure: " +
+ failure.reason + " Current test: " + testConfig.currentRunningTest.toString()
+ )
// The session failed. Let's just try again (yay infinite loops)
closePreviewAndCamera(activity, params, testConfig)
@@ -68,8 +72,10 @@
timestamp: Long,
frameNumber: Long
) {
- MainActivity.logd("captureStillPicture captureCallback: Capture Started. Current test: " +
- testConfig.currentRunningTest.toString() + ", frame number: " + frameNumber)
+ MainActivity.logd(
+ "captureStillPicture captureCallback: Capture Started. Current test: " +
+ testConfig.currentRunningTest.toString() + ", frame number: " + frameNumber
+ )
super.onCaptureStarted(session, request, timestamp, frameNumber)
}
@@ -78,8 +84,10 @@
request: CaptureRequest,
partialResult: CaptureResult
) {
- MainActivity.logd("captureStillPicture captureCallback: Capture progressed. " +
- "Current test: " + testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "captureStillPicture captureCallback: Capture progressed. " +
+ "Current test: " + testConfig.currentRunningTest.toString()
+ )
super.onCaptureProgressed(session, request, partialResult)
}
@@ -89,8 +97,10 @@
target: Surface,
frameNumber: Long
) {
- MainActivity.logd("captureStillPicture captureCallback: Buffer lost. Current test: " +
- testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "captureStillPicture captureCallback: Buffer lost. Current test: " +
+ testConfig.currentRunningTest.toString()
+ )
super.onCaptureBufferLost(session, request, target, frameNumber)
}
@@ -104,8 +114,10 @@
return
}
- MainActivity.logd("Camera2 onCaptureCompleted. CaptureEnd. Current test: " +
- testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "Camera2 onCaptureCompleted. CaptureEnd. Current test: " +
+ testConfig.currentRunningTest.toString()
+ )
params.timer.captureEnd = System.currentTimeMillis()
@@ -115,8 +127,10 @@
// ImageReader might get the image before this callback is called, if so, the test is done
if (0L != params.timer.imageSaveEnd) {
params.timer.imageReaderStart = params.timer.imageReaderEnd // No ImageReader delay
- MainActivity.logd("Camera2 onCaptureCompleted. Image already saved. " +
- "Ending Test and closing camera.")
+ MainActivity.logd(
+ "Camera2 onCaptureCompleted. Image already saved. " +
+ "Ending Test and closing camera."
+ )
if (TestType.MULTI_PHOTO_CHAIN == testConfig.currentRunningTest) {
testEnded(activity, params, testConfig)
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2CaptureSessionCallback.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2CaptureSessionCallback.kt
index 02e680a..04c128e 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2CaptureSessionCallback.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2CaptureSessionCallback.kt
@@ -57,8 +57,10 @@
request: CaptureRequest,
failure: CaptureFailure
) {
- MainActivity.logd("Camera2CaptureSessionCallback : Capture sequence FAILED - " +
- failure.reason)
+ MainActivity.logd(
+ "Camera2CaptureSessionCallback : Capture sequence FAILED - " +
+ failure.reason
+ )
if (!params.isOpen) {
return
@@ -84,13 +86,17 @@
// We are waiting for AF and AE to converge, check if this has happened
CameraState.WAITING_FOCUS_LOCK -> {
val afState = result.get(CaptureResult.CONTROL_AF_STATE)
- MainActivity.logd("Camera2CaptureSessionCallback: STATE_WAITING_LOCK, afstate == " +
- afState + ", frame number: " + result.frameNumber)
+ MainActivity.logd(
+ "Camera2CaptureSessionCallback: STATE_WAITING_LOCK, afstate == " +
+ afState + ", frame number: " + result.frameNumber
+ )
when (afState) {
null -> {
- MainActivity.logd("Camera2CaptureSessionCallback: STATE_WAITING_LOCK, " +
- "afState == null, Calling captureStillPicture!")
+ MainActivity.logd(
+ "Camera2CaptureSessionCallback: STATE_WAITING_LOCK, " +
+ "afState == null, Calling captureStillPicture!"
+ )
params.state = CameraState.IMAGE_REQUESTED
captureStillPicture(activity, params, testConfig)
}
@@ -102,8 +108,10 @@
// some devices this can be longer or get stuck indefinitely. If AF has not
// started after 50 frames, just run the capture.
if (params.autoFocusStuckCounter++ > 50) {
- MainActivity.logd("Camera2CaptureSessionCallback : " +
- "STATE_WAITING_LOCK, AF is stuck! Calling captureStillPicture!")
+ MainActivity.logd(
+ "Camera2CaptureSessionCallback : " +
+ "STATE_WAITING_LOCK, AF is stuck! Calling captureStillPicture!"
+ )
params.state = CameraState.IMAGE_REQUESTED
captureStillPicture(activity, params, testConfig)
}
@@ -115,10 +123,13 @@
// AF is locked, check AE. Note CONTROL_AE_STATE can be null on some devices
val aeState = result.get(CaptureResult.CONTROL_AE_STATE)
if (aeState == null ||
- aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
- MainActivity.logd("Camera2CaptureSessionCallback : " +
- "STATE_WAITING_LOCK, AF and AE converged! " +
- "Calling captureStillPicture!")
+ aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED
+ ) {
+ MainActivity.logd(
+ "Camera2CaptureSessionCallback : " +
+ "STATE_WAITING_LOCK, AF and AE converged! " +
+ "Calling captureStillPicture!"
+ )
params.state = CameraState.IMAGE_REQUESTED
captureStillPicture(activity, params, testConfig)
} else {
@@ -141,8 +152,10 @@
// No aeState on this device, just do the capture
if (aeState == null) {
- MainActivity.logd("Camera2CaptureSessionCallback : STATE_WAITING_PRECAPTURE, " +
- "aeState == null, Calling captureStillPicture!")
+ MainActivity.logd(
+ "Camera2CaptureSessionCallback : STATE_WAITING_PRECAPTURE, " +
+ "aeState == null, Calling captureStillPicture!"
+ )
params.state = CameraState.IMAGE_REQUESTED
captureStillPicture(activity, params, testConfig)
} else when (aeState) {
@@ -161,9 +174,11 @@
// just do the capture to avoid getting stuck.
CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED,
CaptureResult.CONTROL_AE_STATE_INACTIVE -> {
- MainActivity.logd("Camera2CaptureSessionCallback : " +
- "STATE_WAITING_PRECAPTURE, aeState: " + aeState +
- ", AE stuck or needs flash, calling captureStillPicture!")
+ MainActivity.logd(
+ "Camera2CaptureSessionCallback : " +
+ "STATE_WAITING_PRECAPTURE, aeState: " + aeState +
+ ", AE stuck or needs flash, calling captureStillPicture!"
+ )
params.state = CameraState.IMAGE_REQUESTED
captureStillPicture(activity, params, testConfig)
}
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2Controller.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2Controller.kt
index 7a1faa0..9b1d8fd 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2Controller.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2Controller.kt
@@ -56,7 +56,8 @@
try {
// TODO make the switch test methodology more robust and handle physical cameras
if ((testConfig.currentRunningTest == TestType.SWITCH_CAMERA) ||
- (testConfig.currentRunningTest == TestType.MULTI_SWITCH)) {
+ (testConfig.currentRunningTest == TestType.MULTI_SWITCH)
+ ) {
testConfig.switchTestRealCameraId = params.id // Save the original camera ID
params.id = testConfig.switchTestCurrentCamera
}
@@ -67,8 +68,10 @@
Camera2CaptureSessionCallback(activity, params, testConfig)
params.timer.openStart = System.currentTimeMillis()
- logd("openCamera: " + params.id + " running test: " +
- testConfig.currentRunningTest.toString())
+ logd(
+ "openCamera: " + params.id + " running test: " +
+ testConfig.currentRunningTest.toString()
+ )
manager.openCamera(params.id, params.camera2DeviceStateCallback!!, params.backgroundHandler)
} catch (e: CameraAccessException) {
@@ -111,8 +114,10 @@
params.captureRequestBuilder?.addTarget(surface)
@Suppress("DEPRECATION")
- params.device?.createCaptureSession(Arrays.asList(surface, imageSurface),
- Camera2PreviewSessionStateCallback(activity, params, testConfig), null)
+ params.device?.createCaptureSession(
+ Arrays.asList(surface, imageSurface),
+ Camera2PreviewSessionStateCallback(activity, params, testConfig), null
+ )
} catch (e: CameraAccessException) {
MainActivity.logd("createCameraPreviewSession CameraAccessException: " + e.message)
e.printStackTrace()
@@ -137,8 +142,10 @@
params.timer.isFirstPhoto = false
}
- logd("Camera2 initializeStillCapture: 1st photo in a multi-photo test. " +
- "Pausing for " + PrefHelper.getPreviewBuffer(activity) + "ms to let preview run.")
+ logd(
+ "Camera2 initializeStillCapture: 1st photo in a multi-photo test. " +
+ "Pausing for " + PrefHelper.getPreviewBuffer(activity) + "ms to let preview run."
+ )
params.timer.previewFillStart = System.currentTimeMillis()
sleep(PrefHelper.getPreviewBuffer(activity))
params.timer.previewFillEnd = System.currentTimeMillis()
@@ -165,26 +172,39 @@
// If this lens can focus, we need to start a focus search and wait for focus lock
if (params.hasAF &&
- FocusMode.AUTO == testConfig.focusMode) {
+ FocusMode.AUTO == testConfig.focusMode
+ ) {
logd("In lockFocus. About to request focus lock and call capture.")
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_AUTO)
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AF_TRIGGER,
- CameraMetadata.CONTROL_AF_TRIGGER_CANCEL)
- params.camera2CaptureSession?.capture(params.captureRequestBuilder?.build()!!,
- params.camera2CaptureSessionCallback, params.backgroundHandler)
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_AUTO
+ )
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AF_TRIGGER,
+ CameraMetadata.CONTROL_AF_TRIGGER_CANCEL
+ )
+ params.camera2CaptureSession?.capture(
+ params.captureRequestBuilder?.build()!!,
+ params.camera2CaptureSessionCallback, params.backgroundHandler
+ )
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_AUTO)
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AF_TRIGGER,
- CameraMetadata.CONTROL_AF_TRIGGER_START)
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_AUTO
+ )
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AF_TRIGGER,
+ CameraMetadata.CONTROL_AF_TRIGGER_START
+ )
params.state = CameraState.WAITING_FOCUS_LOCK
params.autoFocusStuckCounter = 0
- params.camera2CaptureSession?.capture(params.captureRequestBuilder?.build()!!,
- params.camera2CaptureSessionCallback, params.backgroundHandler)
+ params.camera2CaptureSession?.capture(
+ params.captureRequestBuilder?.build()!!,
+ params.camera2CaptureSessionCallback, params.backgroundHandler
+ )
} else {
// If no auto-focus requested, go ahead to the still capture routine
logd("In lockFocus. Fixed focus or continuous focus, calling captureStillPicture.")
@@ -208,12 +228,16 @@
try {
if (null != params.device) {
setAutoFlash(params, params.captureRequestBuilder)
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
- CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START)
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+ CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START
+ )
params.state = CameraState.WAITING_EXPOSURE_LOCK
- params.camera2CaptureSession?.capture(params.captureRequestBuilder?.build()!!,
- params.camera2CaptureSessionCallback, params.backgroundHandler)
+ params.camera2CaptureSession?.capture(
+ params.captureRequestBuilder?.build()!!,
+ params.camera2CaptureSessionCallback, params.backgroundHandler
+ )
}
} catch (e: CameraAccessException) {
e.printStackTrace()
@@ -243,12 +267,16 @@
when (testConfig.focusMode) {
FocusMode.CONTINUOUS -> {
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
+ )
}
FocusMode.AUTO -> {
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AF_TRIGGER,
- CameraMetadata.CONTROL_AF_TRIGGER_IDLE)
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AF_TRIGGER,
+ CameraMetadata.CONTROL_AF_TRIGGER_IDLE
+ )
}
FocusMode.FIXED -> {
}
@@ -272,8 +300,10 @@
setAutoFlash(params, params.captureRequestBuilder)
val captureCallback = Camera2CaptureCallback(activity, params, testConfig)
- params.camera2CaptureSession?.capture(params.captureRequestBuilder?.build()!!,
- captureCallback, params.backgroundHandler)
+ params.camera2CaptureSession?.capture(
+ params.captureRequestBuilder?.build()!!,
+ captureCallback, params.backgroundHandler
+ )
}
} catch (e: CameraAccessException) {
e.printStackTrace()
@@ -299,7 +329,8 @@
}
if ((testConfig.currentRunningTest == TestType.SWITCH_CAMERA) ||
- (testConfig.currentRunningTest == TestType.MULTI_SWITCH)) {
+ (testConfig.currentRunningTest == TestType.MULTI_SWITCH)
+ ) {
params.id = testConfig.switchTestRealCameraId // Restore the actual camera ID
}
}
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2DeviceStateCallback.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2DeviceStateCallback.kt
index 7404d0e..17483c1 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2DeviceStateCallback.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2DeviceStateCallback.kt
@@ -37,8 +37,10 @@
*/
override fun onOpened(cameraDevice: CameraDevice) {
params.timer.openEnd = System.currentTimeMillis()
- MainActivity.logd("In CameraStateCallback onOpened: " + cameraDevice.id +
- " current test: " + testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "In CameraStateCallback onOpened: " + cameraDevice.id +
+ " current test: " + testConfig.currentRunningTest.toString()
+ )
params.isOpen = true
params.device = cameraDevice
@@ -62,8 +64,10 @@
* If this is a switch test, swizzle camera ids and move to the next step of the test.
*/
override fun onClosed(camera: CameraDevice) {
- MainActivity.logd("In CameraStateCallback onClosed. Camera: " + params.id +
- " is closed. testFinished: " + testConfig.testFinished)
+ MainActivity.logd(
+ "In CameraStateCallback onClosed. Camera: " + params.id +
+ " is closed. testFinished: " + testConfig.testFinished
+ )
params.isOpen = false
if (testConfig.testFinished) {
@@ -74,7 +78,8 @@
}
if ((testConfig.currentRunningTest == TestType.SWITCH_CAMERA) ||
- (testConfig.currentRunningTest == TestType.MULTI_SWITCH)) {
+ (testConfig.currentRunningTest == TestType.MULTI_SWITCH)
+ ) {
// First camera closed, now start the second
if (testConfig.switchTestCurrentCamera == testConfig.switchTestCameras.get(0)) {
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2PreviewSessionStateCallback.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2PreviewSessionStateCallback.kt
index aef5c89..8366fc0 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2PreviewSessionStateCallback.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/Camera2PreviewSessionStateCallback.kt
@@ -100,16 +100,22 @@
try {
when (testConfig.focusMode) {
FocusMode.AUTO -> {
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_AUTO)
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_AUTO
+ )
}
FocusMode.CONTINUOUS -> {
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
+ )
}
FocusMode.FIXED -> {
- params.captureRequestBuilder?.set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_AUTO)
+ params.captureRequestBuilder?.set(
+ CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_AUTO
+ )
}
}
@@ -120,14 +126,18 @@
params.state = CameraState.PREVIEW_RUNNING
// Request that the camera preview begins
- cameraCaptureSession.setRepeatingRequest(params.captureRequestBuilder?.build()!!,
- params.camera2CaptureSessionCallback, params.backgroundHandler)
+ cameraCaptureSession.setRepeatingRequest(
+ params.captureRequestBuilder?.build()!!,
+ params.camera2CaptureSessionCallback, params.backgroundHandler
+ )
} catch (e: CameraAccessException) {
MainActivity.logd("Create Capture Session error: " + params.id)
e.printStackTrace()
} catch (e: IllegalStateException) {
- MainActivity.logd("createCameraPreviewSession onConfigured, IllegalStateException," +
- " aborting: " + e)
+ MainActivity.logd(
+ "createCameraPreviewSession onConfigured, IllegalStateException," +
+ " aborting: " + e
+ )
}
}
@@ -187,7 +197,9 @@
params.timer.cameraCloseStart = System.currentTimeMillis()
params.device?.close()
}
- }, null)
+ },
+ null
+ )
} catch (e: CameraAccessException) {
MainActivity.logd("createCameraPreviewSession CameraAccessException: " + e.message)
e.printStackTrace()
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXCaptureSessionCallback.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXCaptureSessionCallback.kt
index e5f714c..58d3974 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXCaptureSessionCallback.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXCaptureSessionCallback.kt
@@ -40,8 +40,10 @@
/** Capture has been aborted. */
override fun onCaptureSequenceAborted(session: CameraCaptureSession, sequenceId: Int) {
- MainActivity.logd("CameraX captureCallback: Sequence aborted. Current test: " +
- testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "CameraX captureCallback: Sequence aborted. Current test: " +
+ testConfig.currentRunningTest.toString()
+ )
super.onCaptureSequenceAborted(session, sequenceId)
}
@@ -51,8 +53,10 @@
request: CaptureRequest,
failure: CaptureFailure
) {
- MainActivity.logd("CameraX captureStillPicture captureCallback: Capture Failed. Failure: " +
- failure.reason + " Current test: " + testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "CameraX captureStillPicture captureCallback: Capture Failed. Failure: " +
+ failure.reason + " Current test: " + testConfig.currentRunningTest.toString()
+ )
closeCameraX(activity, params, testConfig)
cameraXOpenCamera(activity, params, testConfig)
}
@@ -112,14 +116,18 @@
}
params.timer.captureEnd = System.currentTimeMillis()
- MainActivity.logd("CameraX StillCapture completed. CaptureEnd. Current test: " +
- testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "CameraX StillCapture completed. CaptureEnd. Current test: " +
+ testConfig.currentRunningTest.toString()
+ )
// ImageReader might get the image before this callback is called, if so, the test is done
if (0L != params.timer.imageSaveEnd) {
params.timer.imageReaderStart = params.timer.imageReaderEnd // No ImageReader delay
- MainActivity.logd("StillCapture completed. Ending Test. Current test: " +
- testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "StillCapture completed. Ending Test. Current test: " +
+ testConfig.currentRunningTest.toString()
+ )
if (TestType.MULTI_PHOTO_CHAIN == testConfig.currentRunningTest) {
testEnded(activity, params, testConfig)
@@ -128,8 +136,10 @@
closeCameraX(activity, params, testConfig)
}
} else {
- MainActivity.logd("StillCapture completed. Waiting on imageReader. Current test: " +
- testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "StillCapture completed. Waiting on imageReader. Current test: " +
+ testConfig.currentRunningTest.toString()
+ )
params.timer.imageReaderStart = System.currentTimeMillis()
}
}
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt
index cd51f6b..e147a94 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt
@@ -104,8 +104,10 @@
previewUseCase.setSurfaceProvider { surfaceRequest ->
// Create the SurfaceTexture and Surface
val surfaceTexture = SurfaceTexture(0)
- surfaceTexture.setDefaultBufferSize(surfaceRequest.resolution.width,
- surfaceRequest.resolution.height)
+ surfaceTexture.setDefaultBufferSize(
+ surfaceRequest.resolution.width,
+ surfaceRequest.resolution.height
+ )
surfaceTexture.detachFromGLContext()
val surface = Surface(surfaceTexture)
@@ -119,10 +121,13 @@
// Surface provided to camera for producing buffers into and
// Release the SurfaceTexture and Surface once camera is done with it
- surfaceRequest.provideSurface(surface, CameraXExecutors.directExecutor(), Consumer {
+ surfaceRequest.provideSurface(
+ surface, CameraXExecutors.directExecutor(),
+ Consumer {
surface.release()
surfaceTexture.release()
- })
+ }
+ )
}
}
@@ -232,7 +237,7 @@
// Pause in multi-captures to make sure HDR routines don't get overloaded
logd(
"CameraX TakePicture. Pausing for " +
- PrefHelper.getPreviewBuffer(activity) + "ms to let preview run."
+ PrefHelper.getPreviewBuffer(activity) + "ms to let preview run."
)
params.timer.previewFillStart = System.currentTimeMillis()
@@ -327,7 +332,7 @@
private fun cameraXImageCaptureUseCaseBuilder(
focusMode: FocusMode,
deviceStateCallback:
- CameraDevice.StateCallback,
+ CameraDevice.StateCallback,
sessionCaptureCallback: CameraCaptureSession.CaptureCallback
): ImageCapture.Builder {
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXDeviceStateCallback.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXDeviceStateCallback.kt
index 7cb17c1..bdc8cdc 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXDeviceStateCallback.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXDeviceStateCallback.kt
@@ -36,8 +36,10 @@
* Camera device has opened successfully, record timing and initiate the preview stream.
*/
override fun onOpened(cameraDevice: CameraDevice) {
- MainActivity.logd("In CameraXStateCallback onOpened: " + cameraDevice.id +
- " current test: " + testConfig.currentRunningTest.toString())
+ MainActivity.logd(
+ "In CameraXStateCallback onOpened: " + cameraDevice.id +
+ " current test: " + testConfig.currentRunningTest.toString()
+ )
params.timer.openEnd = System.currentTimeMillis()
params.isOpen = true
@@ -72,7 +74,8 @@
}
if ((testConfig.currentRunningTest == TestType.SWITCH_CAMERA) ||
- (testConfig.currentRunningTest == TestType.MULTI_SWITCH)) {
+ (testConfig.currentRunningTest == TestType.MULTI_SWITCH)
+ ) {
// First camera closed, now start the second
if (testConfig.switchTestCurrentCamera == testConfig.switchTestCameras.get(0)) {
@@ -102,8 +105,10 @@
* Camera device has thrown an error. Try to recover or fail gracefully.
*/
override fun onError(cameraDevice: CameraDevice, error: Int) {
- MainActivity.logd("In CameraXStateCallback onError: " +
- cameraDevice.id + " and error: " + error)
+ MainActivity.logd(
+ "In CameraXStateCallback onError: " +
+ cameraDevice.id + " and error: " + error
+ )
when (error) {
CameraDevice.StateCallback.ERROR_MAX_CAMERAS_IN_USE -> {
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXPreviewSessionStateCallback.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXPreviewSessionStateCallback.kt
index fa1a58d..ee1f1e6 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXPreviewSessionStateCallback.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXPreviewSessionStateCallback.kt
@@ -45,7 +45,8 @@
// Prevent duplicate captures from being triggered if running a capture test
if (testConfig.currentRunningTest != TestType.MULTI_SWITCH &&
- testConfig.currentRunningTest != TestType.SWITCH_CAMERA) {
+ testConfig.currentRunningTest != TestType.SWITCH_CAMERA
+ ) {
if (testConfig.isFirstOnActive) {
testConfig.isFirstOnActive = false
} else {
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageAnalysisBaseTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageAnalysisBaseTest.kt
index 580f20a..d727731 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageAnalysisBaseTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageAnalysisBaseTest.kt
@@ -93,7 +93,7 @@
}
assertWithMessage(
"The image rotation degrees [$imageRotationDegrees] was expected to" +
- " be equal to [$sensorToTargetRotation]"
+ " be equal to [$sensorToTargetRotation]"
)
.that(imageRotationDegrees)
.isEqualTo(sensorToTargetRotation)
@@ -101,15 +101,15 @@
}
protected inline fun <reified A : CameraActivity> launchActivity(lensFacing: Int):
- ActivityScenario<A> {
- val intent = Intent(
- ApplicationProvider.getApplicationContext(),
- A::class.java
- ).apply {
- putExtra(CameraActivity.KEY_LENS_FACING, lensFacing)
+ ActivityScenario<A> {
+ val intent = Intent(
+ ApplicationProvider.getApplicationContext(),
+ A::class.java
+ ).apply {
+ putExtra(CameraActivity.KEY_LENS_FACING, lensFacing)
+ }
+ return ActivityScenario.launch<A>(intent)
}
- return ActivityScenario.launch<A>(intent)
- }
protected inline fun <reified A : CameraActivity> ActivityScenario<A>.waitOnCameraFrames() {
val analysisRunning = withActivity { mAnalysisRunning }
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageAnalysisOrientationConfigChangesTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageAnalysisOrientationConfigChangesTest.kt
index 085988b..8ece0de 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageAnalysisOrientationConfigChangesTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageAnalysisOrientationConfigChangesTest.kt
@@ -75,14 +75,14 @@
}
private fun ActivityScenario<OrientationConfigChangesOverriddenActivity>.rotate(rotation: Int):
- Boolean {
- val currentRotation = withActivity {
- val root = findViewById<View>(android.R.id.content)
- root.display.rotation
+ Boolean {
+ val currentRotation = withActivity {
+ val root = findViewById<View>(android.R.id.content)
+ root.display.rotation
+ }
+ InstrumentationRegistry.getInstrumentation().uiAutomation.setRotation(rotation)
+ return currentRotation != rotation
}
- InstrumentationRegistry.getInstrumentation().uiAutomation.setRotation(rotation)
- return currentRotation != rotation
- }
private fun ActivityScenario<OrientationConfigChangesOverriddenActivity>.waitForRotation() {
val displayChanged = withActivity { mDisplayChanged }
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt
index fb98edb..ef516ee 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureBaseTest.kt
@@ -145,8 +145,8 @@
assertWithMessage(
"The captured image rotation degrees [$imageRotationDegrees] was expected to be " +
- "equal to [$sensorToTargetRotation], or the captured image's resolution " +
- "[$imageSize] was expected to be equal to [$expectedResolution]"
+ "equal to [$sensorToTargetRotation], or the captured image's resolution " +
+ "[$imageSize] was expected to be equal to [$expectedResolution]"
)
.that(areRotationsEqual || areResolutionsEqual)
.isTrue()
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureOrientationConfigChangesTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureOrientationConfigChangesTest.kt
index abc055c..3c2b49e 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureOrientationConfigChangesTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureOrientationConfigChangesTest.kt
@@ -84,14 +84,14 @@
}
private fun ActivityScenario<OrientationConfigChangesOverriddenActivity>.rotate(rotation: Int):
- Boolean {
- val currentRotation = withActivity {
- val root = findViewById<View>(android.R.id.content)
- root.display.rotation
+ Boolean {
+ val currentRotation = withActivity {
+ val root = findViewById<View>(android.R.id.content)
+ root.display.rotation
+ }
+ InstrumentationRegistry.getInstrumentation().uiAutomation.setRotation(rotation)
+ return currentRotation != rotation
}
- InstrumentationRegistry.getInstrumentation().uiAutomation.setRotation(rotation)
- return currentRotation != rotation
- }
private fun ActivityScenario<OrientationConfigChangesOverriddenActivity>.waitForRotation() {
val displayChanged = withActivity { mDisplayChanged }
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/viewpager/ViewPager2ActivityTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/viewpager/ViewPager2ActivityTest.kt
index a449991..daca177 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/viewpager/ViewPager2ActivityTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/viewpager/ViewPager2ActivityTest.kt
@@ -60,8 +60,10 @@
private const val ACTION_IDLE_TIMEOUT: Long = 5000
@JvmStatic
@Parameterized.Parameters(name = "lensFacing={0}")
- fun data() = listOf(CameraSelector.LENS_FACING_FRONT,
- CameraSelector.LENS_FACING_BACK)
+ fun data() = listOf(
+ CameraSelector.LENS_FACING_FRONT,
+ CameraSelector.LENS_FACING_BACK
+ )
}
@get:Rule
@@ -140,14 +142,14 @@
}
private fun launchActivity(lensFacing: Int):
- ActivityScenario<ViewPager2Activity> {
- val intent = Intent(
- ApplicationProvider.getApplicationContext<Context>(),
- ViewPager2Activity::class.java
- )
- intent.putExtra(BaseActivity.INTENT_LENS_FACING, lensFacing)
- return ActivityScenario.launch<ViewPager2Activity>(intent)
- }
+ ActivityScenario<ViewPager2Activity> {
+ val intent = Intent(
+ ApplicationProvider.getApplicationContext<Context>(),
+ ViewPager2Activity::class.java
+ )
+ intent.putExtra(BaseActivity.INTENT_LENS_FACING, lensFacing)
+ return ActivityScenario.launch<ViewPager2Activity>(intent)
+ }
private fun getTextureView(previewView: PreviewView): TextureView? {
var index: Int = 0
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/viewpager/ViewPagerActivityTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/viewpager/ViewPagerActivityTest.kt
index 2816aa3..03fc901 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/viewpager/ViewPagerActivityTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/viewpager/ViewPagerActivityTest.kt
@@ -60,8 +60,10 @@
private const val ACTION_IDLE_TIMEOUT: Long = 5000
@JvmStatic
@Parameterized.Parameters(name = "lensFacing={0}")
- fun data() = listOf(CameraSelector.LENS_FACING_FRONT,
- CameraSelector.LENS_FACING_BACK)
+ fun data() = listOf(
+ CameraSelector.LENS_FACING_FRONT,
+ CameraSelector.LENS_FACING_BACK
+ )
}
@get:Rule
@@ -141,14 +143,14 @@
// .SURFACE_VIEW in ViewPagerActivity.
private fun launchActivity(lensFacing: Int):
- ActivityScenario<ViewPagerActivity> {
- val intent = Intent(
- ApplicationProvider.getApplicationContext<Context>(),
- ViewPagerActivity::class.java
- )
- intent.putExtra(BaseActivity.INTENT_LENS_FACING, lensFacing)
- return ActivityScenario.launch<ViewPagerActivity>(intent)
- }
+ ActivityScenario<ViewPagerActivity> {
+ val intent = Intent(
+ ApplicationProvider.getApplicationContext<Context>(),
+ ViewPagerActivity::class.java
+ )
+ intent.putExtra(BaseActivity.INTENT_LENS_FACING, lensFacing)
+ return ActivityScenario.launch<ViewPagerActivity>(intent)
+ }
private fun getTextureView(previewView: PreviewView): TextureView? {
var index: Int = 0
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
index 7cd8d9a..dfb7c28 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
@@ -96,10 +96,13 @@
private fun setUpCamera() {
val cameraProcessFuture = ProcessCameraProvider.getInstance(this)
- cameraProcessFuture.addListener(Runnable {
- val cameraProvider = cameraProcessFuture.get()
- setUpCamera(cameraProvider)
- }, ContextCompat.getMainExecutor(this))
+ cameraProcessFuture.addListener(
+ Runnable {
+ val cameraProvider = cameraProcessFuture.get()
+ setUpCamera(cameraProvider)
+ },
+ ContextCompat.getMainExecutor(this)
+ )
}
private fun setUpCamera(cameraProvider: ProcessCameraProvider) {
@@ -171,7 +174,8 @@
mCaptureDone.release()
Log.e(TAG, "InMemory image capture failed", exception)
}
- })
+ }
+ )
}
private fun ImageCapture.setFileCallback() {
@@ -191,7 +195,8 @@
mCaptureDone.release()
Log.e(TAG, "File image capture failed", exception)
}
- })
+ }
+ )
}
private fun ImageCapture.setOutputStreamCallback() {
@@ -212,7 +217,8 @@
mCaptureDone.release()
Log.e(TAG, "OutputStream image capture failed", exception)
}
- })
+ }
+ )
}
private fun ImageCapture.setMediaStoreCallback() {
@@ -238,7 +244,8 @@
mCaptureDone.release()
Log.e(TAG, "MediaStore image capture failed", exception)
}
- })
+ }
+ )
}
protected fun isImageAnalysisInitialized(): Boolean {
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/viewpager/CameraFragment.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/viewpager/CameraFragment.kt
index 8f7b151..cdd2020 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/viewpager/CameraFragment.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/viewpager/CameraFragment.kt
@@ -60,10 +60,13 @@
Log.d(TAG, "onViewCreated")
(requireActivity() as BaseActivity).previewView = preview_textureview
- cameraProviderFuture.addListener(Runnable {
- cameraProvider = cameraProviderFuture.get()
- bindPreview()
- }, ContextCompat.getMainExecutor(this.context))
+ cameraProviderFuture.addListener(
+ Runnable {
+ cameraProvider = cameraProviderFuture.get()
+ bindPreview()
+ },
+ ContextCompat.getMainExecutor(this.context)
+ )
}
private fun bindPreview() {
@@ -82,8 +85,10 @@
private fun getCameraSelector(): CameraSelector {
val lensFacing = (requireActivity() as BaseActivity).intent.getIntExtra(
- BaseActivity.INTENT_LENS_FACING, CameraSelector
- .LENS_FACING_BACK)
+ BaseActivity.INTENT_LENS_FACING,
+ CameraSelector
+ .LENS_FACING_BACK
+ )
return CameraSelector.Builder()
.requireLensFacing(lensFacing)
.build()
diff --git a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
index 56223bf..97fdada 100644
--- a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
+++ b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
@@ -95,7 +95,8 @@
}
override fun onFailure(t: Throwable) {}
- }, CameraXExecutors.directExecutor()
+ },
+ CameraXExecutors.directExecutor()
)
assertThat(semaphore.tryAcquire(TIMEOUT_SECONDS, TimeUnit.SECONDS)).isTrue()
}
@@ -233,8 +234,8 @@
val errorTolerance = 1F
for ((i, colorShift) in RGB_SHIFTS.withIndex()) {
val errorMsg = "Color $i Capture\n" +
- colorComponentToReadableString(captureBitmap, colorShift) + "Preview\n" +
- colorComponentToReadableString(previewBitmap, colorShift)
+ colorComponentToReadableString(captureBitmap, colorShift) + "Preview\n" +
+ colorComponentToReadableString(previewBitmap, colorShift)
assertWithMessage(errorMsg).that(captureMoment[i].x).isWithin(errorTolerance)
.of(previewMoment[i].x)
assertWithMessage(errorMsg).that(captureMoment[i].y).isWithin(errorTolerance)
@@ -346,19 +347,19 @@
* @param colorShift: color component in the format of right shift on Int color.
*/
private fun colorComponentToReadableString(bitmap1: Bitmap, colorShift: Int):
- String {
- var result = ""
- for (x in 0 until bitmap1.width) {
- for (y in 0 until bitmap1.height) {
- var color = (bitmap1.getPixel(x, y) shr colorShift and 0xFF).toString()
- // 10x10 table Each column is a fixed size of 4.
- color += " ".repeat((3 - color.length))
- result += "$color "
+ String {
+ var result = ""
+ for (x in 0 until bitmap1.width) {
+ for (y in 0 until bitmap1.height) {
+ var color = (bitmap1.getPixel(x, y) shr colorShift and 0xFF).toString()
+ // 10x10 table Each column is a fixed size of 4.
+ color += " ".repeat((3 - color.length))
+ result += "$color "
+ }
+ result += "\n"
}
- result += "\n"
+ return result
}
- return result
- }
private fun rotationValueToRotationDegrees(rotationValue: Int): Int {
return when (rotationValue) {
@@ -419,11 +420,11 @@
}
private fun FragmentScenario<CameraControllerFragment?>.getFragment():
- CameraControllerFragment {
- var fragment: CameraControllerFragment? = null
- this.onFragment { newValue: CameraControllerFragment -> fragment = newValue }
- return fragment!!
- }
+ CameraControllerFragment {
+ var fragment: CameraControllerFragment? = null
+ this.onFragment { newValue: CameraControllerFragment -> fragment = newValue }
+ return fragment!!
+ }
private fun CameraControllerFragment.assertPreviewIsStreaming() {
assertPreviewState(PreviewView.StreamState.STREAMING)
@@ -436,11 +437,14 @@
private fun CameraControllerFragment.assertPreviewState(state: PreviewView.StreamState) {
val previewStreaming = Semaphore(0)
instrumentation.runOnMainSync {
- previewView.previewStreamState.observe(this, Observer {
- if (it == state) {
- previewStreaming.release()
+ previewView.previewStreamState.observe(
+ this,
+ Observer {
+ if (it == state) {
+ previewStreaming.release()
+ }
}
- })
+ )
}
assertThat(previewStreaming.tryAcquire(TIMEOUT_SECONDS, TimeUnit.SECONDS)).isTrue()
}
diff --git a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraViewFragmentTest.kt b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraViewFragmentTest.kt
index 6024366..f93b9d5 100644
--- a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraViewFragmentTest.kt
+++ b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraViewFragmentTest.kt
@@ -73,7 +73,7 @@
launchFragmentInContainer<CameraViewFragment>(
fragmentArgs = bundleOf(
CameraViewFragment.ARG_LIFECYCLE_TYPE to
- CameraViewFragment.LIFECYCLE_TYPE_ACTIVITY
+ CameraViewFragment.LIFECYCLE_TYPE_ACTIVITY
)
)
) { assertStreaming() }
@@ -85,7 +85,7 @@
launchFragmentInContainer<CameraViewFragment>(
fragmentArgs = bundleOf(
CameraViewFragment.ARG_LIFECYCLE_TYPE to
- CameraViewFragment.LIFECYCLE_TYPE_FRAGMENT
+ CameraViewFragment.LIFECYCLE_TYPE_FRAGMENT
)
)
) { assertStreaming() }
@@ -97,7 +97,7 @@
launchFragmentInContainer<CameraViewFragment>(
fragmentArgs = bundleOf(
CameraViewFragment.ARG_LIFECYCLE_TYPE to
- CameraViewFragment.LIFECYCLE_TYPE_FRAGMENT_VIEW
+ CameraViewFragment.LIFECYCLE_TYPE_FRAGMENT_VIEW
)
)
) { assertStreaming() }
@@ -116,7 +116,8 @@
CameraViewFragment().apply {
setDebugLifecycleOwner(TestLifecycleOwner(Lifecycle.State.DESTROYED))
}
- })
+ }
+ )
}
}
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
index ed2e370..00bf90e 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
@@ -96,9 +96,10 @@
for (byte value : bytes) {
total += value & 0xFF;
}
- final int luminance = total / bytes.length;
- mLuminance.post(
- () -> mLuminance.setText(String.valueOf(luminance)));
+ if (bytes.length != 0) {
+ final int luminance = total / bytes.length;
+ mLuminance.post(() -> mLuminance.setText(String.valueOf(luminance)));
+ }
// Forward the call to wrapped analyzer if set.
if (mWrappedAnalyzer != null) {
mWrappedAnalyzer.analyze(image);
diff --git a/compose/animation/animation/src/androidAndroidTest/kotlin/androidx/compose/animation/AnimatedVisibilityTest.kt b/compose/animation/animation/src/androidAndroidTest/kotlin/androidx/compose/animation/AnimatedVisibilityTest.kt
index 5c40a46..88f429d 100644
--- a/compose/animation/animation/src/androidAndroidTest/kotlin/androidx/compose/animation/AnimatedVisibilityTest.kt
+++ b/compose/animation/animation/src/androidAndroidTest/kotlin/androidx/compose/animation/AnimatedVisibilityTest.kt
@@ -74,9 +74,11 @@
tween(100, easing = FastOutSlowInEasing)
)
) {
- Box(Modifier.onGloballyPositioned {
- offset = it.localToRoot(Offset.Zero)
- }.size(100.dp, 100.dp)) {
+ Box(
+ Modifier.onGloballyPositioned {
+ offset = it.localToRoot(Offset.Zero)
+ }.size(100.dp, 100.dp)
+ ) {
onDispose {
disposed = true
}
@@ -176,9 +178,11 @@
tween(100, easing = FastOutSlowInEasing)
)
) {
- Box(Modifier.onGloballyPositioned {
- offset = it.localToRoot(Offset.Zero)
- }.size(100.dp, 100.dp)) {
+ Box(
+ Modifier.onGloballyPositioned {
+ offset = it.localToRoot(Offset.Zero)
+ }.size(100.dp, 100.dp)
+ ) {
onDispose {
disposed = true
}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
index 79c7bd3..09edd90 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
@@ -28,20 +28,21 @@
* ComposeVersion.kt is updated.
*/
private val versionTable = mapOf(
- 1600 to "0.1.0-dev16"
+ 1600 to "0.1.0-dev16",
+ 1700 to "1.0.0-alpha06"
)
/**
* The minimum version int that this compiler is guaranteed to be compatible with. Typically
* this will match the version int that is in ComposeVersion.kt in the runtime.
*/
- private val minimumRuntimeVersionInt: Int = 1600
+ private val minimumRuntimeVersionInt: Int = 1700
/**
* The maven version string of this compiler. This string should be updated before/after every
* release.
*/
- private val compilerVersion: String = "0.1.0-dev16"
+ private val compilerVersion: String = "1.0.0-alpha06"
private val minimumRuntimeVersion: String
get() = versionTable[minimumRuntimeVersionInt] ?: "unknown"
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt
index 67e6fcf..946f9be 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt
@@ -1005,7 +1005,7 @@
}
val getterIsStable = prop.hasStableAnnotation() ||
- symbol.owner.hasStableAnnotation()
+ symbol.owner.hasStableAnnotation()
if (
getterIsStable &&
@@ -1038,7 +1038,7 @@
.descriptor
.fqNameSafe
.topLevelName() == "kotlin" ||
- symbol.owner.hasStableAnnotation()
+ symbol.owner.hasStableAnnotation()
val typeIsStable = type.toKotlinType().isStable()
if (!typeIsStable) return false
@@ -1054,7 +1054,7 @@
// if it is a call to remember with 0 input arguments, then we can
// consider the value static if the result type of the lambda is stable
val syntheticRememberParams = 1 + // composer param
- 1 // changed param
+ 1 // changed param
val expectedArgumentsCount = 1 + syntheticRememberParams // 1 for lambda
if (
valueArgumentsCount == expectedArgumentsCount &&
diff --git a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/example1/Main.kt b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/example1/Main.kt
index 4ccb7f4..7ded868 100644
--- a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/example1/Main.kt
+++ b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/example1/Main.kt
@@ -18,7 +18,6 @@
import androidx.compose.animation.animate
import androidx.compose.animation.core.TweenSpec
import androidx.compose.desktop.AppWindow
-import androidx.compose.desktop.Window
import androidx.compose.foundation.Icon
import androidx.compose.foundation.Image
import androidx.compose.foundation.Text
@@ -59,6 +58,11 @@
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
+import androidx.compose.ui.input.key.ExperimentalKeyInput
+import androidx.compose.ui.input.key.Key
+import androidx.compose.ui.input.key.ShortcutHandler
+import androidx.compose.ui.input.key.keyInputFilter
+import androidx.compose.ui.input.key.plus
import androidx.compose.ui.input.pointer.pointerMoveFilter
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.text.Placeholder
@@ -106,6 +110,7 @@
}
}
+@OptIn(ExperimentalKeyInput::class)
@Composable
private fun LeftColumn(modifier: Modifier) = Column(modifier) {
val amount = remember { mutableStateOf(0) }
@@ -209,6 +214,9 @@
overflow = TextOverflow.Ellipsis
)
+ var overText by remember { mutableStateOf("Move mouse over text:") }
+ Text(overText)
+
Text(
text = "fun <T : Comparable<T>> List<T>.quickSort(): List<T> = when {\n" +
" size < 2 -> this\n" +
@@ -219,18 +227,16 @@
" }\n" +
"}",
modifier = Modifier.padding(10.dp).pointerMoveFilter(
- onMove = { position ->
- println("MOVE: $position")
+ onMove = {
+ overText = "Move position: $it"
false
},
onEnter = {
- println("HOVER!")
- text.value = "HOVER ${amount.value}"
+ overText = "Over enter"
false
},
onExit = {
- println("UNHOVER!")
- text.value = "UNHOVER ${amount.value}"
+ overText = "Over exit"
false
}
)
@@ -262,7 +268,11 @@
Button(
modifier = Modifier.padding(4.dp),
onClick = {
- Window(size = IntSize(400, 200)) {
+ AppWindow(size = IntSize(400, 200)).also {
+ it.keyboard.shortcut(Key.Escape) {
+ it.close()
+ }
+ }.show {
Animations(isCircularEnabled = animation.value)
}
}
@@ -283,10 +293,16 @@
onValueChange = { amount.value = it.toIntOrNull() ?: 42 },
label = { Text(text = "Input1") }
)
+
TextField(
value = text.value,
onValueChange = { text.value = it },
- label = { Text(text = "Input2") }
+ label = { Text(text = "Input2") },
+ modifier = Modifier.keyInputFilter(
+ ShortcutHandler(Key.MetaLeft + Key.Enter) {
+ text.value = "Cleared!"
+ }
+ )
)
Image(imageResource("androidx/compose/desktop/example/circus.jpg"))
diff --git a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/AppWindow.kt b/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/AppWindow.kt
index 220ef86d..919b1c3 100644
--- a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/AppWindow.kt
+++ b/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/AppWindow.kt
@@ -19,6 +19,8 @@
import androidx.compose.runtime.Providers
import androidx.compose.runtime.ambientOf
import androidx.compose.runtime.emptyContent
+import androidx.compose.ui.input.key.ExperimentalKeyInput
+import androidx.compose.ui.platform.Keyboard
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import java.awt.Dimension
@@ -145,6 +147,7 @@
}
}
+ @OptIn(ExperimentalKeyInput::class)
override fun show(content: @Composable () -> Unit) {
if (invoker != null) {
invoker!!.lockWindow()
@@ -152,6 +155,7 @@
}
onCreate {
+ window.owners?.keyboard = keyboard
content()
}
@@ -192,4 +196,7 @@
}
disconnectPair()
}
+
+ @ExperimentalKeyInput
+ val keyboard: Keyboard = Keyboard()
}
diff --git a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/ComposeWindow.kt b/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/ComposeWindow.kt
index 5e1fa31..d44d49d 100644
--- a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/ComposeWindow.kt
+++ b/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/ComposeWindow.kt
@@ -40,7 +40,7 @@
}
val parent: AppFrame
- private val layer = FrameSkiaLayer()
+ internal val layer = FrameSkiaLayer()
private val events = AWTDebounceEventQueue()
var owners: DesktopOwners? = null
@@ -56,6 +56,7 @@
addComponentListener(object : ComponentAdapter() {
override fun componentResized(e: ComponentEvent) {
layer.reinit()
+ needRedrawLayer()
}
})
initCanvas()
@@ -118,15 +119,15 @@
}
layer.wrapped.addKeyListener(object : KeyAdapter() {
override fun keyPressed(event: KeyEvent) = events.post {
- owners?.onKeyPressed(event.keyCode, event.keyChar)
+ owners?.onKeyPressed(event)
}
override fun keyReleased(event: KeyEvent) = events.post {
- owners?.onKeyReleased(event.keyCode, event.keyChar)
+ owners?.onKeyReleased(event)
}
override fun keyTyped(event: KeyEvent) = events.post {
- owners?.onKeyTyped(event.keyChar)
+ owners?.onKeyTyped(event)
}
})
}
@@ -134,6 +135,7 @@
override fun setVisible(value: Boolean) {
if (value != isVisible) {
super.setVisible(value)
+ layer.wrapped.requestFocus()
updateLayer()
needRedrawLayer()
}
@@ -141,15 +143,8 @@
}
private class OwnersRenderer(private val owners: DesktopOwners) : FrameSkiaLayer.Renderer {
- override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
- try {
- owners.onRender(canvas, width, height, nanoTime)
- } catch (e: Throwable) {
- e.printStackTrace(System.err)
- if (System.getProperty("compose.desktop.ignore.errors") == null) {
- System.exit(1)
- }
- }
+ override suspend fun onFrame(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
+ owners.onFrame(canvas, width, height, nanoTime)
}
}
diff --git a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/FrameSkiaLayer.kt b/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/FrameSkiaLayer.kt
index 1017855..6b4ebc4 100644
--- a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/FrameSkiaLayer.kt
+++ b/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/FrameSkiaLayer.kt
@@ -16,6 +16,8 @@
package androidx.compose.desktop
+import androidx.compose.ui.platform.DesktopComponent
+import androidx.compose.ui.platform.FrameDispatcher
import org.jetbrains.skija.Canvas
import org.jetbrains.skija.Picture
import org.jetbrains.skija.PictureRecorder
@@ -23,6 +25,8 @@
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaRenderer
import java.awt.DisplayMode
+import java.awt.event.FocusEvent
+import java.awt.im.InputMethodRequests
internal class FrameSkiaLayer {
var renderer: Renderer? = null
@@ -37,23 +41,45 @@
private val picture = MutableResource<Picture>()
private val pictureRecorder = PictureRecorder()
- private fun onFrame(nanoTime: Long) {
+ private suspend fun onFrame(nanoTime: Long) {
this.frameNanoTime = nanoTime
+ preparePicture(frameNanoTime)
wrapped.redrawLayer()
}
- val wrapped = object : SkiaLayer() {
- override fun redrawLayer() {
- preparePicture(frameNanoTime)
- super.redrawLayer()
+ inner class Wrapped : SkiaLayer(), DesktopComponent {
+ var currentInputMethodRequests: InputMethodRequests? = null
+
+ override fun getInputMethodRequests() = currentInputMethodRequests
+
+ override fun enableInput(inputMethodRequests: InputMethodRequests) {
+ currentInputMethodRequests = inputMethodRequests
+ enableInputMethods(true)
+ val focusGainedEvent = FocusEvent(this, FocusEvent.FOCUS_GAINED)
+ inputContext.dispatchEvent(focusGainedEvent)
}
+
+ override fun disableInput() {
+ currentInputMethodRequests = null
+ }
+
+ override fun locationOnScreen() = locationOnScreen
}
+ val wrapped = Wrapped()
+
init {
wrapped.renderer = object : SkiaRenderer {
override fun onRender(canvas: Canvas, width: Int, height: Int) {
- picture.useWithoutClosing {
- it?.also(canvas::drawPicture)
+ try {
+ picture.useWithoutClosing {
+ it?.also(canvas::drawPicture)
+ }
+ } catch (e: Throwable) {
+ e.printStackTrace(System.err)
+ if (System.getProperty("compose.desktop.render.ignore.errors") == null) {
+ System.exit(1)
+ }
}
}
@@ -66,10 +92,10 @@
// We draw into picture, because SkiaLayer.draw can be called from the other thread,
// but onRender should be called in AWT thread. Picture doesn't add any visible overhead on
// CPU/RAM.
- private fun preparePicture(frameTimeNanos: Long) {
+ private suspend fun preparePicture(frameTimeNanos: Long) {
val bounds = Rect.makeWH(wrapped.width.toFloat(), wrapped.height.toFloat())
val pictureCanvas = pictureRecorder.beginRecording(bounds)
- renderer?.onRender(pictureCanvas, wrapped.width, wrapped.height, frameTimeNanos)
+ renderer?.onFrame(pictureCanvas, wrapped.width, wrapped.height, frameTimeNanos)
picture.set(pictureRecorder.finishRecordingAsPicture())
}
@@ -78,9 +104,9 @@
wrapped.reinit()
}
- private fun getFramesPerSecond(): Int {
+ private fun getFramesPerSecond(): Float {
val refreshRate = wrapped.graphicsConfiguration.device.displayMode.refreshRate
- return if (refreshRate != DisplayMode.REFRESH_RATE_UNKNOWN) refreshRate else 60
+ return if (refreshRate != DisplayMode.REFRESH_RATE_UNKNOWN) refreshRate.toFloat() else 60f
}
fun updateLayer() {
@@ -104,6 +130,6 @@
}
interface Renderer {
- fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long)
+ suspend fun onFrame(canvas: Canvas, width: Int, height: Int, nanoTime: Long)
}
}
\ No newline at end of file
diff --git a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/Wrapper.kt b/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/Wrapper.kt
index a23d2f2..205806b 100644
--- a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/Wrapper.kt
+++ b/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/Wrapper.kt
@@ -21,14 +21,15 @@
import androidx.compose.ui.platform.DesktopOwners
import androidx.compose.ui.platform.setContent
-fun ComposeWindow.setContent(content: @Composable () -> Unit): Composition {
- val owners = DesktopOwners(this, this::needRedrawLayer)
- val owner = DesktopOwner(owners)
- val composition = owner.setContent(content)
+fun ComposeWindow.setContent(content: @Composable () -> Unit):
+ Composition {
+ val owners = DesktopOwners(this.layer.wrapped, this::needRedrawLayer)
+ val owner = DesktopOwner(owners)
- this.owners = owners
+ this.owners = owners
+ val composition = owner.setContent(content)
- parent.onDismissEvents.add(owner::dispose)
+ parent.onDismissEvents.add(owner::dispose)
- return composition
-}
+ return composition
+ }
diff --git a/compose/desktop/desktop/src/jvmTest/kotlin/androidx/compose/desktop/FrameDispatcherTest.kt b/compose/desktop/desktop/src/jvmTest/kotlin/androidx/compose/desktop/FrameDispatcherTest.kt
index a40d6fc7..25dddc3 100644
--- a/compose/desktop/desktop/src/jvmTest/kotlin/androidx/compose/desktop/FrameDispatcherTest.kt
+++ b/compose/desktop/desktop/src/jvmTest/kotlin/androidx/compose/desktop/FrameDispatcherTest.kt
@@ -16,6 +16,7 @@
package androidx.compose.desktop
+import androidx.compose.ui.platform.FrameDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.TestCoroutineScope
@@ -38,7 +39,7 @@
fun TestCoroutineScope.testFrameDispatcher() = FrameDispatcher(
::onFrame,
- framesPerSecond = { 100 }, // one frame is 10 milliseconds
+ framesPerSecond = { 100f }, // one frame is 10 milliseconds
nanoTime = { currentTime * 1_000_000 },
coroutineContext
)
diff --git a/compose/foundation/foundation-layout/api/current.txt b/compose/foundation/foundation-layout/api/current.txt
index f54c9ee..d98e366 100644
--- a/compose/foundation/foundation-layout/api/current.txt
+++ b/compose/foundation/foundation-layout/api/current.txt
@@ -67,7 +67,7 @@
}
public final class BoxKt {
- method @androidx.compose.runtime.Composable public static void Box(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> children);
+ method @androidx.compose.runtime.Composable public static inline void Box(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> children);
method @androidx.compose.runtime.Composable public static void Box(androidx.compose.ui.Modifier modifier);
method @Deprecated @androidx.compose.runtime.Composable public static void Stack(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> children);
}
diff --git a/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt b/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
index f54c9ee..d98e366 100644
--- a/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
@@ -67,7 +67,7 @@
}
public final class BoxKt {
- method @androidx.compose.runtime.Composable public static void Box(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> children);
+ method @androidx.compose.runtime.Composable public static inline void Box(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> children);
method @androidx.compose.runtime.Composable public static void Box(androidx.compose.ui.Modifier modifier);
method @Deprecated @androidx.compose.runtime.Composable public static void Stack(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> children);
}
diff --git a/compose/foundation/foundation-layout/api/restricted_current.txt b/compose/foundation/foundation-layout/api/restricted_current.txt
index 46e800e..b067263 100644
--- a/compose/foundation/foundation-layout/api/restricted_current.txt
+++ b/compose/foundation/foundation-layout/api/restricted_current.txt
@@ -67,9 +67,10 @@
}
public final class BoxKt {
- method @androidx.compose.runtime.Composable public static void Box(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> children);
+ method @androidx.compose.runtime.Composable public static inline void Box(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> children);
method @androidx.compose.runtime.Composable public static void Box(androidx.compose.ui.Modifier modifier);
method @Deprecated @androidx.compose.runtime.Composable public static void Stack(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> children);
+ method @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static androidx.compose.ui.node.LayoutNode.MeasureBlocks rememberMeasureBlocks(androidx.compose.ui.Alignment alignment);
}
@androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Immutable public interface BoxScope {
diff --git a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/LayoutPaddingTest.kt b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/LayoutPaddingTest.kt
index fd9f166..613e4fa 100644
--- a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/LayoutPaddingTest.kt
+++ b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/LayoutPaddingTest.kt
@@ -27,6 +27,7 @@
import androidx.compose.ui.onGloballyPositioned
import androidx.compose.ui.platform.InspectableValue
import androidx.compose.ui.platform.LayoutDirectionAmbient
+import androidx.compose.ui.platform.ValueElement
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntSize
@@ -361,16 +362,26 @@
@Test
fun testInspectableParameter() {
- val exclusions = listOf("nameFallback", "rtlAware")
val modifier = Modifier.padding(10.dp, 20.dp, 30.dp, 40.dp) as InspectableValue
assertThat(modifier.nameFallback).isEqualTo("padding")
assertThat(modifier.valueOverride).isNull()
- assertThat(modifier.inspectableElements.map { it.name }.toList())
- .containsExactlyElementsIn(
- modifier.javaClass.declaredFields
- .filter { !it.isSynthetic && !exclusions.contains(it.name) }
- .map { it.name }
- )
+ assertThat(modifier.inspectableElements.toList()).containsExactly(
+ ValueElement("start", 10.dp),
+ ValueElement("top", 20.dp),
+ ValueElement("end", 30.dp),
+ ValueElement("bottom", 40.dp)
+ )
+ }
+
+ @Test
+ fun testInspectableParameterWith2Parameters() {
+ val modifier = Modifier.padding(10.dp, 20.dp) as InspectableValue
+ assertThat(modifier.nameFallback).isEqualTo("padding")
+ assertThat(modifier.valueOverride).isNull()
+ assertThat(modifier.inspectableElements.toList()).containsExactly(
+ ValueElement("horizontal", 10.dp),
+ ValueElement("vertical", 20.dp)
+ )
}
@Test
@@ -378,22 +389,20 @@
val modifier = Modifier.absolutePadding(10.dp, 20.dp, 30.dp, 40.dp) as InspectableValue
assertThat(modifier.nameFallback).isEqualTo("absolutePadding")
assertThat(modifier.valueOverride).isNull()
- assertThat(modifier.inspectableElements.map { it.name }.toList())
- .containsExactly("left", "top", "right", "bottom")
+ assertThat(modifier.inspectableElements.toList()).containsExactly(
+ ValueElement("left", 10.dp),
+ ValueElement("top", 20.dp),
+ ValueElement("right", 30.dp),
+ ValueElement("bottom", 40.dp)
+ )
}
@Test
fun testInspectableParameterWithSameOverallValue() {
- val exclusions = listOf("nameFallback", "rtlAware")
val modifier = Modifier.padding(40.dp) as InspectableValue
assertThat(modifier.nameFallback).isEqualTo("padding")
assertThat(modifier.valueOverride).isEqualTo(40.dp)
- assertThat(modifier.inspectableElements.map { it.name }.toList())
- .containsExactlyElementsIn(
- modifier.javaClass.declaredFields
- .filter { !it.isSynthetic && !exclusions.contains(it.name) }
- .map { it.name }
- )
+ assertThat(modifier.inspectableElements.toList()).isEmpty()
}
private fun testPaddingIsAppliedImplementation(
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Box.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Box.kt
index 5632af4..0db5a85 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Box.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Box.kt
@@ -19,15 +19,21 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
+import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Layout
import androidx.compose.ui.Measurable
+import androidx.compose.ui.MeasuringIntrinsicsMeasureBlocks
import androidx.compose.ui.Modifier
import androidx.compose.ui.ParentDataModifier
import androidx.compose.ui.Placeable
+import androidx.compose.ui.node.ExperimentalLayoutNodeApi
+import androidx.compose.ui.node.LayoutNode
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.util.fastForEachIndexed
import kotlin.math.max
/**
@@ -40,61 +46,130 @@
*
* Example usage:
*
- * @sample androidx.compose.foundation.layout.samples.SimpleBox
+ * @2sample androidx.compose.foundation.layout.samples.SimpleBox
*
* @param modifier The modifier to be applied to the layout.
* @param alignment The default alignment inside the Box.
*/
@Composable
-fun Box(
+@OptIn(ExperimentalLayoutNodeApi::class)
+inline fun Box(
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.TopStart,
- children: @Composable BoxScope.() -> Unit
+ crossinline children: @Composable BoxScope.() -> Unit
) {
- val boxChildren: @Composable () -> Unit = { BoxScope.children() }
+ val measureBlocks = rememberMeasureBlocks(alignment)
+ Layout(
+ children = { BoxScope.children() },
+ measureBlocks = measureBlocks,
+ modifier = modifier
+ )
+}
- Layout(boxChildren, modifier = modifier) { measurables, constraints ->
- val placeables = arrayOfNulls<Placeable>(measurables.size)
- // First measure aligned children to get the size of the layout.
- val childConstraints = constraints.copy(minWidth = 0, minHeight = 0)
- (0 until measurables.size).filter { i -> !measurables[i].stretch }.forEach { i ->
- placeables[i] = measurables[i].measure(childConstraints)
- }
- val (boxWidth, boxHeight) = with(placeables.filterNotNull()) {
- Pair(
- max(maxByOrNull { it.width }?.width ?: 0, constraints.minWidth),
- max(maxByOrNull { it.height }?.height ?: 0, constraints.minHeight)
- )
+@PublishedApi
+@Composable
+internal fun rememberMeasureBlocks(
+ alignment: Alignment
+) = remember(alignment) {
+ if (alignment == Alignment.TopStart) {
+ DefaultBoxMeasureBlocks
+ } else {
+ boxMeasureBlocks(alignment)
+ }
+}
+
+@OptIn(ExperimentalLayoutNodeApi::class)
+internal val DefaultBoxMeasureBlocks: LayoutNode.MeasureBlocks =
+ boxMeasureBlocks(Alignment.TopStart)
+
+internal fun boxMeasureBlocks(alignment: Alignment) =
+ MeasuringIntrinsicsMeasureBlocks { measurables, constraints ->
+ if (measurables.isEmpty()) {
+ return@MeasuringIntrinsicsMeasureBlocks layout(
+ constraints.minWidth,
+ constraints.minHeight
+ ) {}
}
- // Now measure stretch children.
- (0 until measurables.size).filter { i -> measurables[i].stretch }.forEach { i ->
- // infinity check is needed for intrinsic measurements
- val minWidth = if (boxWidth != Constraints.Infinity) boxWidth else 0
- val minHeight = if (boxHeight != Constraints.Infinity) boxHeight else 0
- placeables[i] = measurables[i].measure(
- Constraints(minWidth, boxWidth, minHeight, boxHeight)
- )
- }
+ val minRelaxedConstraints = constraints.copy(minWidth = 0, minHeight = 0)
- // Position the children.
- layout(boxWidth, boxHeight) {
- (0 until measurables.size).forEach { i ->
- val measurable = measurables[i]
- val childAlignment = measurable.boxChildData?.alignment ?: alignment
- val placeable = placeables[i]!!
-
- val position = childAlignment.align(
- IntSize(
- boxWidth - placeable.width,
- boxHeight - placeable.height
- ),
- layoutDirection
+ if (measurables.size == 1) {
+ val measurable = measurables[0]
+ val boxWidth: Int
+ val boxHeight: Int
+ val placeable: Placeable
+ if (!measurable.matchesParentSize) {
+ placeable = measurable.measure(minRelaxedConstraints)
+ boxWidth = max(constraints.minWidth, placeable.width)
+ boxHeight = max(constraints.minHeight, placeable.height)
+ } else {
+ boxWidth = constraints.minWidth
+ boxHeight = constraints.minHeight
+ placeable = measurable.measure(
+ Constraints.fixed(constraints.minWidth, constraints.minHeight)
)
- placeable.place(position.x, position.y)
+ }
+ return@MeasuringIntrinsicsMeasureBlocks layout(boxWidth, boxHeight) {
+ placeInBox(placeable, measurable, layoutDirection, boxWidth, boxHeight, alignment)
+ }
+ }
+
+ val placeables = arrayOfNulls<Placeable>(measurables.size)
+ // First measure non match parent size children to get the size of the Box.
+ var hasMatchParentSizeChildren = false
+ var boxWidth = constraints.minWidth
+ var boxHeight = constraints.minHeight
+ measurables.fastForEachIndexed { index, measurable ->
+ if (!measurable.matchesParentSize) {
+ val placeable = measurable.measure(minRelaxedConstraints)
+ placeables[index] = placeable
+ boxWidth = max(boxWidth, placeable.width)
+ boxHeight = max(boxHeight, placeable.height)
+ } else {
+ hasMatchParentSizeChildren = true
+ }
+ }
+
+ // Now measure match parent size children, if any.
+ if (hasMatchParentSizeChildren) {
+ // The infinity check is needed for default intrinsic measurements.
+ val matchParentSizeConstraints = Constraints(
+ minWidth = if (boxWidth != Constraints.Infinity) boxWidth else 0,
+ minHeight = if (boxHeight != Constraints.Infinity) boxHeight else 0,
+ maxWidth = boxWidth,
+ maxHeight = boxHeight
+ )
+ measurables.fastForEachIndexed { index, measurable ->
+ if (measurable.matchesParentSize) {
+ placeables[index] = measurable.measure(matchParentSizeConstraints)
+ }
+ }
+ }
+
+ // Specify the size of the Box and position its children.
+ layout(boxWidth, boxHeight) {
+ placeables.forEachIndexed { index, placeable ->
+ placeable as Placeable
+ val measurable = measurables[index]
+ placeInBox(placeable, measurable, layoutDirection, boxWidth, boxHeight, alignment)
}
}
}
+
+private fun Placeable.PlacementScope.placeInBox(
+ placeable: Placeable,
+ measurable: Measurable,
+ layoutDirection: LayoutDirection,
+ boxWidth: Int,
+ boxHeight: Int,
+ alignment: Alignment
+) {
+ val childAlignment = measurable.boxChildData?.alignment ?: alignment
+ val position = childAlignment.align(
+ IntSize(boxWidth - placeable.width, boxHeight - placeable.height),
+ layoutDirection
+ )
+ placeable.place(position)
}
/**
@@ -108,10 +183,14 @@
* @param modifier The modifier to be applied to the layout.
*/
@Composable
+@OptIn(ExperimentalLayoutNodeApi::class)
fun Box(modifier: Modifier) {
- Layout({}, modifier = modifier) { _, constraints ->
- layout(constraints.minWidth, constraints.minHeight) {}
- }
+ Layout({}, measureBlocks = EmptyBoxMeasureBlocks, modifier = modifier)
+}
+
+@OptIn(ExperimentalLayoutNodeApi::class)
+internal val EmptyBoxMeasureBlocks = MeasuringIntrinsicsMeasureBlocks { _, constraints ->
+ layout(constraints.minWidth, constraints.minHeight) {}
}
@Composable
@@ -155,7 +234,7 @@
* available space.
*/
@Stable
- fun Modifier.matchParentSize() = this.then(StretchAlignModifier)
+ fun Modifier.matchParentSize() = this.then(MatchParentSizeModifier)
companion object : BoxScope
}
@@ -167,14 +246,14 @@
typealias StackScope = BoxScope
@Stable
-private val StretchAlignModifier: ParentDataModifier = BoxChildData(Alignment.Center, true)
+private val MatchParentSizeModifier: ParentDataModifier = BoxChildData(Alignment.Center, true)
private val Measurable.boxChildData: BoxChildData? get() = parentData as? BoxChildData
-private val Measurable.stretch: Boolean get() = boxChildData?.stretch ?: false
+private val Measurable.matchesParentSize: Boolean get() = boxChildData?.matchParentSize ?: false
private data class BoxChildData(
var alignment: Alignment,
- var stretch: Boolean = false
+ var matchParentSize: Boolean = false
) : ParentDataModifier {
override fun Density.modifyParentData(parentData: Any?) = this@BoxChildData
}
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/LayoutPadding.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/LayoutPadding.kt
index aa6bae9..841a403 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/LayoutPadding.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/LayoutPadding.kt
@@ -22,8 +22,9 @@
import androidx.compose.ui.Measurable
import androidx.compose.ui.MeasureScope
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.InspectableValue
-import androidx.compose.ui.platform.ValueElement
+import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.platform.InspectorValueInfo
+import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
@@ -55,7 +56,14 @@
top = top,
end = end,
bottom = bottom,
- rtlAware = true
+ rtlAware = true,
+ inspectorInfo = debugInspectorInfo {
+ name = "padding"
+ properties["start"] = start
+ properties["top"] = top
+ properties["end"] = end
+ properties["bottom"] = bottom
+ }
)
)
@@ -80,7 +88,12 @@
top = vertical,
end = horizontal,
bottom = vertical,
- rtlAware = true
+ rtlAware = true,
+ inspectorInfo = debugInspectorInfo {
+ name = "padding"
+ properties["horizontal"] = horizontal
+ properties["vertical"] = vertical
+ }
)
)
@@ -96,7 +109,19 @@
*/
@Stable
fun Modifier.padding(all: Dp) =
- this.then(PaddingModifier(start = all, top = all, end = all, bottom = all, rtlAware = true))
+ this.then(
+ PaddingModifier(
+ start = all,
+ top = all,
+ end = all,
+ bottom = all,
+ rtlAware = true,
+ inspectorInfo = debugInspectorInfo {
+ name = "padding"
+ value = all
+ }
+ )
+ )
/**
* Apply [PaddingValues] to the component as additional space along each edge of the content's left,
@@ -115,7 +140,14 @@
top = padding.top,
end = padding.end,
bottom = padding.bottom,
- rtlAware = true
+ rtlAware = true,
+ inspectorInfo = debugInspectorInfo {
+ name = "padding"
+ properties["start"] = padding.start
+ properties["top"] = padding.top
+ properties["end"] = padding.end
+ properties["bottom"] = padding.bottom
+ }
)
)
@@ -142,17 +174,25 @@
top = top,
end = right,
bottom = bottom,
- rtlAware = false
+ rtlAware = false,
+ inspectorInfo = debugInspectorInfo {
+ name = "absolutePadding"
+ properties["left"] = left
+ properties["top"] = top
+ properties["right"] = right
+ properties["bottom"] = bottom
+ }
)
)
-private data class PaddingModifier(
+private class PaddingModifier(
val start: Dp = 0.dp,
val top: Dp = 0.dp,
val end: Dp = 0.dp,
val bottom: Dp = 0.dp,
- val rtlAware: Boolean
-) : LayoutModifier, InspectableValue {
+ val rtlAware: Boolean,
+ inspectorInfo: InspectorInfo.() -> Unit
+) : LayoutModifier, InspectorValueInfo(inspectorInfo) {
init {
require(start.value >= 0f && top.value >= 0f && end.value >= 0f && bottom.value >= 0f) {
"Padding must be non-negative"
@@ -179,18 +219,23 @@
}
}
- override val nameFallback = if (rtlAware) "padding" else "absolutePadding"
+ override fun hashCode(): Int {
+ var result = start.hashCode()
+ result = 31 * result + top.hashCode()
+ result = 31 * result + end.hashCode()
+ result = 31 * result + bottom.hashCode()
+ result = 31 * result + rtlAware.hashCode()
+ return result
+ }
- override val valueOverride: Any?
- get() = if (start == top && top == end && end == bottom) start else null
-
- override val inspectableElements: Sequence<ValueElement>
- get() = sequenceOf(
- ValueElement(if (rtlAware) "start" else "left", start),
- ValueElement("top", top),
- ValueElement(if (rtlAware) "end" else "right", end),
- ValueElement("bottom", bottom)
- )
+ override fun equals(other: Any?): Boolean {
+ val otherModifier = other as? PaddingModifier ?: return false
+ return start == otherModifier.start &&
+ top == otherModifier.top &&
+ end == otherModifier.end &&
+ bottom == otherModifier.bottom &&
+ rtlAware == otherModifier.rtlAware
+ }
}
/**
diff --git a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputField.kt b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputField.kt
index 1b007a8..59ae659 100644
--- a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputField.kt
+++ b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputField.kt
@@ -19,16 +19,22 @@
import androidx.compose.foundation.BaseTextField
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.ScrollableColumn
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.savedinstancestate.savedInstanceState
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.SoftwareKeyboardController
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.unit.dp
private val KEYBOARD_TYPES = listOf(
Pair(KeyboardType.Text, "Text"),
@@ -86,6 +92,7 @@
val controller = remember { mutableStateOf<SoftwareKeyboardController?>(null) }
val state = savedInstanceState(saver = TextFieldValue.Saver) { TextFieldValue() }
BaseTextField(
+ modifier = demoTextFieldModifiers,
value = state.value,
keyboardType = keyboardType,
imeAction = imeAction,
@@ -97,3 +104,8 @@
}
)
}
+
+val demoTextFieldModifiers = Modifier
+ .padding(6.dp)
+ .border(1.dp, Color.LightGray, RoundedCornerShape(6.dp))
+ .padding(6.dp)
\ No newline at end of file
diff --git a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputFieldFocusTransition.kt b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputFieldFocusTransition.kt
index 97c535c..ac30ec6 100644
--- a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputFieldFocusTransition.kt
+++ b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputFieldFocusTransition.kt
@@ -25,7 +25,6 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.savedinstancestate.savedInstanceState
import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.ExperimentalFocus
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.isFocused
@@ -69,7 +68,7 @@
BaseTextField(
value = state.value,
- modifier = Modifier
+ modifier = demoTextFieldModifiers
.focusObserver { color = if (it.isFocused) Red else Black }
.focusRequester(focusRequester),
textStyle = TextStyle(color = color, fontSize = 32.sp),
diff --git a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputFieldTrickyUseCase.kt b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputFieldTrickyUseCase.kt
index abbdbb9..c1cee2d 100644
--- a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputFieldTrickyUseCase.kt
+++ b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeInputFieldTrickyUseCase.kt
@@ -42,6 +42,7 @@
private fun RejectNonDigits() {
val state = savedInstanceState(saver = TextFieldValue.Saver) { TextFieldValue() }
BaseTextField(
+ modifier = demoTextFieldModifiers,
value = state.value,
textStyle = TextStyle(fontSize = 32.sp),
onValueChange = {
@@ -58,6 +59,7 @@
private fun RejectComposition() {
val state = savedInstanceState(saver = TextFieldValue.Saver) { TextFieldValue() }
BaseTextField(
+ modifier = demoTextFieldModifiers,
value = state.value,
textStyle = TextStyle(fontSize = 32.sp),
onValueChange = {
diff --git a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelection.kt b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelection.kt
index fa257fc..8e24042 100644
--- a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelection.kt
+++ b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelection.kt
@@ -167,7 +167,8 @@
SelectionContainer(
selection = selection.value,
- onSelectionChange = { selection.value = it }) {
+ onSelectionChange = { selection.value = it }
+ ) {
Column(Modifier.fillMaxHeight()) {
Text(
text = textSelectable,
diff --git a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeVariousInputField.kt b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeVariousInputField.kt
index 3af4936..c8c6d2b 100644
--- a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeVariousInputField.kt
+++ b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeVariousInputField.kt
@@ -246,6 +246,7 @@
) {
val state = savedInstanceState(saver = TextFieldValue.Saver) { TextFieldValue() }
BaseTextField(
+ modifier = demoTextFieldModifiers,
value = state.value,
keyboardType = keyboardType,
imeAction = imeAction,
@@ -274,7 +275,7 @@
private fun HintEditText(hintText: @Composable () -> Unit) {
val state = savedInstanceState(saver = TextFieldValue.Saver) { TextFieldValue() }
- Box {
+ Box(demoTextFieldModifiers) {
BaseTextField(
modifier = Modifier.fillMaxWidth(),
value = state.value,
diff --git a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/TailFollowingTextField.kt b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/TailFollowingTextField.kt
index b1579e7..a207ecb 100644
--- a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/TailFollowingTextField.kt
+++ b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/TailFollowingTextField.kt
@@ -18,17 +18,14 @@
import androidx.compose.foundation.BaseTextField
import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.savedinstancestate.savedInstanceState
import androidx.compose.ui.Layout
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
-import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.Constraints
@@ -46,9 +43,8 @@
value = hstate.value,
onValueChange = { hstate.value = it },
modifier = Modifier
- .padding(20.dp)
+ .then(demoTextFieldModifiers)
.fillMaxWidth()
- .background(color = Color.Gray)
.clipToBounds()
)
@@ -59,10 +55,9 @@
value = vstate.value,
onValueChange = { vstate.value = it },
modifier = Modifier
- .padding(20.dp)
+ .then(demoTextFieldModifiers)
.fillMaxWidth()
.height(120.dp)
- .background(Color.Gray)
.clipToBounds()
)
}
diff --git a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
index ebda198..0d7659d 100644
--- a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
+++ b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
@@ -144,7 +144,7 @@
* communicating with platform text input service, e.g. software keyboard on Android. Called with
* [SoftwareKeyboardController] instance which can be used for requesting input show/hide software
* keyboard.
- * @param cursorColor Color of the cursor. If [Color.Unset], there will be no cursor drawn
+ * @param cursorColor Color of the cursor. If [Color.Unspecified], there will be no cursor drawn
*/
@Composable
@OptIn(
@@ -162,7 +162,7 @@
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
onTextInputStarted: (SoftwareKeyboardController) -> Unit = {},
- cursorColor: Color = Color.Unset
+ cursorColor: Color = Color.Unspecified
) {
// If developer doesn't pass new value to TextField, recompose won't happen but internal state
// and IME may think it is updated. To fix this inconsistent state, enforce recompose.
@@ -419,8 +419,8 @@
val modifiers = modifier.focusRequester(focusRequester)
.then(focusObserver)
.then(cursorModifier)
- .then(if (state.hasFocus) dragPositionGestureModifier else Modifier)
- .then(if (state.hasFocus) selectionLongPressModifier else Modifier)
+ .then(dragPositionGestureModifier)
+ .then(selectionLongPressModifier)
.then(focusRequestTapModifier)
.then(drawModifier)
.then(onPositionedModifier)
@@ -651,8 +651,8 @@
val animationClocks = AnimationClockAmbient.current
val cursorAlpha = remember(animationClocks) { AnimatedFloatModel(0f, animationClocks) }
- if (state.hasFocus && value.selection.collapsed && cursorColor != Color.Unset) {
- onCommit(cursorColor) {
+ if (state.hasFocus && value.selection.collapsed && cursorColor != Color.Unspecified) {
+ onCommit(cursorColor, value.text) {
if (blinkingCursorEnabled) {
cursorAlpha.animateTo(0f, anim = cursorAnimationSpec)
} else {
@@ -699,7 +699,7 @@
// TODO(b/151940543): Remove this variable when we have a solution for idling animations
@InternalTextApi
- /** @suppress */
+/** @suppress */
var blinkingCursorEnabled: Boolean = true
@VisibleForTesting
set
\ No newline at end of file
diff --git a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.kt b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.kt
index a9f2caa..b5ebdcf 100644
--- a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.kt
+++ b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.kt
@@ -42,6 +42,7 @@
import androidx.compose.ui.text.input.getTextBeforeSelection
import androidx.compose.ui.text.style.ResolvedTextDirection
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.annotation.VisibleForTesting
import kotlin.math.max
import kotlin.math.min
@@ -176,7 +177,7 @@
override fun onStop(velocity: Offset) {
super.onStop(velocity)
state?.showFloatingToolbar = true
- showSelectionToolbar()
+ if (textToolbar?.status == TextToolbarStatus.Hidden) showSelectionToolbar()
}
}
@@ -227,7 +228,7 @@
super.onStop(velocity)
state?.draggingHandle = false
state?.showFloatingToolbar = true
- showSelectionToolbar()
+ if (textToolbar?.status == TextToolbarStatus.Hidden) showSelectionToolbar()
}
}
}
@@ -337,6 +338,17 @@
setSelectionStatus(false)
}
+ @VisibleForTesting
+ internal fun selectAll() {
+ setSelectionStatus(true)
+
+ val newValue = TextFieldValue(
+ text = value.text,
+ selection = TextRange(0, value.text.length)
+ )
+ onValueChange(newValue)
+ }
+
internal fun getHandlePosition(isStartHandle: Boolean): Offset {
return if (isStartHandle)
getSelectionHandleCoordinates(
@@ -381,11 +393,18 @@
}
} else null
+ val selectAll: (() -> Unit)? = if (value.selection.length != value.text.length) {
+ {
+ selectAll()
+ }
+ } else null
+
textToolbar?.showMenu(
rect = getContentRect(),
onCopyRequested = copy,
onPasteRequested = paste,
- onCutRequested = cut
+ onCutRequested = cut,
+ onSelectAllRequested = selectAll
)
}
diff --git a/compose/foundation/foundation-text/src/test/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManagerTest.kt b/compose/foundation/foundation-text/src/test/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManagerTest.kt
index fbaf29f..bd7cda3 100644
--- a/compose/foundation/foundation-text/src/test/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManagerTest.kt
+++ b/compose/foundation/foundation-text/src/test/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManagerTest.kt
@@ -390,6 +390,30 @@
}
@Test
+ fun selectAll() {
+ manager.value = TextFieldValue(
+ text = text,
+ selection = TextRange(0)
+ )
+
+ manager.selectAll()
+
+ assertThat(value.selection).isEqualTo(TextRange(0, text.length))
+ }
+
+ @Test
+ fun selectAll_whenPartiallySelected() {
+ manager.value = TextFieldValue(
+ text = text,
+ selection = TextRange(0, 5)
+ )
+
+ manager.selectAll()
+
+ assertThat(value.selection).isEqualTo(TextRange(0, text.length))
+ }
+
+ @Test
fun showSelectionToolbar_trigger_textToolbar_showMenu_Clipboard_empty_not_show_paste() {
manager.value = TextFieldValue(
text = text + text,
@@ -398,7 +422,7 @@
manager.showSelectionToolbar()
- verify(textToolbar, times(1)).showMenu(any(), any(), isNull(), any())
+ verify(textToolbar, times(1)).showMenu(any(), any(), isNull(), any(), any())
}
@Test
@@ -411,7 +435,27 @@
manager.showSelectionToolbar()
- verify(textToolbar, times(1)).showMenu(any(), isNull(), any(), isNull())
+ verify(textToolbar, times(1)).showMenu(any(), isNull(), any(), isNull(), any())
+ }
+
+ @Test
+ fun showSelectionToolbar_trigger_textToolbar_showMenu_no_text_show_paste_only() {
+ whenever(clipboardManager.getText()).thenReturn(AnnotatedString(text))
+ manager.value = TextFieldValue()
+
+ manager.showSelectionToolbar()
+
+ verify(textToolbar, times(1)).showMenu(any(), isNull(), any(), isNull(), isNull())
+ }
+
+ @Test
+ fun showSelectionToolbar_trigger_textToolbar_no_menu() {
+ whenever(clipboardManager.getText()).thenReturn(null)
+ manager.value = TextFieldValue()
+
+ manager.showSelectionToolbar()
+
+ verify(textToolbar, times(1)).showMenu(any(), isNull(), isNull(), isNull(), isNull())
}
@Test
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/FoundationDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/FoundationDemos.kt
index 17f32ab..cdeba47 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/FoundationDemos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/FoundationDemos.kt
@@ -23,12 +23,15 @@
import androidx.compose.integration.demos.common.ComposableDemo
import androidx.compose.integration.demos.common.DemoCategory
-val FoundationDemos = DemoCategory("Foundation", listOf(
- ComposableDemo("Draggable, Scrollable, Zoomable") { HighLevelGesturesDemo() },
- ComposableDemo("Scrollable Column") { ScrollableColumnSample() },
- ComposableDemo("Controlled Scrollable Row") { ControlledScrollableRowSample() },
- ComposableDemo("Draw Modifiers") { DrawModifiersDemo() },
- DemoCategory("Lazy lists", LazyListDemos),
- ComposableDemo("Priority InteractionState") { PriorityInteractionStateSample() },
- ComposableDemo("Multiple-interaction InteractionState") { MultipleInteractionStateSample() }
-))
+val FoundationDemos = DemoCategory(
+ "Foundation",
+ listOf(
+ ComposableDemo("Draggable, Scrollable, Zoomable") { HighLevelGesturesDemo() },
+ ComposableDemo("Scrollable Column") { ScrollableColumnSample() },
+ ComposableDemo("Controlled Scrollable Row") { ControlledScrollableRowSample() },
+ ComposableDemo("Draw Modifiers") { DrawModifiersDemo() },
+ DemoCategory("Lazy lists", LazyListDemos),
+ ComposableDemo("Priority InteractionState") { PriorityInteractionStateSample() },
+ ComposableDemo("Multiple-interaction InteractionState") { MultipleInteractionStateSample() }
+ )
+)
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldCursorTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldCursorTest.kt
index c762904..d4037ba 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldCursorTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldCursorTest.kt
@@ -22,6 +22,8 @@
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.preferredSize
import androidx.compose.foundation.text.CoreTextField
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.ExperimentalFocus
import androidx.compose.ui.focus.isFocused
@@ -42,6 +44,7 @@
import androidx.ui.test.createComposeRule
import androidx.ui.test.hasInputMethodsSupport
import androidx.ui.test.performClick
+import androidx.ui.test.performTextReplacement
import org.junit.Rule
import org.junit.Test
import java.util.concurrent.CountDownLatch
@@ -156,7 +159,7 @@
.preferredSize(width, height)
.background(Color.White)
.focusObserver { if (it.isFocused) latch.countDown() },
- cursorColor = Color.Unset
+ cursorColor = Color.Unspecified
)
}
}
@@ -191,6 +194,55 @@
)
}
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ fun cursorNotBlinking_whileTyping() = with(rule.density) {
+ val width = 10.dp
+ val height = 20.dp
+ val latch = CountDownLatch(1)
+ rule.setContent {
+ // The padding helps if the test is run accidentally in landscape. Landscape makes
+ // the cursor to be next to the navigation bar which affects the red color to be a bit
+ // different - possibly anti-aliasing.
+ Box(Modifier.padding(10.dp)) {
+ val text = remember { mutableStateOf(TextFieldValue("test")) }
+ CoreTextField(
+ value = text.value,
+ onValueChange = { text.value = it },
+ textStyle = TextStyle(color = Color.White, background = Color.White),
+ modifier = Modifier
+ .preferredSize(width, height)
+ .background(Color.White)
+ .focusObserver { if (it.isFocused) latch.countDown() },
+ cursorColor = Color.Red
+ )
+ }
+ }
+
+ rule.onNode(hasInputMethodsSupport()).performClick()
+ assert(latch.await(1, TimeUnit.SECONDS))
+ rule.waitForIdle()
+
+ // cursor visible first 500 ms
+ rule.clockTestRule.advanceClock(500)
+ // TODO(b/170298051) check here that cursor is visible when we have a way to control
+ // cursor position when sending a text
+
+ // change text field value
+ rule.onNode(hasInputMethodsSupport())
+ .performTextReplacement("", true)
+ rule.waitForIdle()
+
+ // cursor would have been invisible during next 500 ms if cursor blinks while typing.
+ // To prevent blinking while typing we restart animation when new symbol is typed.
+ rule.clockTestRule.advanceClock(400)
+ with(rule.density) {
+ rule.onNode(hasInputMethodsSupport())
+ .captureToBitmap()
+ .assertCursor(2.dp, this)
+ }
+ }
+
private fun Bitmap.assertCursor(cursorWidth: Dp, density: Density) {
val cursorWidthPx = (with(density) { cursorWidth.toIntPx() })
val width = width
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
index e4599c3..abeaf96 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
@@ -236,8 +236,10 @@
if (it != null) {
Spacer(Modifier.preferredHeight(101.dp).fillParentMaxWidth().testTag(it))
} else {
- Spacer(Modifier.preferredHeight(101.dp).fillParentMaxWidth()
- .testTag(nullTestTag))
+ Spacer(
+ Modifier.preferredHeight(101.dp).fillParentMaxWidth()
+ .testTag(nullTestTag)
+ )
}
}
}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
index a5f5b5a..3963601 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
@@ -236,8 +236,10 @@
if (it != null) {
Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight().testTag(it))
} else {
- Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight()
- .testTag(nullTestTag))
+ Spacer(
+ Modifier.preferredWidth(101.dp).fillParentMaxHeight()
+ .testTag(nullTestTag)
+ )
}
}
}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/BaseTextField.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/BaseTextField.kt
index ab39640..38f4d25 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/BaseTextField.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/BaseTextField.kt
@@ -63,8 +63,8 @@
* @param onValueChange Called when the input service updates values in
* [TextFieldValue].
* @param modifier optional [Modifier] for this text field.
- * @param textColor [Color] to apply to the text. If [Color.Unset], and [textStyle] has no color
- * set, this will be [AmbientContentColor].
+ * @param textColor [Color] to apply to the text. If [Color.Unspecified], and [textStyle] has no
+ * color set, this will be [AmbientContentColor].
* @param textStyle Style configuration that applies at character level such as color, font etc.
* The default [textStyle] uses the [AmbientTextStyle] defined by the theme
* @param keyboardType The keyboard type to be used in this text field. Note that this input type
@@ -84,7 +84,7 @@
* communicating with platform text input service, e.g. software keyboard on Android. Called with
* [SoftwareKeyboardController] instance which can be used for requesting input show/hide software
* keyboard.
- * @param cursorColor Color of the cursor. If [Color.Unset], there will be no cursor drawn
+ * @param cursorColor Color of the cursor. If [Color.Unspecified], there will be no cursor drawn
*
* @see TextFieldValue
* @see ImeAction
@@ -98,7 +98,7 @@
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
modifier: Modifier = Modifier,
- textColor: Color = Color.Unset,
+ textColor: Color = Color.Unspecified,
textStyle: TextStyle = AmbientTextStyle.current,
keyboardType: KeyboardType = KeyboardType.Text,
imeAction: ImeAction = ImeAction.Unspecified,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Border.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Border.kt
index 8409bd4..1ae2602 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Border.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Border.kt
@@ -39,8 +39,7 @@
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
-import androidx.compose.ui.platform.InspectableValue
-import androidx.compose.ui.platform.ValueElement
+import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.util.nativeClass
@@ -80,9 +79,20 @@
* @param brush brush to paint the border with
* @param shape shape of the border
*/
-fun Modifier.border(width: Dp, brush: Brush, shape: Shape): Modifier = composed {
- BorderModifier(remember { BorderModifierCache() }, shape, width, brush)
-}
+fun Modifier.border(width: Dp, brush: Brush, shape: Shape): Modifier = composed(
+ factory = { BorderModifier(remember { BorderModifierCache() }, shape, width, brush) },
+ inspectorInfo = debugInspectorInfo {
+ name = "border"
+ properties["width"] = width
+ if (brush is SolidColor) {
+ properties["color"] = brush.value
+ value = brush.value
+ } else {
+ properties["brush"] = brush
+ }
+ properties["shape"] = shape
+ }
+)
/**
* Returns a [Modifier] that adds border with appearance specified with a [border] and a [shape]
@@ -150,7 +160,7 @@
private val shape: Shape,
private val borderWidth: Dp,
private val brush: Brush
-) : DrawModifier, InspectableValue {
+) : DrawModifier {
// put params to constructor to ensure proper equals and update cache after construction
init {
@@ -226,23 +236,6 @@
result = 31 * result + brush.hashCode()
return result
}
-
- override val inspectableElements: Sequence<ValueElement>
- get() {
- val brushParam = if (brush is SolidColor) {
- ValueElement("color", brush.value)
- } else {
- ValueElement("brush", brush)
- }
- return sequenceOf(
- brushParam,
- ValueElement("shape", shape),
- ValueElement("width", borderWidth)
- )
- }
- override val nameFallback = "border"
- override val valueOverride: Any?
- get() = (brush as? SolidColor)?.value ?: brush
}
private class BorderModifierCache {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Text.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Text.kt
index bbc80df..55d4056 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Text.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Text.kt
@@ -69,8 +69,8 @@
*
* @param text The text to be displayed.
* @param modifier [Modifier] to apply to this layout node.
- * @param color [Color] to apply to the text. If [Color.Unset], and [style] has no color set, this
- * will be [AmbientContentColor].
+ * @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
+ * this will be [AmbientContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
* @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
* See [TextStyle.fontStyle].
@@ -98,7 +98,7 @@
fun Text(
text: String,
modifier: Modifier = Modifier,
- color: Color = Color.Unset,
+ color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Inherit,
fontStyle: FontStyle? = null,
fontWeight: FontWeight? = null,
@@ -162,8 +162,8 @@
*
* @param text The text to be displayed.
* @param modifier [Modifier] to apply to this layout node.
- * @param color [Color] to apply to the text. If [Color.Unset], and [style] has no color set, this
- * will be [AmbientContentColor].
+ * @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
+ * this will be [AmbientContentColor].
* @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
* @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
* See [TextStyle.fontStyle].
@@ -193,7 +193,7 @@
fun Text(
text: AnnotatedString,
modifier: Modifier = Modifier,
- color: Color = Color.Unset,
+ color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Inherit,
fontStyle: FontStyle? = null,
fontWeight: FontWeight? = null,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt
index 15f11b6..565ffbe 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt
@@ -344,7 +344,8 @@
// can be larger if items were resized, or if, for example, we were previously
// displaying the item 15, but now we have only 10 items in total in the data set.
if (scrollToBeConsumed.roundToInt().sign == scrollDelta.sign &&
- abs(scrollToBeConsumed.roundToInt()) >= abs(scrollDelta)) {
+ abs(scrollToBeConsumed.roundToInt()) >= abs(scrollDelta)
+ ) {
scrollToBeConsumed -= scrollDelta
} else {
scrollToBeConsumed = 0f
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/gestures/DesktopScrollableTest.kt b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/gestures/DesktopScrollableTest.kt
index a92840c..ef4efb8 100644
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/gestures/DesktopScrollableTest.kt
+++ b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/gestures/DesktopScrollableTest.kt
@@ -18,8 +18,8 @@
import androidx.compose.animation.core.AnimationClockObservable
import androidx.compose.animation.core.AnimationClockObserver
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.animation.defaultFlingConfig
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
diff --git a/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/TextFieldToggleTextBenchmark.kt b/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/TextFieldToggleTextBenchmark.kt
index b1769b9..e1a196e 100644
--- a/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/TextFieldToggleTextBenchmark.kt
+++ b/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/TextFieldToggleTextBenchmark.kt
@@ -32,6 +32,7 @@
import androidx.test.filters.SmallTest
import androidx.ui.integration.test.TextBenchmarkTestRule
import androidx.ui.integration.test.core.text.TextFieldToggleTextTestCase
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -74,6 +75,7 @@
* given input. This is the time taken to call the [BaseTextField] composable function.
*/
@Test
+ @Ignore
fun first_compose() {
benchmarkRule.benchmarkFirstComposeFast(caseFactory)
}
@@ -84,6 +86,7 @@
* [BaseTextField] composable.
*/
@Test
+ @Ignore
fun first_measure() {
benchmarkRule.benchmarkFirstMeasureFast(caseFactory)
}
@@ -93,6 +96,7 @@
* given input.
*/
@Test
+ @Ignore
fun first_layout() {
benchmarkRule.benchmarkFirstLayoutFast(caseFactory)
}
@@ -102,6 +106,7 @@
* input.
*/
@Test
+ @Ignore
fun first_draw() {
benchmarkRule.benchmarkFirstDrawFast(caseFactory)
}
@@ -111,6 +116,7 @@
* constrains changed. This is mainly the time used to re-measure and re-layout the composable.
*/
@Test
+ @Ignore
fun layout() {
benchmarkRule.benchmarkLayoutPerf(caseFactory)
}
@@ -119,6 +125,7 @@
* Measure the time taken by redrawing the [BaseTextField] composable.
*/
@Test
+ @Ignore
fun draw() {
benchmarkRule.benchmarkDrawPerf(caseFactory)
}
diff --git a/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/lazy/LazyListScrollingBenchmark.kt b/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/lazy/LazyListScrollingBenchmark.kt
index b7ffdd7..49fb51c 100644
--- a/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/lazy/LazyListScrollingBenchmark.kt
+++ b/compose/integration-tests/benchmark/src/androidTest/java/androidx/compose/ui/lazy/LazyListScrollingBenchmark.kt
@@ -290,11 +290,14 @@
@Composable
fun RemeasurableItem() {
- Layout(emptyContent(), modifier = object : RemeasurementModifier {
- override fun onRemeasurementAvailable(remeasurement: Remeasurement) {
- [email protected] = remeasurement
+ Layout(
+ emptyContent(),
+ modifier = object : RemeasurementModifier {
+ override fun onRemeasurementAvailable(remeasurement: Remeasurement) {
+ [email protected] = remeasurement
+ }
}
- }) { _, _ ->
+ ) { _, _ ->
val size = size.toIntPx()
layout(size, size) {}
}
diff --git a/compose/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/NestedBoxesBenchmark.kt b/compose/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/NestedBoxesBenchmark.kt
new file mode 100644
index 0000000..1995d57
--- /dev/null
+++ b/compose/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/NestedBoxesBenchmark.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.ui.benchmark.test
+
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkFirstCompose
+import androidx.compose.testutils.benchmark.benchmarkFirstLayout
+import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.test.filters.LargeTest
+import androidx.ui.integration.test.foundation.NestedBoxesTestCase
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Benchmark that runs [NestedBoxesTestCase].
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+class NestedBoxesBenchmark(private val depth: Int, private val children: Int) {
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "depth={0} children={1}")
+ fun initParameters(): Array<Any> = arrayOf(arrayOf(7, 2), arrayOf(4, 5), arrayOf(100, 1))
+ }
+
+ @get:Rule
+ val benchmarkRule = ComposeBenchmarkRule()
+
+ private val checkboxCaseFactory = { NestedBoxesTestCase(depth, children) }
+
+ @Test
+ fun first_compose() {
+ benchmarkRule.benchmarkFirstCompose(checkboxCaseFactory)
+ }
+
+ @Test
+ fun first_measure() {
+ benchmarkRule.benchmarkFirstMeasure(checkboxCaseFactory)
+ }
+
+ @Test
+ fun first_layout() {
+ benchmarkRule.benchmarkFirstLayout(checkboxCaseFactory)
+ }
+}
\ No newline at end of file
diff --git a/compose/integration-tests/src/main/java/androidx/ui/integration/test/foundation/NestedBoxesTestCase.kt b/compose/integration-tests/src/main/java/androidx/ui/integration/test/foundation/NestedBoxesTestCase.kt
new file mode 100644
index 0000000..6021066
--- /dev/null
+++ b/compose/integration-tests/src/main/java/androidx/ui/integration/test/foundation/NestedBoxesTestCase.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.ui.integration.test.foundation
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.ComposeTestCase
+
+/**
+ * Test case representing a layout hierarchy of nested boxes.
+ */
+class NestedBoxesTestCase(
+ private val depth: Int,
+ private val children: Int
+) : ComposeTestCase {
+
+ @Composable
+ override fun emitContent() {
+ Box {
+ emitBoxes(depth - 1, children)
+ }
+ }
+
+ @Composable
+ private fun emitBoxes(depth: Int, children: Int) {
+ if (depth == 0) return
+ repeat(children) {
+ Box {
+ emitBoxes(depth - 1, children)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/compose/material/material-icons-extended/src/androidAndroidTest/kotlin/androidx/compose/material/icons/IconComparisonTest.kt b/compose/material/material-icons-extended/src/androidAndroidTest/kotlin/androidx/compose/material/icons/IconComparisonTest.kt
index e74026a..d418ff5 100644
--- a/compose/material/material-icons-extended/src/androidAndroidTest/kotlin/androidx/compose/material/icons/IconComparisonTest.kt
+++ b/compose/material/material-icons-extended/src/androidAndroidTest/kotlin/androidx/compose/material/icons/IconComparisonTest.kt
@@ -47,6 +47,8 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
+import kotlin.math.ceil
+import kotlin.math.roundToInt
import kotlin.reflect.KProperty0
import kotlin.reflect.jvm.javaGetter
@@ -81,7 +83,8 @@
@Parameterized.Parameters(name = "{1}")
fun initIconSublist(): Array<Array<Any>> {
val numberOfChunks = 4
- val subLists = AllIcons.chunked(AllIcons.size / numberOfChunks)
+ val listSize = ceil(AllIcons.size / numberOfChunks.toFloat()).roundToInt()
+ val subLists = AllIcons.chunked(listSize)
return subLists.mapIndexed { index, list ->
arrayOf(list, "${index + 1}of$numberOfChunks")
}.toTypedArray()
@@ -111,6 +114,11 @@
val iconName = property.javaGetter!!.declaringClass.canonicalName!!
+ // The XML inflated VectorAsset doesn't have a name, and we set a name in the
+ // programmatic VectorAsset. This doesn't affect how the VectorAsset is drawn, so we
+ // make sure the names match so the comparison does not fail.
+ xmlVector = xmlVector!!.copy(name = programmaticVector.name)
+
assertVectorAssetsAreEqual(xmlVector!!, programmaticVector, iconName)
matcher.assertBitmapsAreEqual(
diff --git a/compose/material/material/api/current.txt b/compose/material/material/api/current.txt
index 810c909..cc0b723 100644
--- a/compose/material/material/api/current.txt
+++ b/compose/material/material/api/current.txt
@@ -166,21 +166,20 @@
method @androidx.compose.runtime.Composable public static void Card-IHU7g64(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface CheckboxColors {
+ method public long borderColor-0d7_KjU(boolean enabled, androidx.compose.foundation.selection.ToggleableState state);
+ method public long boxColor-0d7_KjU(boolean enabled, androidx.compose.foundation.selection.ToggleableState state);
+ method public long checkmarkColor-0d7_KjU(androidx.compose.foundation.selection.ToggleableState state);
+ }
+
public final class CheckboxConstants {
- method @androidx.compose.runtime.Composable public long animateDefaultBorderColor-xAuy4YE(androidx.compose.foundation.selection.ToggleableState state, boolean enabled, optional long checkedColor, optional long uncheckedColor, optional long disabledColor, optional long disabledIndeterminateColor);
- method @androidx.compose.runtime.Composable public long animateDefaultBoxColor-4eRnVYk(androidx.compose.foundation.selection.ToggleableState state, boolean enabled, optional long checkedColor, optional long uncheckedColor, optional long disabledCheckedColor, optional long disabledUncheckedColor, optional long disabledIndeterminateColor);
- method @androidx.compose.runtime.Composable public long animateDefaultCheckmarkColor-9THJUkw(androidx.compose.foundation.selection.ToggleableState state, optional long checkedColor, optional long uncheckedColor);
- method @androidx.compose.runtime.Composable public long defaultDisabledIndeterminateColor-8_81llA(long checkedColor);
- method public long getDefaultDisabledColor-0d7_KjU();
- method public long getDefaultUncheckedColor-0d7_KjU();
- property public final long defaultDisabledColor;
- property public final long defaultUncheckedColor;
+ method @androidx.compose.runtime.Composable public androidx.compose.material.CheckboxColors defaultColors-QGkLkJU(optional long checkedColor, optional long uncheckedColor, optional long checkmarkColor, optional long disabledColor, optional long disabledIndeterminateColor);
field public static final androidx.compose.material.CheckboxConstants INSTANCE;
}
public final class CheckboxKt {
- method @androidx.compose.runtime.Composable public static void Checkbox-JW8VE8g(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long checkedColor, optional long uncheckedColor);
- method @androidx.compose.runtime.Composable public static void TriStateCheckbox-yIvEug4(androidx.compose.foundation.selection.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long checkMarkColor, optional long boxColor, optional long borderColor);
+ method @androidx.compose.runtime.Composable public static void Checkbox(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.CheckboxColors colors);
+ method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.foundation.selection.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.CheckboxColors colors);
}
@androidx.compose.runtime.Stable public final class Colors {
@@ -431,17 +430,17 @@
method @androidx.compose.runtime.Composable public static void LinearProgressIndicator-kLDug40(@FloatRange(from=0.0, to=1.0) float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional long backgroundColor);
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface RadioButtonColors {
+ method public long radioColor-0d7_KjU(boolean enabled, boolean selected);
+ }
+
public final class RadioButtonConstants {
- method @androidx.compose.runtime.Composable public long animateDefaultColor-tRWe6DU(boolean selected, boolean enabled, optional long selectedColor, optional long unselectedColor, optional long disabledColor);
- method public long getDefaultDisabledColor-0d7_KjU();
- method public long getDefaultUnselectedColor-0d7_KjU();
- property public final long defaultDisabledColor;
- property public final long defaultUnselectedColor;
+ method @androidx.compose.runtime.Composable public androidx.compose.material.RadioButtonColors defaultColors-xS_xkl8(optional long selectedColor, optional long unselectedColor, optional long disabledColor);
field public static final androidx.compose.material.RadioButtonConstants INSTANCE;
}
public final class RadioButtonKt {
- method @androidx.compose.runtime.Composable public static void RadioButton-BNs5H-w(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long color);
+ method @androidx.compose.runtime.Composable public static void RadioButton(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.RadioButtonColors colors);
}
@androidx.compose.runtime.Immutable public final class ResistanceConfig {
diff --git a/compose/material/material/api/public_plus_experimental_current.txt b/compose/material/material/api/public_plus_experimental_current.txt
index 810c909..cc0b723 100644
--- a/compose/material/material/api/public_plus_experimental_current.txt
+++ b/compose/material/material/api/public_plus_experimental_current.txt
@@ -166,21 +166,20 @@
method @androidx.compose.runtime.Composable public static void Card-IHU7g64(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface CheckboxColors {
+ method public long borderColor-0d7_KjU(boolean enabled, androidx.compose.foundation.selection.ToggleableState state);
+ method public long boxColor-0d7_KjU(boolean enabled, androidx.compose.foundation.selection.ToggleableState state);
+ method public long checkmarkColor-0d7_KjU(androidx.compose.foundation.selection.ToggleableState state);
+ }
+
public final class CheckboxConstants {
- method @androidx.compose.runtime.Composable public long animateDefaultBorderColor-xAuy4YE(androidx.compose.foundation.selection.ToggleableState state, boolean enabled, optional long checkedColor, optional long uncheckedColor, optional long disabledColor, optional long disabledIndeterminateColor);
- method @androidx.compose.runtime.Composable public long animateDefaultBoxColor-4eRnVYk(androidx.compose.foundation.selection.ToggleableState state, boolean enabled, optional long checkedColor, optional long uncheckedColor, optional long disabledCheckedColor, optional long disabledUncheckedColor, optional long disabledIndeterminateColor);
- method @androidx.compose.runtime.Composable public long animateDefaultCheckmarkColor-9THJUkw(androidx.compose.foundation.selection.ToggleableState state, optional long checkedColor, optional long uncheckedColor);
- method @androidx.compose.runtime.Composable public long defaultDisabledIndeterminateColor-8_81llA(long checkedColor);
- method public long getDefaultDisabledColor-0d7_KjU();
- method public long getDefaultUncheckedColor-0d7_KjU();
- property public final long defaultDisabledColor;
- property public final long defaultUncheckedColor;
+ method @androidx.compose.runtime.Composable public androidx.compose.material.CheckboxColors defaultColors-QGkLkJU(optional long checkedColor, optional long uncheckedColor, optional long checkmarkColor, optional long disabledColor, optional long disabledIndeterminateColor);
field public static final androidx.compose.material.CheckboxConstants INSTANCE;
}
public final class CheckboxKt {
- method @androidx.compose.runtime.Composable public static void Checkbox-JW8VE8g(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long checkedColor, optional long uncheckedColor);
- method @androidx.compose.runtime.Composable public static void TriStateCheckbox-yIvEug4(androidx.compose.foundation.selection.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long checkMarkColor, optional long boxColor, optional long borderColor);
+ method @androidx.compose.runtime.Composable public static void Checkbox(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.CheckboxColors colors);
+ method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.foundation.selection.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.CheckboxColors colors);
}
@androidx.compose.runtime.Stable public final class Colors {
@@ -431,17 +430,17 @@
method @androidx.compose.runtime.Composable public static void LinearProgressIndicator-kLDug40(@FloatRange(from=0.0, to=1.0) float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional long backgroundColor);
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface RadioButtonColors {
+ method public long radioColor-0d7_KjU(boolean enabled, boolean selected);
+ }
+
public final class RadioButtonConstants {
- method @androidx.compose.runtime.Composable public long animateDefaultColor-tRWe6DU(boolean selected, boolean enabled, optional long selectedColor, optional long unselectedColor, optional long disabledColor);
- method public long getDefaultDisabledColor-0d7_KjU();
- method public long getDefaultUnselectedColor-0d7_KjU();
- property public final long defaultDisabledColor;
- property public final long defaultUnselectedColor;
+ method @androidx.compose.runtime.Composable public androidx.compose.material.RadioButtonColors defaultColors-xS_xkl8(optional long selectedColor, optional long unselectedColor, optional long disabledColor);
field public static final androidx.compose.material.RadioButtonConstants INSTANCE;
}
public final class RadioButtonKt {
- method @androidx.compose.runtime.Composable public static void RadioButton-BNs5H-w(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long color);
+ method @androidx.compose.runtime.Composable public static void RadioButton(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.RadioButtonColors colors);
}
@androidx.compose.runtime.Immutable public final class ResistanceConfig {
diff --git a/compose/material/material/api/restricted_current.txt b/compose/material/material/api/restricted_current.txt
index 810c909..cc0b723 100644
--- a/compose/material/material/api/restricted_current.txt
+++ b/compose/material/material/api/restricted_current.txt
@@ -166,21 +166,20 @@
method @androidx.compose.runtime.Composable public static void Card-IHU7g64(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface CheckboxColors {
+ method public long borderColor-0d7_KjU(boolean enabled, androidx.compose.foundation.selection.ToggleableState state);
+ method public long boxColor-0d7_KjU(boolean enabled, androidx.compose.foundation.selection.ToggleableState state);
+ method public long checkmarkColor-0d7_KjU(androidx.compose.foundation.selection.ToggleableState state);
+ }
+
public final class CheckboxConstants {
- method @androidx.compose.runtime.Composable public long animateDefaultBorderColor-xAuy4YE(androidx.compose.foundation.selection.ToggleableState state, boolean enabled, optional long checkedColor, optional long uncheckedColor, optional long disabledColor, optional long disabledIndeterminateColor);
- method @androidx.compose.runtime.Composable public long animateDefaultBoxColor-4eRnVYk(androidx.compose.foundation.selection.ToggleableState state, boolean enabled, optional long checkedColor, optional long uncheckedColor, optional long disabledCheckedColor, optional long disabledUncheckedColor, optional long disabledIndeterminateColor);
- method @androidx.compose.runtime.Composable public long animateDefaultCheckmarkColor-9THJUkw(androidx.compose.foundation.selection.ToggleableState state, optional long checkedColor, optional long uncheckedColor);
- method @androidx.compose.runtime.Composable public long defaultDisabledIndeterminateColor-8_81llA(long checkedColor);
- method public long getDefaultDisabledColor-0d7_KjU();
- method public long getDefaultUncheckedColor-0d7_KjU();
- property public final long defaultDisabledColor;
- property public final long defaultUncheckedColor;
+ method @androidx.compose.runtime.Composable public androidx.compose.material.CheckboxColors defaultColors-QGkLkJU(optional long checkedColor, optional long uncheckedColor, optional long checkmarkColor, optional long disabledColor, optional long disabledIndeterminateColor);
field public static final androidx.compose.material.CheckboxConstants INSTANCE;
}
public final class CheckboxKt {
- method @androidx.compose.runtime.Composable public static void Checkbox-JW8VE8g(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long checkedColor, optional long uncheckedColor);
- method @androidx.compose.runtime.Composable public static void TriStateCheckbox-yIvEug4(androidx.compose.foundation.selection.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long checkMarkColor, optional long boxColor, optional long borderColor);
+ method @androidx.compose.runtime.Composable public static void Checkbox(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.CheckboxColors colors);
+ method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.foundation.selection.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.CheckboxColors colors);
}
@androidx.compose.runtime.Stable public final class Colors {
@@ -431,17 +430,17 @@
method @androidx.compose.runtime.Composable public static void LinearProgressIndicator-kLDug40(@FloatRange(from=0.0, to=1.0) float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional long backgroundColor);
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface RadioButtonColors {
+ method public long radioColor-0d7_KjU(boolean enabled, boolean selected);
+ }
+
public final class RadioButtonConstants {
- method @androidx.compose.runtime.Composable public long animateDefaultColor-tRWe6DU(boolean selected, boolean enabled, optional long selectedColor, optional long unselectedColor, optional long disabledColor);
- method public long getDefaultDisabledColor-0d7_KjU();
- method public long getDefaultUnselectedColor-0d7_KjU();
- property public final long defaultDisabledColor;
- property public final long defaultUnselectedColor;
+ method @androidx.compose.runtime.Composable public androidx.compose.material.RadioButtonColors defaultColors-xS_xkl8(optional long selectedColor, optional long unselectedColor, optional long disabledColor);
field public static final androidx.compose.material.RadioButtonConstants INSTANCE;
}
public final class RadioButtonKt {
- method @androidx.compose.runtime.Composable public static void RadioButton-BNs5H-w(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long color);
+ method @androidx.compose.runtime.Composable public static void RadioButton(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.RadioButtonColors colors);
}
@androidx.compose.runtime.Immutable public final class ResistanceConfig {
diff --git a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/VectorAssetGenerator.kt b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/VectorAssetGenerator.kt
index 060b0eb..9eee139 100644
--- a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/VectorAssetGenerator.kt
+++ b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/VectorAssetGenerator.kt
@@ -99,7 +99,8 @@
backingProperty,
MemberNames.MaterialIcon,
iconTheme.name,
- iconName)
+ iconName
+ )
vector.nodes.forEach { node -> addRecursively(node) }
endControlFlow()
}
diff --git a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ColorPickerDemo.kt b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ColorPickerDemo.kt
index 75bf244..7b0bd30 100644
--- a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ColorPickerDemo.kt
+++ b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ColorPickerDemo.kt
@@ -63,7 +63,7 @@
import androidx.compose.ui.graphics.ImageAsset
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.SolidColor
-import androidx.compose.ui.graphics.isSet
+import androidx.compose.ui.graphics.isSpecified
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.graphics.toPixelMap
import androidx.compose.ui.platform.DensityAmbient
@@ -106,7 +106,7 @@
// Work out if the new position is inside the circle we are drawing, and has a
// valid color associated to it. If not, keep the current position
val newColor = colorWheel.colorForPosition(newPosition)
- if (newColor.isSet) {
+ if (newColor.isSpecified) {
position = newPosition
onColorChange(newColor)
}
@@ -117,7 +117,7 @@
Box(Modifier.fillMaxSize()) {
Image(modifier = inputModifier, asset = colorWheel.image)
val color = colorWheel.colorForPosition(position)
- if (color.isSet) {
+ if (color.isSpecified) {
Magnifier(visible = isDragging, position = position, color = color)
}
}
@@ -342,7 +342,7 @@
val x = position.x.toInt().coerceAtLeast(0)
val y = position.y.toInt().coerceAtLeast(0)
with(image.toPixelMap()) {
- if (x >= width || y >= height) return Color.Unset
- return this[x, y].takeIf { it.alpha == 1f } ?: Color.Unset
+ if (x >= width || y >= height) return Color.Unspecified
+ return this[x, y].takeIf { it.alpha == 1f } ?: Color.Unspecified
}
}
diff --git a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt
index 9764fbd..ce4cf20 100644
--- a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt
+++ b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt
@@ -221,7 +221,7 @@
AmbientEmphasisLevels.current.medium.applyEmphasis(MaterialTheme.colors.onSurface)
}
Option.Error -> MaterialTheme.colors.error
- else -> Color.Unset
+ else -> Color.Unspecified
}
Column {
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt
index b5cf351..771a06b 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt
@@ -64,10 +64,12 @@
Divider()
ListItem(
text = { Text("One line clickable list item") },
- icon = { Image(
- icon56x56,
- colorFilter = ColorFilter.tint(AmbientContentColor.current)
- ) },
+ icon = {
+ Image(
+ icon56x56,
+ colorFilter = ColorFilter.tint(AmbientContentColor.current)
+ )
+ },
modifier = Modifier.clickable { }
)
Divider()
@@ -78,10 +80,12 @@
Divider()
ListItem(
text = { Text("One line list item") },
- icon = { Image(
- icon40x40,
- colorFilter = ColorFilter.tint(AmbientContentColor.current)
- ) },
+ icon = {
+ Image(
+ icon40x40,
+ colorFilter = ColorFilter.tint(AmbientContentColor.current)
+ )
+ },
trailing = { Icon(vectorIcon) }
)
Divider()
@@ -119,20 +123,24 @@
text = { Text("Two line list item with 40x40 icon") },
secondaryText = { Text("Secondary text") },
trailing = { Text("meta") },
- icon = { Image(
- icon40x40,
- colorFilter = ColorFilter.tint(AmbientContentColor.current)
- ) }
+ icon = {
+ Image(
+ icon40x40,
+ colorFilter = ColorFilter.tint(AmbientContentColor.current)
+ )
+ }
)
Divider()
var checked by remember { mutableStateOf(false) }
ListItem(
text = { Text("Two line list item") },
secondaryText = { Text("Secondary text") },
- icon = { Image(
- icon40x40,
- colorFilter = ColorFilter.tint(AmbientContentColor.current)
- ) },
+ icon = {
+ Image(
+ icon40x40,
+ colorFilter = ColorFilter.tint(AmbientContentColor.current)
+ )
+ },
trailing = {
Checkbox(checked, onCheckedChange = { checked = !checked })
}
@@ -249,19 +257,23 @@
ListItem(
text = { Text("عنصر قائمة مكون من سطرين مع رمز") },
overlineText = { Text("فوق الخط") },
- icon = { Image(
- icon40x40,
- colorFilter = ColorFilter.tint(AmbientContentColor.current)
- ) }
+ icon = {
+ Image(
+ icon40x40,
+ colorFilter = ColorFilter.tint(AmbientContentColor.current)
+ )
+ }
)
Divider()
ListItem(
text = { Text("Clickable two line item") },
secondaryText = { Text("Secondary text") },
- icon = { Image(
- icon40x40,
- colorFilter = ColorFilter.tint(AmbientContentColor.current)
- ) },
+ icon = {
+ Image(
+ icon40x40,
+ colorFilter = ColorFilter.tint(AmbientContentColor.current)
+ )
+ },
trailing = {
var checked by remember { mutableStateOf(false) }
Checkbox(checked, onCheckedChange = { checked = !checked })
@@ -272,10 +284,12 @@
ListItem(
text = { Text("بندان قابلان للنقر") },
secondaryText = { Text("نص ثانوي") },
- icon = { Image(
- icon40x40,
- colorFilter = ColorFilter.tint(AmbientContentColor.current)
- ) },
+ icon = {
+ Image(
+ icon40x40,
+ colorFilter = ColorFilter.tint(AmbientContentColor.current)
+ )
+ },
modifier = Modifier.clickable { }
)
Divider()
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SelectionControlsSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SelectionControlsSamples.kt
index 15f11cb..42c677c 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SelectionControlsSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SelectionControlsSamples.kt
@@ -64,14 +64,7 @@
TriStateCheckbox(
state = parentState,
onClick = onParentClick,
- boxColor = CheckboxConstants.animateDefaultBoxColor(
- state = parentState,
- enabled = true,
- checkedColor = MaterialTheme.colors.primary
- ),
- borderColor = CheckboxConstants.animateDefaultBorderColor(
- state = parentState,
- enabled = true,
+ colors = CheckboxConstants.defaultColors(
checkedColor = MaterialTheme.colors.primary
)
)
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt
index c21ecdd..a02eea2 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt
@@ -95,11 +95,13 @@
},
background = {
val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
- val color = animate(when (dismissState.targetValue) {
- Default -> Color.LightGray
- DismissedToEnd -> Color.Green
- DismissedToStart -> Color.Red
- })
+ val color = animate(
+ when (dismissState.targetValue) {
+ Default -> Color.LightGray
+ DismissedToEnd -> Color.Green
+ DismissedToStart -> Color.Red
+ }
+ )
val alignment = when (direction) {
StartToEnd -> Alignment.CenterStart
EndToStart -> Alignment.CenterEnd
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/AlertDialogTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/AlertDialogTest.kt
index 6a0183c..877db8e 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/AlertDialogTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/AlertDialogTest.kt
@@ -45,7 +45,7 @@
@Test
fun customStyleProperties_shouldApply() {
- var contentColor = Color.Unset
+ var contentColor = Color.Unspecified
rule.setContent {
AlertDialog(
onDismissRequest = {},
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt
index 688f806..f6975c7 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt
@@ -105,7 +105,7 @@
BottomSheetScaffold(
scaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState =
- rememberBottomSheetState(initialValue = BottomSheetValue.Expanded)
+ rememberBottomSheetState(initialValue = BottomSheetValue.Expanded)
),
sheetContent = {
Box(Modifier.fillMaxWidth().height(300.dp).testTag(sheetContent))
@@ -126,7 +126,7 @@
rule.setContent {
BottomSheetScaffold(
scaffoldState =
- rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState),
+ rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState),
sheetContent = {
Box(Modifier.fillMaxWidth().height(300.dp).testTag(sheetContent))
},
@@ -163,7 +163,7 @@
rule.setContent {
BottomSheetScaffold(
scaffoldState =
- rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState),
+ rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState),
sheetContent = {
Box(Modifier.fillMaxWidth().height(300.dp).testTag(sheetContent))
},
@@ -201,7 +201,7 @@
rule.setContent {
BottomSheetScaffold(
scaffoldState =
- rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState),
+ rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState),
sheetContent = {
Box(Modifier.fillMaxWidth().height(300.dp).testTag(sheetContent))
},
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MenuTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MenuTest.kt
index 657a889..b575083 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MenuTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MenuTest.kt
@@ -256,9 +256,9 @@
@Test
fun dropdownMenuItem_emphasis() {
- var onSurface = Color.Unset
- var enabledContentColor = Color.Unset
- var disabledContentColor = Color.Unset
+ var onSurface = Color.Unspecified
+ var enabledContentColor = Color.Unspecified
+ var disabledContentColor = Color.Unspecified
lateinit var enabledEmphasis: Emphasis
lateinit var disabledEmphasis: Emphasis
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldScreenshotTest.kt
index 965e693..0d16443 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldScreenshotTest.kt
@@ -658,11 +658,12 @@
val layoutDirection = if (rtl) LayoutDirection.Rtl else LayoutDirection.Ltr
Providers(LayoutDirectionAmbient provides layoutDirection) {
- Box(Modifier
- .fillMaxSize(0.5f)
- .wrapContentSize()
- .semantics(mergeAllDescendants = true) {}
- .testTag(Tag)
+ Box(
+ Modifier
+ .fillMaxSize(0.5f)
+ .wrapContentSize()
+ .semantics(mergeAllDescendants = true) {}
+ .testTag(Tag)
) {
Scaffold(
topBar = topAppBar,
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt
index f65ce73..9a8bba0 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt
@@ -16,7 +16,12 @@
package androidx.compose.material
-import androidx.compose.animation.animate
+import androidx.compose.animation.AnimatedValueModel
+import androidx.compose.animation.VectorConverter
+import androidx.compose.animation.asDisposableClock
+import androidx.compose.animation.core.AnimatedValue
+import androidx.compose.animation.core.AnimationClockObservable
+import androidx.compose.animation.core.AnimationVector4D
import androidx.compose.animation.core.FloatPropKey
import androidx.compose.animation.core.TransitionSpec
import androidx.compose.animation.core.keyframes
@@ -35,6 +40,7 @@
import androidx.compose.material.ripple.RippleIndication
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -48,6 +54,7 @@
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.platform.AnimationClockAmbient
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.lerp
@@ -69,13 +76,10 @@
* present on this Checkbox. You can create and pass in your own remembered
* [InteractionState] if you want to read the [InteractionState] and customize the appearance /
* behavior of this Checkbox in different [Interaction]s.
- * @param checkedColor color of the box of the Checkbox when [checked]. See
- * [TriStateCheckbox] to fully customize the color of the checkmark / box / border in different
- * states.
- * @param uncheckedColor color of the border of the Checkbox when not [checked]. See
- * [TriStateCheckbox] to fully customize the color of the checkmark / box / border in different
- * states.
+ * @param colors [CheckboxColors] that will be used to determine the color of the checkmark / box
+ * / border in different states. See [CheckboxConstants.defaultColors].
*/
+@OptIn(ExperimentalMaterialApi::class)
@Composable
fun Checkbox(
checked: Boolean,
@@ -83,25 +87,14 @@
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionState: InteractionState = remember { InteractionState() },
- checkedColor: Color = MaterialTheme.colors.secondary,
- uncheckedColor: Color = CheckboxConstants.defaultUncheckedColor
+ colors: CheckboxColors = CheckboxConstants.defaultColors()
) {
TriStateCheckbox(
state = ToggleableState(checked),
onClick = { onCheckedChange(!checked) },
interactionState = interactionState,
enabled = enabled,
- boxColor = CheckboxConstants.animateDefaultBoxColor(
- state = ToggleableState(checked),
- enabled = enabled,
- checkedColor = checkedColor
- ),
- borderColor = CheckboxConstants.animateDefaultBorderColor(
- state = ToggleableState(checked),
- enabled = enabled,
- checkedColor = checkedColor,
- uncheckedColor = uncheckedColor
- ),
+ colors = colors,
modifier = modifier
)
}
@@ -127,16 +120,10 @@
* present on this TriStateCheckbox. You can create and pass in your own remembered
* [InteractionState] if you want to read the [InteractionState] and customize the appearance /
* behavior of this TriStateCheckbox in different [Interaction]s.
- * @param checkMarkColor color of the check mark of the [TriStateCheckbox]. See
- * [CheckboxConstants.animateDefaultCheckmarkColor] for customizing the check mark color in
- * different [state]s.
- * @param boxColor background color of the box containing the checkmark. See
- * [CheckboxConstants.animateDefaultBoxColor] for customizing the box color in different [state]s,
- * such as when [ToggleableState.On] or not [enabled].
- * @param borderColor color of the border of the box containing the checkmark. See
- * [CheckboxConstants.animateDefaultBorderColor] for customizing the border color in different
- * [state]s, such as when [ToggleableState.On] or not [enabled].
+ * @param colors [CheckboxColors] that will be used to determine the color of the checkmark / box
+ * / border in different states. See [CheckboxConstants.defaultColors].
*/
+@OptIn(ExperimentalMaterialApi::class)
@Composable
fun TriStateCheckbox(
state: ToggleableState,
@@ -144,11 +131,10 @@
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionState: InteractionState = remember { InteractionState() },
- checkMarkColor: Color = CheckboxConstants.animateDefaultCheckmarkColor(state),
- boxColor: Color = CheckboxConstants.animateDefaultBoxColor(state, enabled),
- borderColor: Color = CheckboxConstants.animateDefaultBorderColor(state, enabled)
+ colors: CheckboxColors = CheckboxConstants.defaultColors()
) {
CheckboxImpl(
+ enabled = enabled,
value = state,
modifier = modifier
.triStateToggleable(
@@ -159,174 +145,116 @@
indication = RippleIndication(bounded = false, radius = CheckboxRippleRadius)
)
.padding(CheckboxDefaultPadding),
- checkColor = checkMarkColor,
- boxColor = boxColor,
- borderColor = borderColor
+ colors = colors
)
}
/**
+ * Represents the colors used by the three different sections (checkmark, box, and border) of a
+ * [Checkbox] or [TriStateCheckbox] in different states.
+ *
+ * See [CheckboxConstants.defaultColors] for the default implementation that follows Material
+ * specifications.
+ */
+@ExperimentalMaterialApi
+@Stable
+interface CheckboxColors {
+
+ /**
+ * Represents the color used for the checkmark inside the checkbox, depending on [state].
+ *
+ * @param state the [ToggleableState] of the checkbox
+ */
+ fun checkmarkColor(state: ToggleableState): Color
+
+ /**
+ * Represents the color used for the box (background) of the checkbox, depending on [enabled]
+ * and [state].
+ *
+ * @param enabled whether the checkbox is enabled or not
+ * @param state the [ToggleableState] of the checkbox
+ */
+ fun boxColor(enabled: Boolean, state: ToggleableState): Color
+
+ /**
+ * Represents the color used for the border of the checkbox, depending on [enabled] and [state].
+ *
+ * @param enabled whether the checkbox is enabled or not
+ * @param state the [ToggleableState] of the checkbox
+ */
+ fun borderColor(enabled: Boolean, state: ToggleableState): Color
+}
+
+/**
* Constants used in [Checkbox] and [TriStateCheckbox].
*/
object CheckboxConstants {
-
/**
- * Represents the default color used for the checkmark in a [Checkbox] or [TriStateCheckbox]
- * as it animates between states.
+ * Creates a [CheckboxColors] that will animate between the provided colors according to the
+ * Material specification.
*
- * @param state the [ToggleableState] of the checkbox
- * @param checkedColor the color to use for the checkmark when the Checkbox is
- * [ToggleableState.On].
- * @param uncheckedColor the color to use for the checkmark when the Checkbox is
- * [ToggleableState.Off] - this is typically transparent, as no checkmark should be displayed
- * in this state.
- * @return the [Color] representing the checkmark color
+ * @param checkedColor the color that will be used for the border and box when checked
+ * @param uncheckedColor color that will be used for the border when unchecked
+ * @param checkmarkColor color that will be used for the checkmark when checked
+ * @param disabledColor color that will be used for the box and border when disabled
+ * @param disabledIndeterminateColor color that will be used for the box and
+ * border in a [TriStateCheckbox] when disabled AND in an [ToggleableState.Indeterminate] state.
*/
+ @OptIn(ExperimentalMaterialApi::class)
@Composable
- fun animateDefaultCheckmarkColor(
- state: ToggleableState,
- checkedColor: Color = MaterialTheme.colors.surface,
- uncheckedColor: Color = checkedColor.copy(alpha = 0f)
- ): Color {
- val target = if (state == ToggleableState.Off) uncheckedColor else checkedColor
-
- val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
- return animate(target, tween(durationMillis = duration))
- }
-
- /**
- * Represents the default color used for the background of the box in a [Checkbox] or
- * [TriStateCheckbox] as it animates between states.
- *
- * @param state the [ToggleableState] of the checkbox
- * @param enabled whether the checkbox is enabled
- * @param checkedColor the color to use for the background of the box when the Checkbox is
- * [ToggleableState.On].
- * @param uncheckedColor the color to use for the background of the box when the Checkbox is
- * [ToggleableState.Off] - this is typically transparent.
- * @param disabledCheckedColor the color to use for the background of the box when the Checkbox is
- * [ToggleableState.On] and not [enabled].
- * @param disabledUncheckedColor the color to use for the background of the box when the
- * Checkbox is [ToggleableState.Off] and not [enabled].
- * @param disabledIndeterminateColor the color to use for the background of the box when the
- * Checkbox is [ToggleableState.Indeterminate] and not [enabled].
- * @return the [Color] representing the background color of the box
- */
- @Composable
- fun animateDefaultBoxColor(
- state: ToggleableState,
- enabled: Boolean,
+ fun defaultColors(
checkedColor: Color = MaterialTheme.colors.secondary,
- uncheckedColor: Color = checkedColor.copy(alpha = 0f),
- disabledCheckedColor: Color = defaultDisabledColor,
- disabledUncheckedColor: Color = Color.Transparent,
- disabledIndeterminateColor: Color = defaultDisabledIndeterminateColor(checkedColor)
- ): Color {
- val target = if (enabled) {
- when (state) {
- ToggleableState.On, ToggleableState.Indeterminate -> checkedColor
- ToggleableState.Off -> uncheckedColor
- }
- } else {
- when (state) {
- ToggleableState.On -> disabledCheckedColor
- ToggleableState.Indeterminate -> disabledIndeterminateColor
- ToggleableState.Off -> disabledUncheckedColor
- }
+ uncheckedColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f),
+ checkmarkColor: Color = MaterialTheme.colors.surface,
+ disabledColor: Color = AmbientEmphasisLevels.current.disabled.applyEmphasis(
+ MaterialTheme.colors.onSurface
+ ),
+ disabledIndeterminateColor: Color = AmbientEmphasisLevels.current.disabled.applyEmphasis(
+ checkedColor
+ )
+ ): CheckboxColors {
+ val clock = AnimationClockAmbient.current.asDisposableClock()
+ return remember(
+ checkedColor,
+ uncheckedColor,
+ checkmarkColor,
+ disabledColor,
+ disabledIndeterminateColor,
+ clock
+ ) {
+ DefaultCheckboxColors(
+ checkedBorderColor = checkedColor,
+ checkedBoxColor = checkedColor,
+ checkedCheckmarkColor = checkmarkColor,
+ uncheckedCheckmarkColor = checkmarkColor.copy(alpha = 0f),
+ uncheckedBoxColor = checkedColor.copy(alpha = 0f),
+ disabledCheckedBoxColor = disabledColor,
+ disabledUncheckedBoxColor = disabledColor.copy(alpha = 0f),
+ disabledIndeterminateBoxColor = disabledIndeterminateColor,
+ uncheckedBorderColor = uncheckedColor,
+ disabledBorderColor = disabledColor,
+ disabledIndeterminateBorderColor = disabledIndeterminateColor,
+ clock = clock
+ )
}
-
- // If not enabled 'snap' to the disabled state, as there should be no animations between
- // enabled / disabled.
- return if (enabled) {
- val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
- animate(target, tween(durationMillis = duration))
- } else {
- target
- }
- }
-
- /**
- * Represents the default color used for the border of the box in a [Checkbox] or
- * [TriStateCheckbox]s as it animates between states.
- *
- * @param state the [ToggleableState] of the checkbox
- * @param enabled whether the checkbox is enabled
- * @param checkedColor the color to use for the border of the box when the Checkbox is
- * [ToggleableState.On].
- * @param uncheckedColor the color to use for the border of the box when the Checkbox is
- * [ToggleableState.Off].
- * @param disabledColor the color to use for the border of the box when the Checkbox is
- * [ToggleableState.On] or [ToggleableState.Off], and not [enabled].
- * @param disabledIndeterminateColor the color to use for the border of the box when the
- * Checkbox is [ToggleableState.Indeterminate] and not [enabled].
- * @return the [Color] representing the border color of the box
- */
- @Composable
- fun animateDefaultBorderColor(
- state: ToggleableState,
- enabled: Boolean,
- checkedColor: Color = MaterialTheme.colors.secondary,
- uncheckedColor: Color = defaultUncheckedColor,
- disabledColor: Color = defaultDisabledColor,
- disabledIndeterminateColor: Color = defaultDisabledIndeterminateColor(checkedColor)
- ): Color {
- val target = if (enabled) {
- when (state) {
- ToggleableState.On, ToggleableState.Indeterminate -> checkedColor
- ToggleableState.Off -> uncheckedColor
- }
- } else {
- when (state) {
- ToggleableState.Indeterminate -> disabledIndeterminateColor
- ToggleableState.On, ToggleableState.Off -> disabledColor
- }
- }
-
- // If not enabled 'snap' to the disabled state, as there should be no animations between
- // enabled / disabled.
- return if (enabled) {
- val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
- animate(target, tween(durationMillis = duration))
- } else {
- target
- }
- }
-
- /**
- * Default color that will be used for a Checkbox when unchecked
- */
- @Composable
- val defaultUncheckedColor: Color
- get() = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
-
- /**
- * Default color that will be used for a Checkbox when disabled
- */
- @Composable
- val defaultDisabledColor: Color
- get() = AmbientEmphasisLevels.current.disabled.applyEmphasis(MaterialTheme.colors.onSurface)
-
- /**
- * Default color that will be used for [TriStateCheckbox] when disabled and in a
- * [ToggleableState.Indeterminate] state.
- */
- @Composable
- fun defaultDisabledIndeterminateColor(checkedColor: Color): Color {
- return AmbientEmphasisLevels.current.disabled.applyEmphasis(checkedColor)
}
}
+@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun CheckboxImpl(
+ enabled: Boolean,
value: ToggleableState,
modifier: Modifier,
- checkColor: Color,
- boxColor: Color,
- borderColor: Color
+ colors: CheckboxColors
) {
val state = transition(definition = TransitionDefinition, toState = value)
val checkCache = remember { CheckDrawingCache() }
Canvas(modifier.wrapContentSize(Alignment.Center).size(CheckboxSize)) {
+ val checkColor = colors.checkmarkColor(value)
+ val boxColor = colors.boxColor(enabled, value)
+ val borderColor = colors.borderColor(enabled, value)
+
val strokeWidthPx = StrokeWidth.toPx()
drawBox(
boxColor = boxColor,
@@ -413,6 +341,121 @@
val pathToDraw: Path = Path()
)
+/**
+ * Default [CheckboxColors] implementation.
+ */
+@OptIn(ExperimentalMaterialApi::class)
+@Stable
+private class DefaultCheckboxColors(
+ private val checkedCheckmarkColor: Color,
+ private val uncheckedCheckmarkColor: Color,
+ private val checkedBoxColor: Color,
+ private val uncheckedBoxColor: Color,
+ private val disabledCheckedBoxColor: Color,
+ private val disabledUncheckedBoxColor: Color,
+ private val disabledIndeterminateBoxColor: Color,
+ private val checkedBorderColor: Color,
+ private val uncheckedBorderColor: Color,
+ private val disabledBorderColor: Color,
+ private val disabledIndeterminateBorderColor: Color,
+ private val clock: AnimationClockObservable
+) : CheckboxColors {
+ private lateinit var animatedCheckmarkColor: AnimatedValue<Color, AnimationVector4D>
+ private lateinit var animatedBoxColor: AnimatedValue<Color, AnimationVector4D>
+ private lateinit var animatedBorderColor: AnimatedValue<Color, AnimationVector4D>
+
+ override fun checkmarkColor(state: ToggleableState): Color {
+ val target = if (state == ToggleableState.Off) {
+ uncheckedCheckmarkColor
+ } else {
+ checkedCheckmarkColor
+ }
+
+ if (!::animatedCheckmarkColor.isInitialized) {
+ animatedCheckmarkColor = AnimatedValueModel(
+ initialValue = target,
+ typeConverter = (Color.VectorConverter)(target.colorSpace),
+ clock = clock
+ )
+ }
+
+ if (animatedCheckmarkColor.targetValue != target) {
+ val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
+ animatedCheckmarkColor.animateTo(target, tween(durationMillis = duration))
+ }
+ return animatedCheckmarkColor.value
+ }
+
+ override fun boxColor(enabled: Boolean, state: ToggleableState): Color {
+ val target = if (enabled) {
+ when (state) {
+ ToggleableState.On, ToggleableState.Indeterminate -> checkedBoxColor
+ ToggleableState.Off -> uncheckedBoxColor
+ }
+ } else {
+ when (state) {
+ ToggleableState.On -> disabledCheckedBoxColor
+ ToggleableState.Indeterminate -> disabledIndeterminateBoxColor
+ ToggleableState.Off -> disabledUncheckedBoxColor
+ }
+ }
+
+ // If not enabled 'snap' to the disabled state, as there should be no animations between
+ // enabled / disabled.
+ return if (enabled) {
+ if (!::animatedBoxColor.isInitialized) {
+ animatedBoxColor = AnimatedValueModel(
+ initialValue = target,
+ typeConverter = (Color.VectorConverter)(target.colorSpace),
+ clock = clock
+ )
+ }
+
+ if (animatedBoxColor.targetValue != target) {
+ val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
+ animatedBoxColor.animateTo(target, tween(durationMillis = duration))
+ }
+ animatedBoxColor.value
+ } else {
+ target
+ }
+ }
+
+ override fun borderColor(enabled: Boolean, state: ToggleableState): Color {
+ val target = if (enabled) {
+ when (state) {
+ ToggleableState.On, ToggleableState.Indeterminate -> checkedBorderColor
+ ToggleableState.Off -> uncheckedBorderColor
+ }
+ } else {
+ when (state) {
+ ToggleableState.Indeterminate -> disabledIndeterminateBorderColor
+ ToggleableState.On, ToggleableState.Off -> disabledBorderColor
+ }
+ }
+
+ // If not enabled 'snap' to the disabled state, as there should be no animations between
+ // enabled / disabled.
+ return if (enabled) {
+ if (!::animatedBorderColor.isInitialized) {
+ animatedBorderColor = AnimatedValueModel(
+ initialValue = target,
+ typeConverter = (Color.VectorConverter)(target.colorSpace),
+ clock = clock
+ )
+ }
+
+ if (animatedBorderColor.targetValue != target) {
+ val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
+ animatedBorderColor.animateTo(target, tween(durationMillis = duration))
+ }
+ animatedBorderColor.value
+ } else {
+ target
+ }
+ }
+}
+
// all float props are fraction now [0f .. 1f] as it seems convenient
private val CheckDrawFraction = FloatPropKey()
private val CheckCenterGravitationShiftFraction = FloatPropKey()
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Colors.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Colors.kt
index ba00d70..60aaf6a 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Colors.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Colors.kt
@@ -235,7 +235,7 @@
* [Colors.onPrimary]. If [color] is not present in the theme, this will return `null`.
*
* @return the matching `on` color for [color]. If [color] is not part of the theme's
- * [Colors], then returns [Color.Unset].
+ * [Colors], then returns [Color.Unspecified].
*
* @see contentColorFor
*/
@@ -248,7 +248,7 @@
background -> onBackground
surface -> onSurface
error -> onError
- else -> Color.Unset
+ else -> Color.Unspecified
}
}
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
index 3d3ea10..7fa60f0 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
@@ -171,7 +171,7 @@
activeColor = activeColor,
inactiveColor = inactiveColor,
errorColor = errorColor,
- backgroundColor = Color.Unset,
+ backgroundColor = Color.Unspecified,
shape = RectangleShape
)
}
@@ -274,7 +274,7 @@
activeColor = activeColor,
inactiveColor = inactiveColor,
errorColor = errorColor,
- backgroundColor = Color.Unset,
+ backgroundColor = Color.Unspecified,
shape = RectangleShape
)
}
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/RadioButton.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/RadioButton.kt
index f0b2bad..9df18d7 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/RadioButton.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/RadioButton.kt
@@ -16,7 +16,13 @@
package androidx.compose.material
+import androidx.compose.animation.AnimatedValueModel
+import androidx.compose.animation.VectorConverter
import androidx.compose.animation.animate
+import androidx.compose.animation.asDisposableClock
+import androidx.compose.animation.core.AnimatedValue
+import androidx.compose.animation.core.AnimationClockObservable
+import androidx.compose.animation.core.AnimationVector4D
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Interaction
@@ -30,6 +36,7 @@
import androidx.compose.foundation.selection.selectable
import androidx.compose.material.ripple.RippleIndication
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -37,6 +44,7 @@
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.platform.AnimationClockAmbient
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@@ -59,10 +67,10 @@
* present on this RadioButton. You can create and pass in your own remembered
* [InteractionState] if you want to read the [InteractionState] and customize the appearance /
* behavior of this RadioButton in different [Interaction]s.
- * @param color color of the RadioButton. See [RadioButtonConstants.animateDefaultColor] for
- * customizing the color of the RadioButton in one / multiple states, such as when [selected] or
- * not [enabled].
+ * @param colors [RadioButtonColors] that will be used to resolve the color used for this
+ * RadioButton in different states. See [RadioButtonConstants.defaultColors].
*/
+@OptIn(ExperimentalMaterialApi::class)
@Composable
fun RadioButton(
selected: Boolean,
@@ -70,7 +78,7 @@
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionState: InteractionState = remember { InteractionState() },
- color: Color = RadioButtonConstants.animateDefaultColor(selected, enabled)
+ colors: RadioButtonColors = RadioButtonConstants.defaultColors()
) {
val dotRadius = animate(
target = if (selected) RadioButtonDotSize / 2 else 0.dp,
@@ -89,32 +97,86 @@
.padding(RadioButtonPadding)
.size(RadioButtonSize)
) {
- drawRadio(color, dotRadius)
+ val radioColor = colors.radioColor(enabled, selected)
+ drawRadio(radioColor, dotRadius)
}
}
/**
+ * Represents the color used by a [RadioButton] in different states.
+ *
+ * See [RadioButtonConstants.defaultColors] for the default implementation that follows Material
+ * specifications.
+ */
+@ExperimentalMaterialApi
+@Stable
+interface RadioButtonColors {
+ /**
+ * Represents the main color used to draw the outer and inner circles, depending on whether
+ * the [RadioButton] is [enabled] / [selected].
+ *
+ * @param enabled whether the [RadioButton] is enabled
+ * @param selected whether the [RadioButton] is selected
+ */
+ fun radioColor(enabled: Boolean, selected: Boolean): Color
+}
+
+/**
* Constants used in [RadioButton].
*/
object RadioButtonConstants {
/**
- * Represents the default color used for a [RadioButton] as it animates between states.
+ * Creates a [RadioButtonColors] that will animate between the provided colors according to
+ * the Material specification.
*
- * @param selected whether the RadioButton is selected
- * @param enabled whether the RadioButton is enabled
* @param selectedColor the color to use for the RadioButton when selected and enabled.
* @param unselectedColor the color to use for the RadioButton when unselected and enabled.
* @param disabledColor the color to use for the RadioButton when disabled.
* @return the resulting [Color] used for the RadioButton
*/
+ @OptIn(ExperimentalMaterialApi::class)
@Composable
- fun animateDefaultColor(
- selected: Boolean,
- enabled: Boolean,
+ fun defaultColors(
selectedColor: Color = MaterialTheme.colors.secondary,
- unselectedColor: Color = defaultUnselectedColor,
- disabledColor: Color = defaultDisabledColor
- ): Color {
+ unselectedColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f),
+ disabledColor: Color = AmbientEmphasisLevels.current.disabled.applyEmphasis(
+ MaterialTheme.colors.onSurface
+ )
+ ): RadioButtonColors {
+ val clock = AnimationClockAmbient.current.asDisposableClock()
+ return remember(
+ selectedColor,
+ unselectedColor,
+ disabledColor,
+ clock
+ ) {
+ DefaultRadioButtonColors(selectedColor, unselectedColor, disabledColor, clock)
+ }
+ }
+}
+
+private fun DrawScope.drawRadio(color: Color, dotRadius: Dp) {
+ val strokeWidth = RadioStrokeWidth.toPx()
+ drawCircle(color, RadioRadius.toPx() - strokeWidth / 2, style = Stroke(strokeWidth))
+ if (dotRadius > 0.dp) {
+ drawCircle(color, dotRadius.toPx() - strokeWidth / 2, style = Fill)
+ }
+}
+
+/**
+ * Default [RadioButtonColors] implementation.
+ */
+@OptIn(ExperimentalMaterialApi::class)
+@Stable
+private class DefaultRadioButtonColors(
+ private val selectedColor: Color,
+ private val unselectedColor: Color,
+ private val disabledColor: Color,
+ private val clock: AnimationClockObservable
+) : RadioButtonColors {
+ private lateinit var animatedColor: AnimatedValue<Color, AnimationVector4D>
+
+ override fun radioColor(enabled: Boolean, selected: Boolean): Color {
val target = when {
!enabled -> disabledColor
!selected -> unselectedColor
@@ -124,33 +186,22 @@
// If not enabled 'snap' to the disabled state, as there should be no animations between
// enabled / disabled.
return if (enabled) {
- animate(target, tween(durationMillis = RadioAnimationDuration))
+ if (!::animatedColor.isInitialized) {
+ animatedColor = AnimatedValueModel(
+ initialValue = target,
+ typeConverter = (Color.VectorConverter)(target.colorSpace),
+ clock = clock
+ )
+ }
+
+ if (animatedColor.targetValue != target) {
+ animatedColor.animateTo(target, tween(durationMillis = RadioAnimationDuration))
+ }
+ animatedColor.value
} else {
target
}
}
-
- /**
- * Default color that will be used for a RadioButton when unselected
- */
- @Composable
- val defaultUnselectedColor: Color
- get() = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
-
- /**
- * Default color that will be used for a RadioButton when disabled
- */
- @Composable
- val defaultDisabledColor: Color
- get() = AmbientEmphasisLevels.current.disabled.applyEmphasis(MaterialTheme.colors.onSurface)
-}
-
-private fun DrawScope.drawRadio(color: Color, dotRadius: Dp) {
- val strokeWidth = RadioStrokeWidth.toPx()
- drawCircle(color, RadioRadius.toPx() - strokeWidth / 2, style = Stroke(strokeWidth))
- if (dotRadius > 0.dp) {
- drawCircle(color, dotRadius.toPx() - strokeWidth / 2, style = Fill)
- }
}
private const val RadioAnimationDuration = 100
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Swipeable.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Swipeable.kt
index f885634..dfc980f 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Swipeable.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Swipeable.kt
@@ -442,13 +442,15 @@
"You cannot have two anchors mapped to the same state."
}
val density = DensityAmbient.current
- onCommit {
+ onCommit(anchors) {
state.anchors = anchors
state.thresholds = { a, b ->
val from = anchors.getValue(a)
val to = anchors.getValue(b)
with(thresholds(from, to)) { density.computeThreshold(a, b) }
}
+ }
+ onCommit {
state.resistance = resistance
}
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ripple/RippleIndication.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ripple/RippleIndication.kt
index 4ab86c04..1b93d43 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ripple/RippleIndication.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ripple/RippleIndication.kt
@@ -67,7 +67,7 @@
* @param radius Effects grow up to this size. If null is provided the size would be calculated
* based on the target layout size.
* @param color The Ripple color is usually the same color used by the text or iconography in the
- * component. If [Color.Unset] is provided the color will be calculated by
+ * component. If [Color.Unspecified] is provided the color will be calculated by
* [RippleTheme.defaultColor]. This color will then have [RippleTheme.rippleOpacity] applied
*/
@Composable
@@ -75,7 +75,7 @@
fun RippleIndication(
bounded: Boolean = true,
radius: Dp? = null,
- color: Color = Color.Unset
+ color: Color = Color.Unspecified
): RippleIndication {
val theme = AmbientRippleTheme.current
val clock = AnimationClockAmbient.current.asDisposableClock()
diff --git a/compose/navigation/navigation/build.gradle b/compose/navigation/navigation/build.gradle
index 63b6598..8d20095 100644
--- a/compose/navigation/navigation/build.gradle
+++ b/compose/navigation/navigation/build.gradle
@@ -46,7 +46,7 @@
androidx {
name = "Compose Navigation"
- publish = Publish.SNAPSHOT_ONLY
+ publish = Publish.SNAPSHOT_AND_RELEASE
mavenVersion = LibraryVersions.COMPOSE_NAVIGATION
mavenGroup = LibraryGroups.Compose.NAVIGATION
inceptionYear = "2020"
diff --git a/compose/paging/paging/integration-tests/paging-demos/src/main/java/androidx/compose/paging/demos/PagingDemos.kt b/compose/paging/paging/integration-tests/paging-demos/src/main/java/androidx/compose/paging/demos/PagingDemos.kt
index dafa309..ef09328 100644
--- a/compose/paging/paging/integration-tests/paging-demos/src/main/java/androidx/compose/paging/demos/PagingDemos.kt
+++ b/compose/paging/paging/integration-tests/paging-demos/src/main/java/androidx/compose/paging/demos/PagingDemos.kt
@@ -21,7 +21,10 @@
import androidx.compose.paging.samples.PagingBackendSample
import androidx.compose.paging.demos.room.PagingRoomDemo
-val PagingDemos = DemoCategory("Paging", listOf(
- ComposableDemo("Paging Backend Demo") { PagingBackendSample() },
- ComposableDemo("Paging Room Demo") { PagingRoomDemo() }
-))
+val PagingDemos = DemoCategory(
+ "Paging",
+ listOf(
+ ComposableDemo("Paging Backend Demo") { PagingBackendSample() },
+ ComposableDemo("Paging Room Demo") { PagingRoomDemo() }
+ )
+)
diff --git a/compose/paging/paging/integration-tests/paging-demos/src/main/java/androidx/compose/paging/demos/room/PagingRoomSample.kt b/compose/paging/paging/integration-tests/paging-demos/src/main/java/androidx/compose/paging/demos/room/PagingRoomSample.kt
index cd46ad8..fbde1ad 100644
--- a/compose/paging/paging/integration-tests/paging-demos/src/main/java/androidx/compose/paging/demos/room/PagingRoomSample.kt
+++ b/compose/paging/paging/integration-tests/paging-demos/src/main/java/androidx/compose/paging/demos/room/PagingRoomSample.kt
@@ -55,46 +55,54 @@
}
Column {
- Button(onClick = {
- scope.launch(Dispatchers.IO) {
- val name = Names[Random.nextInt(Names.size)]
- dao.insert(User(id = 0, name = name))
+ Button(
+ onClick = {
+ scope.launch(Dispatchers.IO) {
+ val name = Names[Random.nextInt(Names.size)]
+ dao.insert(User(id = 0, name = name))
+ }
}
- }) {
+ ) {
Text("Add random user")
}
- Button(onClick = {
- scope.launch(Dispatchers.IO) {
- dao.clearAll()
+ Button(
+ onClick = {
+ scope.launch(Dispatchers.IO) {
+ dao.clearAll()
+ }
}
- }) {
+ ) {
Text("Clear all users")
}
- Button(onClick = {
- scope.launch(Dispatchers.IO) {
- val randomUser = dao.getRandomUser()
- if (randomUser != null) {
- dao.delete(randomUser)
+ Button(
+ onClick = {
+ scope.launch(Dispatchers.IO) {
+ val randomUser = dao.getRandomUser()
+ if (randomUser != null) {
+ dao.delete(randomUser)
+ }
}
}
- }) {
+ ) {
Text("Remove random user")
}
- Button(onClick = {
- scope.launch(Dispatchers.IO) {
- val randomUser = dao.getRandomUser()
- if (randomUser != null) {
- val updatedUser = User(
- randomUser.id,
- randomUser.name + " updated"
- )
- dao.update(updatedUser)
+ Button(
+ onClick = {
+ scope.launch(Dispatchers.IO) {
+ val randomUser = dao.getRandomUser()
+ if (randomUser != null) {
+ val updatedUser = User(
+ randomUser.id,
+ randomUser.name + " updated"
+ )
+ dao.update(updatedUser)
+ }
}
}
- }) {
+ ) {
Text("Update random user")
}
diff --git a/compose/paging/paging/samples/src/main/java/androidx/compose/paging/samples/PagingSample.kt b/compose/paging/paging/samples/src/main/java/androidx/compose/paging/samples/PagingSample.kt
index de1e25f..74dc658 100644
--- a/compose/paging/paging/samples/src/main/java/androidx/compose/paging/samples/PagingSample.kt
+++ b/compose/paging/paging/samples/src/main/java/androidx/compose/paging/samples/PagingSample.kt
@@ -100,13 +100,14 @@
fun PagingBackendSample() {
val myBackend = remember { MyBackend() }
- val pager = remember { Pager(
- PagingConfig(
- pageSize = myBackend.DataBatchSize,
- enablePlaceholders = true,
- maxSize = 200
- )
- ) { myBackend.getAllData() }
+ val pager = remember {
+ Pager(
+ PagingConfig(
+ pageSize = myBackend.DataBatchSize,
+ enablePlaceholders = true,
+ maxSize = 200
+ )
+ ) { myBackend.getAllData() }
}
val lazyPagingItems = pager.flow.collectAsLazyPagingItems()
@@ -128,8 +129,10 @@
if (lazyPagingItems.loadState.append == LoadState.Loading) {
item {
- CircularProgressIndicator(modifier = Modifier.fillMaxWidth()
- .wrapContentWidth(Alignment.CenterHorizontally))
+ CircularProgressIndicator(
+ modifier = Modifier.fillMaxWidth()
+ .wrapContentWidth(Alignment.CenterHorizontally)
+ )
}
}
}
diff --git a/compose/paging/paging/src/androidTest/java/androidx/compose/paging/LazyPagingItemsTest.kt b/compose/paging/paging/src/androidTest/java/androidx/compose/paging/LazyPagingItemsTest.kt
index 65443e8..6a6faaf 100644
--- a/compose/paging/paging/src/androidTest/java/androidx/compose/paging/LazyPagingItemsTest.kt
+++ b/compose/paging/paging/src/androidTest/java/androidx/compose/paging/LazyPagingItemsTest.kt
@@ -81,8 +81,10 @@
val lazyPagingItems = pager.flow.collectAsLazyPagingItems()
LazyColumn(Modifier.preferredHeight(200.dp)) {
items(lazyPagingItems) {
- Spacer(Modifier.preferredHeight(101.dp).fillParentMaxWidth()
- .testTag("$it"))
+ Spacer(
+ Modifier.preferredHeight(101.dp).fillParentMaxWidth()
+ .testTag("$it")
+ )
}
}
}
@@ -108,8 +110,10 @@
val lazyPagingItems = pager.flow.collectAsLazyPagingItems()
LazyColumn(Modifier.preferredHeight(200.dp)) {
itemsIndexed(lazyPagingItems) { index, item ->
- Spacer(Modifier.preferredHeight(101.dp).fillParentMaxWidth()
- .testTag("$index-$item"))
+ Spacer(
+ Modifier.preferredHeight(101.dp).fillParentMaxWidth()
+ .testTag("$index-$item")
+ )
}
}
}
@@ -135,8 +139,10 @@
val lazyPagingItems = pager.flow.collectAsLazyPagingItems()
LazyRow(Modifier.preferredWidth(200.dp)) {
items(lazyPagingItems) {
- Spacer(Modifier.preferredWidth(101.dp).fillParentMaxHeight()
- .testTag("$it"))
+ Spacer(
+ Modifier.preferredWidth(101.dp).fillParentMaxHeight()
+ .testTag("$it")
+ )
}
}
}
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index d829491..58642cf 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -378,6 +378,10 @@
method public void updateScope(kotlin.jvm.functions.Function2<? super androidx.compose.runtime.Composer<?>,? super java.lang.Integer,kotlin.Unit> block);
}
+ public final class SideEffectKt {
+ method @androidx.compose.runtime.Composable @androidx.compose.runtime.ComposableContract(restartable=false) public static void SideEffect(kotlin.jvm.functions.Function0<kotlin.Unit> effect);
+ }
+
public final class SkippableUpdater<T> {
ctor public SkippableUpdater(androidx.compose.runtime.Composer<?> composer, T? node);
method public androidx.compose.runtime.Composer<?> getComposer();
diff --git a/compose/runtime/runtime/api/public_plus_experimental_current.txt b/compose/runtime/runtime/api/public_plus_experimental_current.txt
index d829491..58642cf 100644
--- a/compose/runtime/runtime/api/public_plus_experimental_current.txt
+++ b/compose/runtime/runtime/api/public_plus_experimental_current.txt
@@ -378,6 +378,10 @@
method public void updateScope(kotlin.jvm.functions.Function2<? super androidx.compose.runtime.Composer<?>,? super java.lang.Integer,kotlin.Unit> block);
}
+ public final class SideEffectKt {
+ method @androidx.compose.runtime.Composable @androidx.compose.runtime.ComposableContract(restartable=false) public static void SideEffect(kotlin.jvm.functions.Function0<kotlin.Unit> effect);
+ }
+
public final class SkippableUpdater<T> {
ctor public SkippableUpdater(androidx.compose.runtime.Composer<?> composer, T? node);
method public androidx.compose.runtime.Composer<?> getComposer();
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index f8a7854..ed75330 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -404,6 +404,10 @@
method public void updateScope(kotlin.jvm.functions.Function2<? super androidx.compose.runtime.Composer<?>,? super java.lang.Integer,kotlin.Unit> block);
}
+ public final class SideEffectKt {
+ method @androidx.compose.runtime.Composable @androidx.compose.runtime.ComposableContract(restartable=false) public static void SideEffect(kotlin.jvm.functions.Function0<kotlin.Unit> effect);
+ }
+
public final class SkippableUpdater<T> {
ctor public SkippableUpdater(androidx.compose.runtime.Composer<?> composer, T? node);
method public androidx.compose.runtime.Composer<?> getComposer();
diff --git a/compose/runtime/runtime/src/androidAndroidTest/kotlin/androidx/compose/runtime/SideEffectTests.kt b/compose/runtime/runtime/src/androidAndroidTest/kotlin/androidx/compose/runtime/SideEffectTests.kt
new file mode 100644
index 0000000..5af62b4
--- /dev/null
+++ b/compose/runtime/runtime/src/androidAndroidTest/kotlin/androidx/compose/runtime/SideEffectTests.kt
@@ -0,0 +1,101 @@
+/*
+ * 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.compose.runtime
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+@Suppress("UNUSED_VARIABLE")
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class SideEffectTests : BaseComposeTest() {
+
+ @get:Rule
+ override val activityRule = makeTestActivityRule()
+
+ /**
+ * Test that side effects run in order of appearance each time the composable
+ * is recomposed.
+ */
+ @Test
+ fun testSideEffectsRunInOrder() {
+ val results = mutableListOf<Int>()
+ var resultsAtComposition: List<Int>? = null
+ var recompose: (() -> Unit)? = null
+ compose {
+ SideEffect {
+ results += 1
+ }
+ SideEffect {
+ results += 2
+ }
+ resultsAtComposition = results.toList()
+ recompose = invalidate
+ }.then {
+ assertEquals(listOf(1, 2), results, "side effects were applied")
+ assertEquals(
+ emptyList(), resultsAtComposition,
+ "side effects weren't applied until after composition"
+ )
+ recompose?.invoke() ?: error("missing recompose function")
+ }.then {
+ assertEquals(listOf(1, 2, 1, 2), results, "side effects applied a second time")
+ }
+ }
+
+ /**
+ * Test that side effects run after lifecycle observers enter the composition,
+ * even if their remembrance happens after the SideEffect call appears.
+ */
+ @Test
+ fun testSideEffectsRunAfterLifecycleObservers() {
+ class MyObserver : CompositionLifecycleObserver {
+ var isPresent: Boolean = false
+ private set
+
+ override fun onEnter() {
+ isPresent = true
+ }
+
+ override fun onLeave() {
+ isPresent = false
+ }
+ }
+
+ val myObserverOne = MyObserver()
+ val myObserverTwo = MyObserver()
+ var wasObserverOnePresent = false
+ var wasObserverTwoPresent = false
+
+ compose {
+ val one = remember { myObserverOne }
+ SideEffect {
+ wasObserverOnePresent = myObserverOne.isPresent
+ wasObserverTwoPresent = myObserverTwo.isPresent
+ }
+ val two = remember { myObserverTwo }
+ }.then {
+ assertTrue(wasObserverOnePresent, "observer one present for side effect")
+ assertTrue(wasObserverTwoPresent, "observer two present for side effect")
+ }
+ }
+}
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Applier.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Applier.kt
index dc44b78..f4f21a7 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Applier.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Applier.kt
@@ -102,6 +102,7 @@
}
override fun up() {
+ check(stack.isNotEmpty())
current = stack.removeAt(stack.size - 1)
}
@@ -125,16 +126,22 @@
}
protected fun MutableList<T>.move(from: Int, to: Int, count: Int) {
+ val dest = if (from > to) to else to - count
if (count == 1) {
- val fromEl = get(from)
- val toEl = set(to, fromEl)
- set(from, toEl)
+ if (from == to + 1 || from == to - 1) {
+ // Adjacent elements, perform swap to avoid backing array manipulations.
+ val fromEl = get(from)
+ val toEl = set(to, fromEl)
+ set(from, toEl)
+ } else {
+ val fromEl = removeAt(from)
+ insert(dest, fromEl)
+ }
} else {
val subView = subList(from, from + count)
val subCopy = subView.toMutableList()
- val dest = if (from > to) to else (to - count)
subView.clear()
addAll(dest, subCopy)
}
}
-}
\ No newline at end of file
+}
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ComposeVersion.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ComposeVersion.kt
index 89cc0bb..8d5ac09 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ComposeVersion.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ComposeVersion.kt
@@ -28,5 +28,5 @@
* IMPORTANT: Whenever updating this value, please make sure to also update `versionTable` and
* `minimumRuntimeVersionInt` in `VersionChecker.kt` of the compiler.
*/
- const val version: Int = 1600
+ const val version: Int = 1700
}
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
index 2fe553a..01402b1 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
@@ -51,6 +51,7 @@
internal interface LifecycleManager {
fun entering(instance: CompositionLifecycleObserver)
fun leaving(instance: CompositionLifecycleObserver)
+ fun sideEffect(effect: () -> Unit)
}
/**
@@ -656,6 +657,7 @@
) : LifecycleManager {
private val enters = mutableSetOf<CompositionLifecycleObserverHolder>()
private val leaves = mutableSetOf<CompositionLifecycleObserverHolder>()
+ private val sideEffects = mutableListOf<() -> Unit>()
override fun entering(instance: CompositionLifecycleObserver) {
val holder = CompositionLifecycleObserverHolder(instance)
@@ -676,6 +678,10 @@
if (left != null) lifecycleObservers.remove(left)
}
+ override fun sideEffect(effect: () -> Unit) {
+ sideEffects += effect
+ }
+
fun dispatchLifecycleObservers() {
trace("Compose:lifecycles") {
// Send lifecycle leaves
@@ -699,6 +705,17 @@
}
}
}
+
+ fun dispatchSideEffects() {
+ trace("Compose:sideEffects") {
+ if (sideEffects.isNotEmpty()) {
+ for (sideEffect in sideEffects) {
+ sideEffect()
+ }
+ sideEffects.clear()
+ }
+ }
+ }
}
/**
@@ -725,7 +742,11 @@
invalidation.location = slotTable.anchorLocation(anchor)
}
+ // Side effects run after lifecycle observers so that any remembered objects
+ // that implement CompositionLifecycleObserver receive onEnter before a side effect
+ // that captured it and operates on it can run.
manager.dispatchLifecycleObservers()
+ manager.dispatchSideEffects()
if (pendingInvalidScopes) {
pendingInvalidScopes = false
@@ -1042,6 +1063,13 @@
}
/**
+ * Schedule a side effect to run when we apply composition changes.
+ */
+ internal fun recordSideEffect(effect: () -> Unit) {
+ record { _, _, lifecycleManager -> lifecycleManager.sideEffect(effect) }
+ }
+
+ /**
* Return the current ambient scope which was provided by a parent group.
*/
private fun currentAmbientScope(): AmbientMap {
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/DerivedState.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/DerivedState.kt
index 41c1eed..865f4c1 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/DerivedState.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/DerivedState.kt
@@ -64,9 +64,12 @@
return readable.result as T
}
val newDependencies = HashSet<StateObject>()
- val result = Snapshot.observe({
- if (it is StateObject) newDependencies.add(it)
- }, null, calculation)
+ val result = Snapshot.observe(
+ {
+ if (it is StateObject) newDependencies.add(it)
+ },
+ null, calculation
+ )
sync {
val writable = first.newWritableRecord(this, snapshot)
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SideEffect.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SideEffect.kt
new file mode 100644
index 0000000..2398966
--- /dev/null
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SideEffect.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.compose.runtime
+
+/**
+ * Schedule [effect] to run when the current composition completes successfully and applies
+ * changes. [SideEffect] can be used to apply side effects to objects managed by the
+ * composition that are not backed by [snapshots][androidx.compose.runtime.snapshots.Snapshot] so
+ * as not to leave those objects in an inconsistent state if the current composition operation
+ * fails.
+ *
+ * [effect] will always be run on the composition's apply dispatcher and appliers are never run
+ * concurrent with themselves, one another, applying changes to the composition tree, or running
+ * [CompositionLifecycleObserver] event callbacks. [SideEffect]s are always run after
+ * [CompositionLifecycleObserver] event callbacks.
+ */
+@Composable
+@ComposableContract(restartable = false)
+fun SideEffect(
+ effect: () -> Unit
+) {
+ currentComposer.recordSideEffect(effect)
+}
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SuspendingEffects.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SuspendingEffects.kt
index ec9cc93..cd99e06 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SuspendingEffects.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SuspendingEffects.kt
@@ -308,8 +308,10 @@
override fun onEnter() {
job?.cancel("Old job was still running!")
- val scope = CoroutineScope(recomposer.applyingCoroutineContext
- ?: error("cannot launch LaunchedTask - Recomposer is not running"))
+ val scope = CoroutineScope(
+ recomposer.applyingCoroutineContext
+ ?: error("cannot launch LaunchedTask - Recomposer is not running")
+ )
job = scope.launch(block = task)
}
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityScopeMap.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityScopeMap.kt
index 57a02fe..6c8ec16 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityScopeMap.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityScopeMap.kt
@@ -109,7 +109,8 @@
val valueIndex = valueOrder[size]
values[valueIndex] = value
val scopeSet = scopeSets[valueIndex] ?: IdentityArraySet<T>().also {
- scopeSets[valueIndex] = it }
+ scopeSets[valueIndex] = it
+ }
// insert into the right location in keyOrder
if (insertIndex < size) {
diff --git a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/ActualDesktop.kt b/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/ActualDesktop.kt
index d076421..84b217f 100644
--- a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/ActualDesktop.kt
+++ b/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/ActualDesktop.kt
@@ -22,9 +22,6 @@
import javax.swing.SwingUtilities
import kotlin.coroutines.CoroutineContext
-// API to allow override embedding context creation mechanism for tests.
-var EmbeddingContextFactory: (() -> EmbeddingContext)? = null
-
class SwingEmbeddingContext : EmbeddingContext {
override fun isMainThread(): Boolean {
return SwingUtilities.isEventDispatchThread()
@@ -35,8 +32,7 @@
}
}
-actual fun EmbeddingContext(): EmbeddingContext =
- EmbeddingContextFactory?.let { it() } ?: SwingEmbeddingContext()
+actual fun EmbeddingContext(): EmbeddingContext = SwingEmbeddingContext()
internal actual object Trace {
actual fun beginSection(name: String): Any? {
diff --git a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/AbstractApplierTest.kt b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/AbstractApplierTest.kt
new file mode 100644
index 0000000..e80dbdb
--- /dev/null
+++ b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/AbstractApplierTest.kt
@@ -0,0 +1,213 @@
+/*
+ * 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.compose.runtime
+
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertSame
+import kotlin.test.fail
+
+class AbstractApplierTest {
+ private val root = Node("Root")
+ private val applier = NodeApplier(root)
+
+ @Test fun upFromRootThrows() {
+ try {
+ applier.up()
+ fail()
+ } catch (_: IllegalStateException) {
+ }
+ }
+
+ @Test fun downGoesDown() {
+ val one = Node("one")
+ applier.insert(0, one)
+ applier.down(one)
+ assertSame(one, applier.current)
+
+ val two = Node("two")
+ applier.insert(0, two)
+ applier.down(two)
+ assertSame(two, applier.current)
+ }
+
+ @Test fun upGoesUp() {
+ val one = Node("one")
+ applier.insert(0, one)
+ applier.down(one)
+ val two = Node("two")
+ applier.insert(0, two)
+ applier.down(two)
+
+ applier.up()
+ assertSame(one, applier.current)
+ applier.up()
+ assertSame(root, applier.current)
+ }
+
+ @Test fun clearClearsAndPointsToRoot() {
+ val child = Node("child")
+ applier.insert(0, child)
+ applier.down(child)
+
+ applier.clear()
+ assertSame(root, applier.current)
+ assertEquals(emptyList<Node>(), root.children)
+ }
+
+ @Test fun removeSingle() {
+ // Note: NodeApplier delegates to AbstractApplier's MutableList.remove
+ // helper which is what is being tested here.
+ val one = Node("one")
+ val two = Node("two")
+ val three = Node("three")
+ val four = Node("four")
+ applier.insert(0, one)
+ applier.insert(1, two)
+ applier.insert(2, three)
+ applier.insert(3, four)
+
+ applier.remove(1, 1) // Middle
+ assertEquals(listOf(one, three, four), root.children)
+ applier.remove(2, 1) // End
+ assertEquals(listOf(one, three), root.children)
+ applier.remove(0, 1) // Start
+ assertEquals(listOf(three), root.children)
+ }
+
+ @Test fun removeMultiple() {
+ // Note: NodeApplier delegates to AbstractApplier's MutableList.remove
+ // helper which is what is being tested here.
+ val one = Node("one")
+ val two = Node("two")
+ val three = Node("three")
+ val four = Node("four")
+ val five = Node("five")
+ val six = Node("six")
+ val seven = Node("seven")
+ applier.insert(0, one)
+ applier.insert(1, two)
+ applier.insert(2, three)
+ applier.insert(3, four)
+ applier.insert(4, five)
+ applier.insert(5, six)
+ applier.insert(6, seven)
+
+ applier.remove(2, 2) // Middle
+ assertEquals(listOf(one, two, five, six, seven), root.children)
+ applier.remove(3, 2) // End
+ assertEquals(listOf(one, two, five), root.children)
+ applier.remove(0, 2) // Start
+ assertEquals(listOf(five), root.children)
+ }
+
+ @Test fun moveSingleHigher() {
+ // Note: NodeApplier delegates to AbstractApplier's MutableList.move
+ // helper which is what is being tested here.
+ val one = Node("one")
+ val two = Node("two")
+ val three = Node("three")
+ applier.insert(0, one)
+ applier.insert(1, two)
+ applier.insert(2, three)
+
+ applier.move(0, 3, 1)
+ assertEquals(listOf(two, three, one), root.children)
+
+ // Do adjacent moves as this is currently specialized to do a swap.
+ applier.move(0, 1, 1)
+ assertEquals(listOf(three, two, one), root.children)
+ applier.move(1, 2, 1)
+ assertEquals(listOf(three, one, two), root.children)
+ }
+
+ @Test fun moveSingleLower() {
+ // Note: NodeApplier delegates to AbstractApplier's MutableList.move
+ // helper which is what is being tested here.
+ val one = Node("one")
+ val two = Node("two")
+ val three = Node("three")
+ applier.insert(0, one)
+ applier.insert(1, two)
+ applier.insert(2, three)
+
+ applier.move(2, 0, 1)
+ assertEquals(listOf(three, one, two), root.children)
+
+ // Do adjacent moves as this is currently specialized to do a swap.
+ applier.move(1, 2, 1)
+ assertEquals(listOf(three, two, one), root.children)
+ applier.move(0, 1, 1)
+ assertEquals(listOf(two, three, one), root.children)
+ }
+
+ @Test fun moveMultipleHigher() {
+ // Note: NodeApplier delegates to AbstractApplier's MutableList.move
+ // helper which is what is being tested here.
+ val one = Node("one")
+ val two = Node("two")
+ val three = Node("three")
+ val four = Node("four")
+ applier.insert(0, one)
+ applier.insert(1, two)
+ applier.insert(2, three)
+ applier.insert(3, four)
+
+ applier.move(0, 4, 2)
+ assertEquals(listOf(three, four, one, two), root.children)
+ }
+
+ @Test fun moveMultipleLower() {
+ // Note: NodeApplier delegates to AbstractApplier's MutableList.move
+ // helper which is what is being tested here.
+ val one = Node("one")
+ val two = Node("two")
+ val three = Node("three")
+ val four = Node("four")
+ applier.insert(0, one)
+ applier.insert(1, two)
+ applier.insert(2, three)
+ applier.insert(3, four)
+
+ applier.move(2, 0, 2)
+ assertEquals(listOf(three, four, one, two), root.children)
+ }
+}
+
+private class Node(val name: String) {
+ val children = mutableListOf<Node>()
+ override fun toString() = name + children.joinToString(",", "(", ")")
+}
+
+@OptIn(ExperimentalComposeApi::class)
+private class NodeApplier(root: Node) : AbstractApplier<Node>(root) {
+ override fun insert(index: Int, instance: Node) {
+ current.children.add(index, instance)
+ }
+
+ override fun remove(index: Int, count: Int) {
+ current.children.remove(index, count)
+ }
+
+ override fun move(from: Int, to: Int, count: Int) {
+ current.children.move(from, to, count)
+ }
+
+ override fun onClear() {
+ current.children.clear()
+ }
+}
diff --git a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/collection/MutableVectorTest.kt b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/collection/MutableVectorTest.kt
index ead8db5..6247dd2 100644
--- a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/collection/MutableVectorTest.kt
+++ b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/collection/MutableVectorTest.kt
@@ -94,17 +94,21 @@
@Test
fun reversedAny() {
val reversedList = mutableListOf<Int>()
- assertFalse(list.reversedAny {
- reversedList.add(it)
- false
- })
+ assertFalse(
+ list.reversedAny {
+ reversedList.add(it)
+ false
+ }
+ )
assertEquals(reversedList, list.asMutableList().reversed())
val reversedSublist = mutableListOf<Int>()
- assertTrue(list.reversedAny {
- reversedSublist.add(it)
- reversedSublist.size == 2
- })
+ assertTrue(
+ list.reversedAny {
+ reversedSublist.add(it)
+ reversedSublist.size == 2
+ }
+ )
assertEquals(reversedSublist, listOf(5, 4))
}
diff --git a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/RoundRect.kt b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/RoundRect.kt
index 9d5a454..4a5814f 100644
--- a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/RoundRect.kt
+++ b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/RoundRect.kt
@@ -296,25 +296,29 @@
)
/** The top-left [Radius]. */
-@Deprecated("use topLeftRadius instead",
+@Deprecated(
+ "use topLeftRadius instead",
ReplaceWith("topLeftRadius", "androidx.compose.ui.geometry")
)
fun RoundRect.topLeftRadius(): Radius = topLeftRadius
/** The top-right [Radius]. */
-@Deprecated("Use topRightRadius instead",
+@Deprecated(
+ "Use topRightRadius instead",
ReplaceWith("topRightRadius", "androidx.compose.ui.geometry")
)
fun RoundRect.topRightRadius(): Radius = topRightRadius
/** The bottom-right [Radius]. */
-@Deprecated("Use bottomRightRadius instead",
+@Deprecated(
+ "Use bottomRightRadius instead",
ReplaceWith("bottomRightRadius", "androidx.compose.ui.geometry")
)
fun RoundRect.bottomRightRadius(): Radius = bottomRightRadius
/** The bottom-right [Radius]. */
-@Deprecated("Use bottomLeftRadius instead",
+@Deprecated(
+ "Use bottomLeftRadius instead",
ReplaceWith("bottomLeftRadius", "androidx.compose.ui.geometry")
)
/** The bottom-left [Radius]. */
@@ -339,7 +343,8 @@
bottomLeftRadius = bottomLeftRadius
)
-@Deprecated("Use outerRect instead",
+@Deprecated(
+ "Use outerRect instead",
ReplaceWith("boundingRect", "androidx.compose.ui.RoundRect")
)
/** The bounding box of this rounded rectangle (the rectangle with no rounded corners). */
@@ -398,20 +403,20 @@
* corner radii.
*/
val RoundRect.isRect get(): Boolean = (topLeftRadius.x == 0.0f || topLeftRadius.y == 0.0f) &&
- (topRightRadius.x == 0.0f || topRightRadius.y == 0.0f) &&
- (bottomLeftRadius.x == 0.0f || bottomLeftRadius.y == 0.0f) &&
- (bottomRightRadius.x == 0.0f || bottomRightRadius.y == 0.0f)
+ (topRightRadius.x == 0.0f || topRightRadius.y == 0.0f) &&
+ (bottomLeftRadius.x == 0.0f || bottomLeftRadius.y == 0.0f) &&
+ (bottomRightRadius.x == 0.0f || bottomRightRadius.y == 0.0f)
/** Whether this rounded rectangle has no side with a straight section. */
val RoundRect.isEllipse get(): Boolean =
topLeftRadius.x == topRightRadius.x &&
- topLeftRadius.y == topRightRadius.y &&
- topRightRadius.x == bottomRightRadius.x &&
- topRightRadius.y == bottomRightRadius.y &&
- bottomRightRadius.x == bottomLeftRadius.x &&
- bottomRightRadius.y == bottomLeftRadius.y &&
- width <= 2.0 * topLeftRadius.x &&
- height <= 2.0 * topLeftRadius.y
+ topLeftRadius.y == topRightRadius.y &&
+ topRightRadius.x == bottomRightRadius.x &&
+ topRightRadius.y == bottomRightRadius.y &&
+ bottomRightRadius.x == bottomLeftRadius.x &&
+ bottomRightRadius.y == bottomLeftRadius.y &&
+ width <= 2.0 * topLeftRadius.x &&
+ height <= 2.0 * topLeftRadius.y
/** Whether this rounded rectangle would draw as a circle. */
val RoundRect.isCircle get() = width == height && isEllipse
@@ -420,7 +425,8 @@
* The lesser of the magnitudes of the [RoundRect.width] and the [RoundRect.height] of this
* rounded rectangle.
*/
-@Deprecated("Use minDimension instead",
+@Deprecated(
+ "Use minDimension instead",
ReplaceWith("minDimension", "androidx.compose.ui.RoundRect")
)
val RoundRect.shortestSide get(): Float = minDimension
@@ -435,7 +441,8 @@
* The greater of the magnitudes of the [RoundRect.width] and the [RoundRect.height] of this
* rounded rectangle.
*/
-@Deprecated("Use maxDimension instead",
+@Deprecated(
+ "Use maxDimension instead",
ReplaceWith("maxDimension", "androidx.compose.ui.RoundRect")
)
val RoundRect.longestSide get(): Float = maxDimension
@@ -446,7 +453,8 @@
* The offset to the point halfway between the left and right and the top and
* bottom edges of this rectangle.
*/
-@Deprecated("Use center instead",
+@Deprecated(
+ "Use center instead",
ReplaceWith("center", "androidx.compose.ui.RoundRect")
)
fun RoundRect.center(): Offset = Offset((left + width / 2.0f), (top + height / 2.0f))
@@ -463,12 +471,12 @@
*/
val RoundRect.isSimple: Boolean
get() = topLeftRadius.x == topLeftRadius.y &&
- topLeftRadius.x == topRightRadius.x &&
- topLeftRadius.x == topRightRadius.y &&
- topLeftRadius.x == bottomRightRadius.x &&
- topLeftRadius.x == bottomRightRadius.y &&
- topLeftRadius.x == bottomLeftRadius.x &&
- topLeftRadius.x == bottomLeftRadius.y
+ topLeftRadius.x == topRightRadius.x &&
+ topLeftRadius.x == topRightRadius.y &&
+ topLeftRadius.x == bottomRightRadius.x &&
+ topLeftRadius.x == bottomRightRadius.y &&
+ topLeftRadius.x == bottomLeftRadius.x &&
+ topLeftRadius.x == bottomLeftRadius.y
/**
* Linearly interpolate between two rounded rectangles.
diff --git a/compose/ui/ui-geometry/src/test/kotlin/androidx/compose/ui/geometry/RoundRectTest.kt b/compose/ui/ui-geometry/src/test/kotlin/androidx/compose/ui/geometry/RoundRectTest.kt
index fa337dd..b883169 100644
--- a/compose/ui/ui-geometry/src/test/kotlin/androidx/compose/ui/geometry/RoundRectTest.kt
+++ b/compose/ui/ui-geometry/src/test/kotlin/androidx/compose/ui/geometry/RoundRectTest.kt
@@ -209,7 +209,8 @@
@Test
fun testSafeInnerRect() {
val insetFactor = 0.29289321881f // 1-cos(pi/4)
- val rr = RoundRect(left = 0f, top = 0f, right = 100f, bottom = 100f,
+ val rr = RoundRect(
+ left = 0f, top = 0f, right = 100f, bottom = 100f,
topLeftRadius = Radius(0f, 5f),
topRightRadius = Radius(5f, 10f),
bottomRightRadius = Radius(10f, 15f),
diff --git a/compose/ui/ui-graphics/api/current.txt b/compose/ui/ui-graphics/api/current.txt
index 857f1f0..e7cfcc0 100644
--- a/compose/ui/ui-graphics/api/current.txt
+++ b/compose/ui/ui-graphics/api/current.txt
@@ -265,7 +265,8 @@
method public long getMagenta-0d7_KjU();
method public long getRed-0d7_KjU();
method public long getTransparent-0d7_KjU();
- method public long getUnset-0d7_KjU();
+ method @Deprecated public long getUnset-0d7_KjU();
+ method public long getUnspecified-0d7_KjU();
method public long getWhite-0d7_KjU();
method public long getYellow-0d7_KjU();
property public final long Black;
@@ -278,7 +279,8 @@
property public final long Magenta;
property public final long Red;
property public final long Transparent;
- property public final long Unset;
+ property @Deprecated public final long Unset;
+ property public final long Unspecified;
property public final long White;
property public final long Yellow;
}
@@ -304,8 +306,10 @@
method @androidx.compose.runtime.Stable public static long Color(long color);
method @androidx.compose.runtime.Stable public static long Color(@IntRange(from=0, to=255) int red, @IntRange(from=0, to=255) int green, @IntRange(from=0, to=255) int blue, optional @IntRange(from=0, to=255) int alpha);
method @androidx.compose.runtime.Stable public static long compositeOver-6xK2E-Q(long, long background);
- method public static inline boolean isSet-8_81llA(long);
- method public static inline boolean isUnset-8_81llA(long);
+ method @Deprecated public static inline boolean isSet-8_81llA(long);
+ method public static inline boolean isSpecified-8_81llA(long);
+ method @Deprecated public static inline boolean isUnset-8_81llA(long);
+ method public static inline boolean isUnspecified-8_81llA(long);
method @androidx.compose.runtime.Stable public static long lerp-m18UwgE(long start, long stop, @FloatRange(from=0.0, to=1.0) float fraction);
method @androidx.compose.runtime.Stable public static float luminance-8_81llA(long);
method @ColorInt @androidx.compose.runtime.Stable public static int toArgb-8_81llA(long);
diff --git a/compose/ui/ui-graphics/api/public_plus_experimental_current.txt b/compose/ui/ui-graphics/api/public_plus_experimental_current.txt
index 857f1f0..e7cfcc0 100644
--- a/compose/ui/ui-graphics/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-graphics/api/public_plus_experimental_current.txt
@@ -265,7 +265,8 @@
method public long getMagenta-0d7_KjU();
method public long getRed-0d7_KjU();
method public long getTransparent-0d7_KjU();
- method public long getUnset-0d7_KjU();
+ method @Deprecated public long getUnset-0d7_KjU();
+ method public long getUnspecified-0d7_KjU();
method public long getWhite-0d7_KjU();
method public long getYellow-0d7_KjU();
property public final long Black;
@@ -278,7 +279,8 @@
property public final long Magenta;
property public final long Red;
property public final long Transparent;
- property public final long Unset;
+ property @Deprecated public final long Unset;
+ property public final long Unspecified;
property public final long White;
property public final long Yellow;
}
@@ -304,8 +306,10 @@
method @androidx.compose.runtime.Stable public static long Color(long color);
method @androidx.compose.runtime.Stable public static long Color(@IntRange(from=0, to=255) int red, @IntRange(from=0, to=255) int green, @IntRange(from=0, to=255) int blue, optional @IntRange(from=0, to=255) int alpha);
method @androidx.compose.runtime.Stable public static long compositeOver-6xK2E-Q(long, long background);
- method public static inline boolean isSet-8_81llA(long);
- method public static inline boolean isUnset-8_81llA(long);
+ method @Deprecated public static inline boolean isSet-8_81llA(long);
+ method public static inline boolean isSpecified-8_81llA(long);
+ method @Deprecated public static inline boolean isUnset-8_81llA(long);
+ method public static inline boolean isUnspecified-8_81llA(long);
method @androidx.compose.runtime.Stable public static long lerp-m18UwgE(long start, long stop, @FloatRange(from=0.0, to=1.0) float fraction);
method @androidx.compose.runtime.Stable public static float luminance-8_81llA(long);
method @ColorInt @androidx.compose.runtime.Stable public static int toArgb-8_81llA(long);
diff --git a/compose/ui/ui-graphics/api/restricted_current.txt b/compose/ui/ui-graphics/api/restricted_current.txt
index e1603ad..f234758 100644
--- a/compose/ui/ui-graphics/api/restricted_current.txt
+++ b/compose/ui/ui-graphics/api/restricted_current.txt
@@ -296,7 +296,8 @@
method public long getMagenta-0d7_KjU();
method public long getRed-0d7_KjU();
method public long getTransparent-0d7_KjU();
- method public long getUnset-0d7_KjU();
+ method @Deprecated public long getUnset-0d7_KjU();
+ method public long getUnspecified-0d7_KjU();
method public long getWhite-0d7_KjU();
method public long getYellow-0d7_KjU();
property public final long Black;
@@ -309,7 +310,8 @@
property public final long Magenta;
property public final long Red;
property public final long Transparent;
- property public final long Unset;
+ property @Deprecated public final long Unset;
+ property public final long Unspecified;
property public final long White;
property public final long Yellow;
}
@@ -335,8 +337,10 @@
method @androidx.compose.runtime.Stable public static long Color(long color);
method @androidx.compose.runtime.Stable public static long Color(@IntRange(from=0, to=255) int red, @IntRange(from=0, to=255) int green, @IntRange(from=0, to=255) int blue, optional @IntRange(from=0, to=255) int alpha);
method @androidx.compose.runtime.Stable public static long compositeOver-6xK2E-Q(long, long background);
- method public static inline boolean isSet-8_81llA(long);
- method public static inline boolean isUnset-8_81llA(long);
+ method @Deprecated public static inline boolean isSet-8_81llA(long);
+ method public static inline boolean isSpecified-8_81llA(long);
+ method @Deprecated public static inline boolean isUnset-8_81llA(long);
+ method public static inline boolean isUnspecified-8_81llA(long);
method @androidx.compose.runtime.Stable public static long lerp-m18UwgE(long start, long stop, @FloatRange(from=0.0, to=1.0) float fraction);
method @androidx.compose.runtime.Stable public static float luminance-8_81llA(long);
method @ColorInt @androidx.compose.runtime.Stable public static int toArgb-8_81llA(long);
diff --git a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Color.kt b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Color.kt
index 8272eff..42744fb 100644
--- a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Color.kt
+++ b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Color.kt
@@ -315,12 +315,26 @@
/**
* Because Color is an inline class, this represents an unset value
* without having to box the Color. It will be treated as [Transparent]
- * when drawn. A Color can compare with [Unset] for equality or use
- * [isUnset] to check for the unset value or [isSet] for any color that isn't
- * [Unset].
+ * when drawn. A Color can compare with [Unspecified] for equality or use
+ * [isUnspecified] to check for the unset value or [isSpecified] for any color that isn't
+ * [Unspecified].
+ */
+ @Deprecated(
+ "Use Color.Unspecified instead",
+ ReplaceWith("Color.Unspecified", "androidx.compose.ui.graphics")
+ )
+ @Stable
+ val Unset = Color(0f, 0f, 0f, 0f, ColorSpaces.Unspecified)
+
+ /**
+ * Because Color is an inline class, this represents an unset value
+ * without having to box the Color. It will be treated as [Transparent]
+ * when drawn. A Color can compare with [Unspecified] for equality or use
+ * [isUnspecified] to check for the unset value or [isSpecified] for any color that isn't
+ * [Unspecified].
*/
@Stable
- val Unset = Color(0f, 0f, 0f, 0f, ColorSpaces.Unset)
+ val Unspecified = Color(0f, 0f, 0f, 0f, ColorSpaces.Unspecified)
}
}
@@ -580,17 +594,37 @@
/**
* `false` when this is [Color.Unset].
*/
+@Deprecated(
+ "Use isSpecified instead",
+ ReplaceWith("Color.isSpecified", "androidx.compose.ui.graphics")
+)
@Stable
-inline val Color.isSet: Boolean get() = value != Color.Unset.value
+inline val Color.isSet: Boolean get() = value != Color.Unspecified.value
+
+/**
+ * `false` when this is [Color.Unspecified].
+ */
+@Stable
+inline val Color.isSpecified: Boolean get() = value != Color.Unspecified.value
/**
* `true` when this is [Color.Unset].
*/
+@Deprecated(
+ "Use Color.isUnspecified instead",
+ ReplaceWith("Color.isUnspecified", "androidx.compose.ui.graphics")
+)
@Stable
-inline val Color.isUnset: Boolean get() = value == Color.Unset.value
+inline val Color.isUnset: Boolean get() = value == Color.Unspecified.value
+
+/**
+ * `true` when this is [Color.Unspecified].
+ */
+@Stable
+inline val Color.isUnspecified: Boolean get() = value == Color.Unspecified.value
/**
* If this [Color] [isSet] then this is returned, otherwise [block] is executed and its result
* is returned.
*/
-inline fun Color.useOrElse(block: () -> Color): Color = if (isSet) this else block()
+inline fun Color.useOrElse(block: () -> Color): Color = if (isSpecified) this else block()
diff --git a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Outline.kt b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Outline.kt
index 668f162..8d8b0b13 100644
--- a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Outline.kt
+++ b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Outline.kt
@@ -97,25 +97,25 @@
colorFilter: ColorFilter? = null,
blendMode: BlendMode = DrawScope.DefaultBlendMode
) = drawOutlineHelper(
- outline,
- { rect ->
- drawRect(color, rect.topLeft(), rect.size(), alpha, style, colorFilter, blendMode)
- },
- { rrect ->
- val radius = rrect.bottomLeftRadius.x
- drawRoundRect(
- color = color,
- topLeft = rrect.topLeft(),
- size = rrect.size(),
- radius = Radius(radius),
- alpha = alpha,
- style = style,
- colorFilter = colorFilter,
- blendMode = blendMode
- )
- },
- { path -> drawPath(path, color, alpha, style, colorFilter, blendMode) }
- )
+ outline,
+ { rect ->
+ drawRect(color, rect.topLeft(), rect.size(), alpha, style, colorFilter, blendMode)
+ },
+ { rrect ->
+ val radius = rrect.bottomLeftRadius.x
+ drawRoundRect(
+ color = color,
+ topLeft = rrect.topLeft(),
+ size = rrect.size(),
+ radius = Radius(radius),
+ alpha = alpha,
+ style = style,
+ colorFilter = colorFilter,
+ blendMode = blendMode
+ )
+ },
+ { path -> drawPath(path, color, alpha, style, colorFilter, blendMode) }
+)
/**
* Draws the [Outline] on a [DrawScope].
@@ -136,25 +136,25 @@
colorFilter: ColorFilter? = null,
blendMode: BlendMode = DrawScope.DefaultBlendMode
) = drawOutlineHelper(
- outline,
- { rect ->
- drawRect(brush, rect.topLeft(), rect.size(), alpha, style, colorFilter, blendMode)
- },
- { rrect ->
- val radius = rrect.bottomLeftRadius.x
- drawRoundRect(
- brush = brush,
- topLeft = rrect.topLeft(),
- size = rrect.size(),
- radius = Radius(radius),
- alpha = alpha,
- style = style,
- colorFilter = colorFilter,
- blendMode = blendMode
- )
- },
- { path -> drawPath(path, brush, alpha, style, colorFilter, blendMode) }
- )
+ outline,
+ { rect ->
+ drawRect(brush, rect.topLeft(), rect.size(), alpha, style, colorFilter, blendMode)
+ },
+ { rrect ->
+ val radius = rrect.bottomLeftRadius.x
+ drawRoundRect(
+ brush = brush,
+ topLeft = rrect.topLeft(),
+ size = rrect.size(),
+ radius = Radius(radius),
+ alpha = alpha,
+ style = style,
+ colorFilter = colorFilter,
+ blendMode = blendMode
+ )
+ },
+ { path -> drawPath(path, brush, alpha, style, colorFilter, blendMode) }
+)
/**
* Convenience method to obtain an Offset from the Rect's top and left parameters
@@ -240,10 +240,10 @@
*/
private fun RoundRect.hasSameCornerRadius(): Boolean {
val sameRadiusX = bottomLeftRadius.x == bottomRightRadius.x &&
- bottomRightRadius.x == topRightRadius.x &&
- topRightRadius.x == topLeftRadius.x
+ bottomRightRadius.x == topRightRadius.x &&
+ topRightRadius.x == topLeftRadius.x
val sameRadiusY = bottomLeftRadius.y == bottomRightRadius.y &&
- bottomRightRadius.y == topRightRadius.y &&
- topRightRadius.y == topLeftRadius.y
+ bottomRightRadius.y == topRightRadius.y &&
+ topRightRadius.y == topLeftRadius.y
return sameRadiusX && sameRadiusY
}
diff --git a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/colorspace/ColorSpaces.kt b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/colorspace/ColorSpaces.kt
index 1d886d6..83cb4e7 100644
--- a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/colorspace/ColorSpaces.kt
+++ b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/colorspace/ColorSpaces.kt
@@ -259,7 +259,7 @@
/**
* This identifies the 'None' color.
*/
- internal val Unset = Rgb(
+ internal val Unspecified = Rgb(
"None",
SrgbPrimaries,
Illuminant.D65,
@@ -323,6 +323,6 @@
Acescg,
CieXyz,
CieLab,
- Unset
+ Unspecified
)
}
\ No newline at end of file
diff --git a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope.kt b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope.kt
index df9cad6..0989dbb 100644
--- a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope.kt
+++ b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope.kt
@@ -134,7 +134,8 @@
* @param block lambda that is called to issue drawing commands within the rotated
* coordinate space
*/
-@Deprecated("Use rotate(degrees, Offset(pivotX, pivotY)) instead",
+@Deprecated(
+ "Use rotate(degrees, Offset(pivotX, pivotY)) instead",
ReplaceWith(
"rotate(degrees, Offset(pivotX, pivotY))",
"androidx.compose.ui.graphics.drawscope"
@@ -202,7 +203,8 @@
* coordinate space vertically
* @param block lambda used to issue drawing commands within the scaled coordinate space
*/
-@Deprecated("Use scale(scaleX, scaleY, Offset(pivotX, pivotY))",
+@Deprecated(
+ "Use scale(scaleX, scaleY, Offset(pivotX, pivotY))",
ReplaceWith(
"scale(scaleX, scaleY, Offset(pivotX, pivotY))",
"androidx.compose.ui.graphics.drawscope"
diff --git a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/DrawTransform.kt b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/DrawTransform.kt
index 0cd38b5..35fd6053 100644
--- a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/DrawTransform.kt
+++ b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/DrawTransform.kt
@@ -57,8 +57,10 @@
* @param pivotY The y-coordinate for the pivot point, defaults to the center of the
* coordinate space vertically
*/
-@Deprecated("use rotateRad(radians, Offset(pivotX, pivotY)) instead",
- ReplaceWith("rotateRad(radians, Offset(pivotX, pivotY))",
+@Deprecated(
+ "use rotateRad(radians, Offset(pivotX, pivotY)) instead",
+ ReplaceWith(
+ "rotateRad(radians, Offset(pivotX, pivotY))",
"androidx.compose.ui.graphics.drawscope"
)
)
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopImageAssetTest.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopImageAssetTest.kt
index 6a8bcc1..02a4b2d 100644
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopImageAssetTest.kt
+++ b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopImageAssetTest.kt
@@ -90,22 +90,26 @@
val array = IntArray(5)
asset.readPixels(array, startX = 0, startY = 0, width = 1, height = 1, bufferOffset = 0)
- assertThat(array.map(::toHexString)).isEqualTo(listOf(
- "ffff0000",
- "00000000",
- "00000000",
- "00000000",
- "00000000"
- ))
+ assertThat(array.map(::toHexString)).isEqualTo(
+ listOf(
+ "ffff0000",
+ "00000000",
+ "00000000",
+ "00000000",
+ "00000000"
+ )
+ )
asset.readPixels(array, startX = 3, startY = 3, width = 2, height = 2, bufferOffset = 1)
- assertThat(array.map(::toHexString)).isEqualTo(listOf(
- "ffff0000",
- "ffff00ff",
- "ffffff00",
- "ff000000",
- "80000000"
- ))
+ assertThat(array.map(::toHexString)).isEqualTo(
+ listOf(
+ "ffff0000",
+ "ffff00ff",
+ "ffffff00",
+ "ff000000",
+ "80000000"
+ )
+ )
}
@Test
@@ -114,14 +118,16 @@
val array = IntArray(6)
asset.readPixels(array, startX = 3, startY = 3, width = 2, height = 2, stride = 3)
- assertThat(array.map(::toHexString)).isEqualTo(listOf(
- "ffff00ff",
- "ffffff00",
- "00000000",
- "ff000000",
- "80000000",
- "00000000"
- ))
+ assertThat(array.map(::toHexString)).isEqualTo(
+ listOf(
+ "ffff00ff",
+ "ffffff00",
+ "00000000",
+ "ff000000",
+ "80000000",
+ "00000000"
+ )
+ )
}
private fun toHexString(num: Int) = "%08x".format(num)
diff --git a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPaintTest.kt b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPaintTest.kt
index 4ebbba4..6d71958e 100644
--- a/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPaintTest.kt
+++ b/compose/ui/ui-graphics/src/desktopTest/kotlin/androidx/compose/ui/graphics/DesktopPaintTest.kt
@@ -17,9 +17,11 @@
package androidx.compose.ui.graphics
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.platform.DesktopPlatform
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import org.junit.Assert.assertEquals
+import org.junit.Assume.assumeTrue
import org.junit.Test
class DesktopPaintTest : DesktopGraphicsTest() {
@@ -88,6 +90,8 @@
@Test
fun filterQuality() {
+ assumeTrue(DesktopPlatform.Current == DesktopPlatform.MacOS)
+
canvas.drawImageRect(
image = imageFromResource("androidx/compose/desktop/test.png"),
srcOffset = IntOffset(0, 2),
@@ -182,13 +186,16 @@
fun imageShader() {
canvas.drawRect(left = 0f, top = 0f, right = 16f, bottom = 16f, paint = redPaint)
- canvas.drawRect(left = 2f, top = 2f, right = 14f, bottom = 14f, paint = Paint().apply {
- shader = ImageShader(
- imageFromResource("androidx/compose/desktop/test.png"),
- tileModeX = TileMode.Clamp,
- tileModeY = TileMode.Repeated
- )
- })
+ canvas.drawRect(
+ left = 2f, top = 2f, right = 14f, bottom = 14f,
+ paint = Paint().apply {
+ shader = ImageShader(
+ imageFromResource("androidx/compose/desktop/test.png"),
+ tileModeX = TileMode.Clamp,
+ tileModeY = TileMode.Repeated
+ )
+ }
+ )
screenshotRule.snap(surface)
}
diff --git a/compose/ui/ui-graphics/src/test/java/androidx/compose/ui/graphics/ColorTest.kt b/compose/ui/ui-graphics/src/test/java/androidx/compose/ui/graphics/ColorTest.kt
index 6491aa3..ebaa71c 100644
--- a/compose/ui/ui-graphics/src/test/java/androidx/compose/ui/graphics/ColorTest.kt
+++ b/compose/ui/ui-graphics/src/test/java/androidx/compose/ui/graphics/ColorTest.kt
@@ -248,12 +248,12 @@
@Test
fun noneColor() {
- assertTrue(Color.Unset.isUnset)
- assertFalse(Color.Unset.isSet)
- assertFalse(Color.Red.isUnset)
- assertTrue(Color.Red.isSet)
- assertEquals(Color.Transparent.toArgb(), Color.Unset.toArgb())
- assertNotEquals(Color.Transparent, Color.Unset)
+ assertTrue(Color.Unspecified.isUnspecified)
+ assertFalse(Color.Unspecified.isSpecified)
+ assertFalse(Color.Red.isUnspecified)
+ assertTrue(Color.Red.isSpecified)
+ assertEquals(Color.Transparent.toArgb(), Color.Unspecified.toArgb())
+ assertNotEquals(Color.Transparent, Color.Unspecified)
}
@Test
diff --git a/compose/ui/ui-text-android/src/androidTest/java/androidx/compose/ui/text/android/style/FontSpanTest.kt b/compose/ui/ui-text-android/src/androidTest/java/androidx/compose/ui/text/android/style/FontSpanTest.kt
index 072af1f..d3c3c34 100644
--- a/compose/ui/ui-text-android/src/androidTest/java/androidx/compose/ui/text/android/style/FontSpanTest.kt
+++ b/compose/ui/ui-text-android/src/androidTest/java/androidx/compose/ui/text/android/style/FontSpanTest.kt
@@ -17,10 +17,15 @@
package androidx.compose.ui.text.android.style
import android.graphics.Typeface
+import android.graphics.fonts.FontStyle
import android.text.TextPaint
import androidx.compose.ui.text.android.InternalPlatformTextApi
+import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.times
+import com.nhaarman.mockitokotlin2.verify
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -39,4 +44,54 @@
span.updatePaint(textPaint)
assertThat(textPaint.typeface).isSameInstanceAs(typeface)
}
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 27)
+ fun updatePaint_bold_belowAPI27() {
+ val textPaint = TextPaint()
+ textPaint.typeface = Typeface.defaultFromStyle(Typeface.BOLD)
+ val getFont = mock<(Int, Boolean) -> Typeface>()
+ val span = FontSpan(getFont)
+
+ span.updatePaint(textPaint)
+ verify(getFont, times(1)).invoke(FontStyle.FONT_WEIGHT_BOLD, false)
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 27)
+ fun updatePaint_italic_belowAPI27() {
+ val textPaint = TextPaint()
+ textPaint.typeface = Typeface.defaultFromStyle(Typeface.ITALIC)
+ val getFont = mock<(Int, Boolean) -> Typeface>()
+ val span = FontSpan(getFont)
+
+ span.updatePaint(textPaint)
+ verify(getFont, times(1)).invoke(FontStyle.FONT_WEIGHT_NORMAL, true)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 28)
+ fun updatePaint_extraLight_aboveAPI28() {
+ val textPaint = TextPaint()
+ val fontWeight = FontStyle.FONT_WEIGHT_EXTRA_LIGHT
+ textPaint.typeface = Typeface.create(null, fontWeight, false)
+ val getFont = mock<(Int, Boolean) -> Typeface>()
+ val span = FontSpan(getFont)
+
+ span.updatePaint(textPaint)
+ verify(getFont, times(1)).invoke(fontWeight, false)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 28)
+ fun updatePaint_italic_aboveAPI28() {
+ val textPaint = TextPaint()
+ val italic = true
+ textPaint.typeface = Typeface.create(null, FontStyle.FONT_WEIGHT_NORMAL, italic)
+ val getFont = mock<(Int, Boolean) -> Typeface>()
+ val span = FontSpan(getFont)
+
+ span.updatePaint(textPaint)
+ verify(getFont, times(1)).invoke(FontStyle.FONT_WEIGHT_NORMAL, italic)
+ }
}
\ No newline at end of file
diff --git a/compose/ui/ui-text-android/src/main/java/androidx/compose/ui/text/android/style/FontSpan.kt b/compose/ui/ui-text-android/src/main/java/androidx/compose/ui/text/android/style/FontSpan.kt
index e062b1a..49e279e 100644
--- a/compose/ui/ui-text-android/src/main/java/androidx/compose/ui/text/android/style/FontSpan.kt
+++ b/compose/ui/ui-text-android/src/main/java/androidx/compose/ui/text/android/style/FontSpan.kt
@@ -42,14 +42,14 @@
textPaint.typeface = getTypeface(FontStyle.FONT_WEIGHT_NORMAL, false)
return
}
- val weight = if (Build.VERSION.SDK_INT <= 28) {
+ val weight = if (Build.VERSION.SDK_INT >= 28) {
+ oldTypeface.weight
+ } else {
if (oldTypeface.isBold) {
FontStyle.FONT_WEIGHT_BOLD
} else {
FontStyle.FONT_WEIGHT_NORMAL
}
- } else {
- oldTypeface.weight
}
textPaint.typeface = getTypeface(weight, oldTypeface.isItalic)
}
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/intl/LocaleListTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/intl/LocaleListTest.kt
index 5b10e8a..b95bfea 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/intl/LocaleListTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/intl/LocaleListTest.kt
@@ -54,4 +54,20 @@
assertThat(LocaleList("en-US,ja-JP"))
.isNotEqualTo(LocaleList("en-US,es-ES"))
}
+
+ @Test
+ fun getCurrent_afterJavaLocaleSetDefault() {
+ val javaLocales = listOf(
+ java.util.Locale("ar"),
+ java.util.Locale("ja"),
+ java.util.Locale("en")
+ )
+ for (javaLocale in javaLocales) {
+ java.util.Locale.setDefault(javaLocale)
+
+ assertThat(LocaleList.current.first()).isEqualTo(
+ Locale(AndroidLocale(javaLocale))
+ )
+ }
+ }
}
\ No newline at end of file
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/AndroidParagraphTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/AndroidParagraphTest.kt
index ae160fd..d3ef45f 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/AndroidParagraphTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/AndroidParagraphTest.kt
@@ -12,6 +12,7 @@
import android.text.style.StrikethroughSpan
import android.text.style.UnderlineSpan
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.graphics.toArgb
@@ -44,6 +45,7 @@
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
+import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
@@ -1132,6 +1134,191 @@
}
@Test
+ fun testPaint_can_change_TextDecoration_to_Underline() {
+ val paragraph = simpleParagraph(
+ text = "",
+ style = TextStyle(textDecoration = null),
+ width = 0.0f
+ )
+ assertThat(paragraph.textPaint.isUnderlineText).isFalse()
+
+ val canvas = Canvas(android.graphics.Canvas())
+ paragraph.paint(canvas, textDecoration = TextDecoration.Underline)
+ assertThat(paragraph.textPaint.isUnderlineText).isEqualTo(true)
+ }
+
+ @Test
+ fun testPaint_can_change_TextDecoration_to_None() {
+ val paragraph = simpleParagraph(
+ text = "",
+ style = TextStyle(
+ textDecoration = TextDecoration.Underline
+ ),
+ width = 0.0f
+ )
+ assertThat(paragraph.textPaint.isUnderlineText).isTrue()
+
+ val canvas = Canvas(android.graphics.Canvas())
+ paragraph.paint(canvas, textDecoration = TextDecoration.None)
+ assertThat(paragraph.textPaint.isUnderlineText).isFalse()
+ }
+
+ @Test
+ fun testPaint_can_change_TextDecoration_null() {
+ val paragraph = simpleParagraph(
+ text = "",
+ style = TextStyle(
+ textDecoration = TextDecoration.Underline
+ ),
+ width = 0.0f
+ )
+ assertThat(paragraph.textPaint.isUnderlineText).isTrue()
+
+ val canvas = Canvas(android.graphics.Canvas())
+ paragraph.paint(canvas, textDecoration = null)
+ assertThat(paragraph.textPaint.isUnderlineText).isFalse()
+ }
+
+ @SdkSuppress(minSdkVersion = 29)
+ @Test
+ fun testPaint_can_change_Shadow() {
+ val paragraph = simpleParagraph(
+ text = "",
+ style = TextStyle(shadow = null),
+ width = 0.0f
+ )
+
+ assertThat(paragraph.textPaint.shadowLayerColor).isEqualTo(0)
+ assertThat(paragraph.textPaint.shadowLayerDx).isEqualTo(0f)
+ assertThat(paragraph.textPaint.shadowLayerDy).isEqualTo(0f)
+ assertThat(paragraph.textPaint.shadowLayerRadius).isEqualTo(0f)
+
+ val canvas = Canvas(android.graphics.Canvas())
+ val color = Color.Red
+ val dx = 1f
+ val dy = 2f
+ val radius = 3f
+
+ paragraph.paint(
+ canvas,
+ shadow = Shadow(color = color, offset = Offset(dx, dy), blurRadius = radius)
+ )
+ assertThat(paragraph.textPaint.shadowLayerColor).isEqualTo(color.toArgb())
+ assertThat(paragraph.textPaint.shadowLayerDx).isEqualTo(dx)
+ assertThat(paragraph.textPaint.shadowLayerDy).isEqualTo(dy)
+ assertThat(paragraph.textPaint.shadowLayerRadius).isEqualTo(radius)
+ }
+
+ @SdkSuppress(minSdkVersion = 29)
+ @Test
+ fun testPaint_can_change_Shadow_to_None() {
+ val dx = 1f
+ val dy = 2f
+ val radius = 3f
+ val color = Color.Red
+
+ val paragraph = simpleParagraph(
+ text = "",
+ style = TextStyle(
+ shadow = Shadow(color, Offset(dx, dy), radius)
+ ),
+ width = 0.0f
+ )
+
+ assertThat(paragraph.textPaint.shadowLayerDx).isEqualTo(dx)
+ assertThat(paragraph.textPaint.shadowLayerDy).isEqualTo(dy)
+ assertThat(paragraph.textPaint.shadowLayerRadius).isEqualTo(radius)
+ assertThat(paragraph.textPaint.shadowLayerColor).isEqualTo(color.toArgb())
+
+ val canvas = Canvas(android.graphics.Canvas())
+ paragraph.paint(canvas, shadow = null)
+ assertThat(paragraph.textPaint.shadowLayerDx).isEqualTo(0f)
+ assertThat(paragraph.textPaint.shadowLayerDy).isEqualTo(0f)
+ assertThat(paragraph.textPaint.shadowLayerRadius).isEqualTo(0f)
+ assertThat(paragraph.textPaint.shadowLayerColor).isEqualTo(0)
+ }
+
+ @SdkSuppress(minSdkVersion = 29)
+ @Test
+ fun testPaint_can_change_Shadow_null() {
+ val dx = 1f
+ val dy = 2f
+ val radius = 3f
+ val color = Color.Red
+
+ val paragraph = simpleParagraph(
+ text = "",
+ style = TextStyle(
+ shadow = Shadow(color, Offset(dx, dy), radius)
+ ),
+ width = 0.0f
+ )
+
+ assertThat(paragraph.textPaint.shadowLayerDx).isEqualTo(dx)
+ assertThat(paragraph.textPaint.shadowLayerDy).isEqualTo(dy)
+ assertThat(paragraph.textPaint.shadowLayerRadius).isEqualTo(radius)
+ assertThat(paragraph.textPaint.shadowLayerColor).isEqualTo(color.toArgb())
+
+ val canvas = Canvas(android.graphics.Canvas())
+ paragraph.paint(canvas, shadow = Shadow.None)
+ assertThat(paragraph.textPaint.shadowLayerDx).isEqualTo(0f)
+ assertThat(paragraph.textPaint.shadowLayerDy).isEqualTo(0f)
+ assertThat(paragraph.textPaint.shadowLayerRadius).isEqualTo(0f)
+ assertThat(paragraph.textPaint.shadowLayerColor).isEqualTo(0)
+ }
+
+ @Test
+ fun testPaint_can_change_Color() {
+ val color1 = Color.Red
+
+ val paragraph = simpleParagraph(
+ text = "",
+ style = TextStyle(color = Color.Red),
+ width = 0.0f
+ )
+ assertThat(paragraph.textPaint.color).isEqualTo(color1.toArgb())
+
+ val color2 = Color.Yellow
+ val canvas = Canvas(android.graphics.Canvas())
+ paragraph.paint(canvas, color = color2)
+ assertThat(paragraph.textPaint.color).isEqualTo(color2.toArgb())
+ }
+
+ @Test
+ fun testPaint_cannot_change_Color_to_Unspecified() {
+ val color1 = Color.Red
+
+ val paragraph = simpleParagraph(
+ text = "",
+ style = TextStyle(color = Color.Red),
+ width = 0.0f
+ )
+ assertThat(paragraph.textPaint.color).isEqualTo(color1.toArgb())
+
+ val color2 = Color.Unspecified
+ val canvas = Canvas(android.graphics.Canvas())
+ paragraph.paint(canvas, color = color2)
+ assertThat(paragraph.textPaint.color).isEqualTo(color1.toArgb())
+ }
+
+ @Test
+ fun testPaint_can_change_Color_to_Transparent() {
+ val color1 = Color.Red
+
+ val paragraph = simpleParagraph(
+ text = "",
+ style = TextStyle(color = Color.Red),
+ width = 0.0f
+ )
+ assertThat(paragraph.textPaint.color).isEqualTo(color1.toArgb())
+
+ val color2 = Color.Transparent
+ val canvas = Canvas(android.graphics.Canvas())
+ paragraph.paint(canvas, color = color2)
+ assertThat(paragraph.textPaint.color).isEqualTo(color2.toArgb())
+ }
+
+ @Test
fun testSpanStyle_baselineShift_appliedAsSpan() {
// baselineShift is reset in the Android Layout constructor.
// therefore we cannot apply them on paint, have to use spans.
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/AndroidTextPaintTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/AndroidTextPaintTest.kt
new file mode 100644
index 0000000..dff1251
--- /dev/null
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/platform/AndroidTextPaintTest.kt
@@ -0,0 +1,201 @@
+/*
+ * 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.compose.ui.text.platform
+
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shadow
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.text.style.TextDecoration
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+@SmallTest
+class AndroidTextPaintTest {
+
+ @Test
+ fun textDecoration_defaultValues() {
+ val textPaint = AndroidTextPaint(0)
+ assertThat(textPaint.isUnderlineText).isFalse()
+ assertThat(textPaint.isStrikeThruText).isFalse()
+ }
+
+ @Test
+ fun setTextDecoration_withNone() {
+ val textPaint = AndroidTextPaint(0)
+ textPaint.setTextDecoration(TextDecoration.None)
+ assertThat(textPaint.isUnderlineText).isFalse()
+ assertThat(textPaint.isStrikeThruText).isFalse()
+ }
+
+ @Test
+ fun setTextDecoration_withNull() {
+ val textPaint = AndroidTextPaint(0)
+ textPaint.setTextDecoration(null)
+ assertThat(textPaint.isUnderlineText).isFalse()
+ assertThat(textPaint.isStrikeThruText).isFalse()
+ }
+
+ @Test
+ fun setTextDecoration_withUnderline() {
+ val textPaint = AndroidTextPaint(0)
+ textPaint.setTextDecoration(TextDecoration.Underline)
+ assertThat(textPaint.isUnderlineText).isTrue()
+ assertThat(textPaint.isStrikeThruText).isFalse()
+ }
+
+ @Test
+ fun setTextDecoration_withLineThrough() {
+ val textPaint = AndroidTextPaint(0)
+ textPaint.setTextDecoration(TextDecoration.LineThrough)
+ assertThat(textPaint.isUnderlineText).isFalse()
+ assertThat(textPaint.isStrikeThruText).isTrue()
+ }
+
+ @Test
+ fun setTextDecoration_withLineThroughAndUnderline() {
+ val textPaint = AndroidTextPaint(0)
+ textPaint.setTextDecoration(
+ TextDecoration.combine(
+ listOf(TextDecoration.LineThrough, TextDecoration.Underline)
+ )
+ )
+ assertThat(textPaint.isUnderlineText).isTrue()
+ assertThat(textPaint.isStrikeThruText).isTrue()
+ }
+
+ @Test
+ fun setTextDecoration_changeDecorationToNull() {
+ val textPaint = AndroidTextPaint(0)
+ textPaint.setTextDecoration(
+ TextDecoration.combine(
+ listOf(TextDecoration.LineThrough, TextDecoration.Underline)
+ )
+ )
+ assertThat(textPaint.isUnderlineText).isTrue()
+ assertThat(textPaint.isStrikeThruText).isTrue()
+
+ textPaint.setTextDecoration(null)
+ assertThat(textPaint.isUnderlineText).isFalse()
+ assertThat(textPaint.isStrikeThruText).isFalse()
+ }
+
+ @Test
+ fun setColor_to_valid_value() {
+ val color = Color.Red
+ val textPaint = AndroidTextPaint(0)
+ textPaint.setColor(color)
+
+ assertThat(textPaint.color).isEqualTo(color.toArgb())
+ }
+
+ @Test
+ fun setColor_to_unspecified() {
+ val textPaint = AndroidTextPaint(0)
+ textPaint.setColor(Color.Unspecified)
+ assertThat(textPaint.color).isNotEqualTo(Color.Unspecified.toArgb())
+
+ textPaint.setColor(Color.Red)
+ assertThat(textPaint.color).isEqualTo(Color.Red.toArgb())
+
+ textPaint.setColor(Color.Unspecified)
+ assertThat(textPaint.color).isEqualTo(Color.Red.toArgb())
+ }
+
+ @Test
+ fun setColor_to_transparent() {
+ val textPaint = AndroidTextPaint(0)
+ textPaint.setColor(Color.Transparent)
+ assertThat(textPaint.color).isEqualTo(Color.Transparent.toArgb())
+
+ textPaint.setColor(Color.Red)
+ assertThat(textPaint.color).isEqualTo(Color.Red.toArgb())
+
+ textPaint.setColor(Color.Transparent)
+ assertThat(textPaint.color).isEqualTo(Color.Transparent.toArgb())
+ }
+
+ @SdkSuppress(minSdkVersion = 29)
+ @Test
+ fun shadow_default_values() {
+ val textPaint = AndroidTextPaint(0)
+
+ // default color is 0 since we do not update it
+ assertThat(textPaint.shadowLayerDx).isEqualTo(0f)
+ assertThat(textPaint.shadowLayerDy).isEqualTo(0f)
+ assertThat(textPaint.shadowLayerRadius).isEqualTo(0f)
+ assertThat(textPaint.shadowLayerColor).isEqualTo(0)
+ }
+
+ @SdkSuppress(minSdkVersion = 29)
+ @Test
+ fun setShadow() {
+ val dx = 1f
+ val dy = 2f
+ val radius = 3f
+ val color = Color.Red
+ val textPaint = AndroidTextPaint(0)
+
+ textPaint.setShadow(Shadow(color, Offset(dx, dy), radius))
+
+ assertThat(textPaint.shadowLayerDx).isEqualTo(dx)
+ assertThat(textPaint.shadowLayerDy).isEqualTo(dy)
+ assertThat(textPaint.shadowLayerRadius).isEqualTo(radius)
+ assertThat(textPaint.shadowLayerColor).isEqualTo(color.toArgb())
+ }
+
+ @SdkSuppress(minSdkVersion = 29)
+ @Test
+ fun resetShadow_to_None() {
+ val dx = 1f
+ val dy = 2f
+ val radius = 3f
+ val color = Color.Red
+ val textPaint = AndroidTextPaint(0)
+
+ textPaint.setShadow(Shadow(color, Offset(dx, dy), radius))
+ textPaint.setShadow(Shadow.None)
+
+ assertThat(textPaint.shadowLayerDx).isEqualTo(0f)
+ assertThat(textPaint.shadowLayerDy).isEqualTo(0f)
+ assertThat(textPaint.shadowLayerRadius).isEqualTo(0f)
+ assertThat(textPaint.shadowLayerColor).isEqualTo(0)
+ }
+
+ @SdkSuppress(minSdkVersion = 29)
+ @Test
+ fun resetShadow_to_null() {
+ val dx = 1f
+ val dy = 2f
+ val radius = 3f
+ val color = Color.Red
+ val textPaint = AndroidTextPaint(0)
+
+ textPaint.setShadow(Shadow(color, Offset(dx, dy), radius))
+ textPaint.setShadow(null)
+
+ assertThat(textPaint.shadowLayerDx).isEqualTo(0f)
+ assertThat(textPaint.shadowLayerDy).isEqualTo(0f)
+ assertThat(textPaint.shadowLayerRadius).isEqualTo(0f)
+ assertThat(textPaint.shadowLayerColor).isEqualTo(0)
+ }
+}
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraph.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraph.kt
index e2be14c..b685ec1 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraph.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraph.kt
@@ -16,7 +16,6 @@
package androidx.compose.ui.text.platform
import android.text.Spanned
-import android.text.TextPaint
import android.text.TextUtils
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
@@ -47,7 +46,6 @@
import androidx.compose.ui.text.android.selection.WordBoundary
import androidx.compose.ui.text.android.style.PlaceholderSpan
import androidx.compose.ui.text.font.Font
-import androidx.compose.ui.text.platform.extensions.applySpanStyle
import androidx.compose.ui.text.style.ResolvedTextDirection
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
@@ -209,7 +207,7 @@
get() = paragraphIntrinsics.charSequence
@VisibleForTesting
- internal val textPaint: TextPaint
+ internal val textPaint: AndroidTextPaint
get() = paragraphIntrinsics.textPaint
override fun getLineForVerticalPosition(vertical: Float): Int {
@@ -329,17 +327,10 @@
shadow: Shadow?,
textDecoration: TextDecoration?
) {
- if (color != Color.Unset || shadow != null || textDecoration != null) {
- textPaint.applySpanStyle(
- style = SpanStyle(
- color = color,
- shadow = shadow,
- textDecoration = textDecoration
- ),
- typefaceAdapter = paragraphIntrinsics.typefaceAdapter,
- density = paragraphIntrinsics.density
- )
- }
+ textPaint.setColor(color)
+ textPaint.setShadow(shadow)
+ textPaint.setTextDecoration(textDecoration)
+
val nativeCanvas = canvas.nativeCanvas
if (didExceedMaxLines) {
nativeCanvas.save()
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphIntrinsics.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphIntrinsics.kt
index daf8c46..171edc6 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphIntrinsics.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphIntrinsics.kt
@@ -17,7 +17,6 @@
package androidx.compose.ui.text.platform
import android.graphics.Paint
-import android.text.TextPaint
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.ParagraphIntrinsics
import androidx.compose.ui.text.Placeholder
@@ -46,7 +45,7 @@
val density: Density
) : ParagraphIntrinsics {
- internal val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
+ internal val textPaint = AndroidTextPaint(Paint.ANTI_ALIAS_FLAG)
internal val charSequence: CharSequence
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidTextPaint.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidTextPaint.kt
new file mode 100644
index 0000000..7732ab3
--- /dev/null
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidTextPaint.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.compose.ui.text.platform
+
+import android.text.TextPaint
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shadow
+import androidx.compose.ui.graphics.isSpecified
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.text.style.TextDecoration
+
+internal class AndroidTextPaint(flags: Int) : TextPaint(flags) {
+ private var textDecoration: TextDecoration = TextDecoration.None
+ private var shadow: Shadow = Shadow.None
+
+ fun setTextDecoration(textDecoration: TextDecoration?) {
+ val tmpTextDecoration = textDecoration ?: TextDecoration.None
+ if (this.textDecoration != tmpTextDecoration) {
+ this.textDecoration = tmpTextDecoration
+ isUnderlineText = TextDecoration.Underline in this.textDecoration
+ isStrikeThruText = TextDecoration.LineThrough in this.textDecoration
+ }
+ }
+
+ fun setShadow(shadow: Shadow?) {
+ val tmpShadow = shadow ?: Shadow.None
+ if (this.shadow != tmpShadow) {
+ this.shadow = tmpShadow
+ if (this.shadow == Shadow.None) {
+ clearShadowLayer()
+ } else {
+ setShadowLayer(
+ this.shadow.blurRadius,
+ this.shadow.offset.x,
+ this.shadow.offset.y,
+ this.shadow.color.toArgb()
+ )
+ }
+ }
+ }
+
+ fun setColor(color: Color) {
+ if (color.isSpecified) {
+ val argbColor = color.toArgb()
+ if (this.color != argbColor) {
+ this.color = argbColor
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.kt
index 7b9e7f3..16d7f45 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/SpannableExtensions.kt
@@ -32,7 +32,7 @@
import android.text.style.UnderlineSpan
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
-import androidx.compose.ui.graphics.isSet
+import androidx.compose.ui.graphics.isSpecified
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
@@ -264,7 +264,7 @@
}
private fun Spannable.setBackground(color: Color, start: Int, end: Int) {
- if (color.isSet) {
+ if (color.isSpecified) {
setSpan(
BackgroundColorSpan(color.toArgb()),
start,
@@ -358,7 +358,7 @@
}
private fun Spannable.setColor(color: Color, start: Int, end: Int) {
- if (color.isSet) {
+ if (color.isSpecified) {
setSpan(ForegroundColorSpan(color.toArgb()), start, end)
}
}
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/TextPaintExtensions.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/TextPaintExtensions.kt
index 5a76f05..96f1980 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/TextPaintExtensions.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/extensions/TextPaintExtensions.kt
@@ -18,11 +18,7 @@
import android.graphics.Typeface
import android.os.Build
-import android.text.TextPaint
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shadow
-import androidx.compose.ui.graphics.isSet
-import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.font.FontListFontFamily
import androidx.compose.ui.text.font.FontStyle
@@ -30,15 +26,15 @@
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.intl.LocaleList
+import androidx.compose.ui.text.platform.AndroidTextPaint
import androidx.compose.ui.text.platform.TypefaceAdapter
import androidx.compose.ui.text.style.BaselineShift
-import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextGeometricTransform
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType
-internal fun TextPaint.applySpanStyle(
+internal fun AndroidTextPaint.applySpanStyle(
style: SpanStyle,
typefaceAdapter: TypefaceAdapter,
density: Density
@@ -70,10 +66,6 @@
}
}
- if (style.color.isSet) {
- color = style.color.toArgb()
- }
-
when (style.letterSpacing.type) {
TextUnitType.Em -> { letterSpacing = style.letterSpacing.value }
TextUnitType.Sp -> {} // Sp will be handled by applying a span
@@ -91,23 +83,10 @@
textSkewX += style.textGeometricTransform.skewX
}
- if (style.shadow != null && style.shadow != Shadow.None) {
- setShadowLayer(
- style.shadow.blurRadius,
- style.shadow.offset.x,
- style.shadow.offset.y,
- style.shadow.color.toArgb()
- )
- }
-
- if (style.textDecoration != null && style.textDecoration != TextDecoration.None) {
- if (TextDecoration.Underline in style.textDecoration) {
- isUnderlineText = true
- }
- if (TextDecoration.LineThrough in style.textDecoration) {
- isStrikeThruText = true
- }
- }
+ // these parameters are also updated by the Paragraph.draw
+ setColor(style.color)
+ setShadow(style.shadow)
+ setTextDecoration(style.textDecoration)
// When FontFamily is a custom font(FontListFontFamily), it needs to be applied on Paint to
// compute empty paragraph height. Meanwhile, we also need a FontSpan for
@@ -129,7 +108,7 @@
TextUnit.Inherit
},
background = if (style.background == Color.Transparent) {
- Color.Unset // No need to add transparent background for default text style.
+ Color.Unspecified // No need to add transparent background for default text style.
} else {
style.background
},
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/MultiParagraph.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/MultiParagraph.kt
index a625fdd..6f71e74 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/MultiParagraph.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/MultiParagraph.kt
@@ -234,7 +234,7 @@
/** Paint the paragraphs to canvas. */
fun paint(
canvas: Canvas,
- color: Color = Color.Unset,
+ color: Color = Color.Unspecified,
shadow: Shadow? = null,
decoration: TextDecoration? = null
) {
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Paragraph.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Paragraph.kt
index 2f53bcd..19e6dd0 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Paragraph.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Paragraph.kt
@@ -243,7 +243,7 @@
*/
fun paint(
canvas: Canvas,
- color: Color = Color.Unset,
+ color: Color = Color.Unspecified,
shadow: Shadow? = null,
textDecoration: TextDecoration? = null
)
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt
index 021eb0d..b7f82b2 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/SpanStyle.kt
@@ -69,7 +69,7 @@
*/
@Immutable
data class SpanStyle(
- val color: Color = Color.Unset,
+ val color: Color = Color.Unspecified,
val fontSize: TextUnit = TextUnit.Inherit,
val fontWeight: FontWeight? = null,
val fontStyle: FontStyle? = null,
@@ -80,7 +80,7 @@
val baselineShift: BaselineShift? = null,
val textGeometricTransform: TextGeometricTransform? = null,
val localeList: LocaleList? = null,
- val background: Color = Color.Unset,
+ val background: Color = Color.Unspecified,
val textDecoration: TextDecoration? = null,
val shadow: Shadow? = null
) {
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextStyle.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextStyle.kt
index 1887d45..a1d8b1a 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextStyle.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TextStyle.kt
@@ -82,7 +82,7 @@
*/
@Immutable
data class TextStyle(
- val color: Color = Color.Unset,
+ val color: Color = Color.Unspecified,
val fontSize: TextUnit = TextUnit.Inherit,
val fontWeight: FontWeight? = null,
val fontStyle: FontStyle? = null,
@@ -93,7 +93,7 @@
val baselineShift: BaselineShift? = null,
val textGeometricTransform: TextGeometricTransform? = null,
val localeList: LocaleList? = null,
- val background: Color = Color.Unset,
+ val background: Color = Color.Unspecified,
val textDecoration: TextDecoration? = null,
val shadow: Shadow? = null,
val textAlign: TextAlign? = null,
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/intl/LocaleList.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/intl/LocaleList.kt
index ae96c2f..cba9ea3 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/intl/LocaleList.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/intl/LocaleList.kt
@@ -32,7 +32,8 @@
/**
* Returns Locale object which represents current locale
*/
- val current = LocaleList(platformLocaleDelegate.current.map { Locale(it) })
+ val current: LocaleList
+ get() = LocaleList(platformLocaleDelegate.current.map { Locale(it) })
}
/**
diff --git a/compose/ui/ui-text/src/desktopMain/kotlin/androidx/compose/ui/text/platform/DesktopParagraph.kt b/compose/ui/ui-text/src/desktopMain/kotlin/androidx/compose/ui/text/platform/DesktopParagraph.kt
index ab132e3..76ed1c3 100644
--- a/compose/ui/ui-text/src/desktopMain/kotlin/androidx/compose/ui/text/platform/DesktopParagraph.kt
+++ b/compose/ui/ui-text/src/desktopMain/kotlin/androidx/compose/ui/text/platform/DesktopParagraph.kt
@@ -22,7 +22,7 @@
import androidx.compose.ui.graphics.DesktopPath
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shadow
-import androidx.compose.ui.graphics.isSet
+import androidx.compose.ui.graphics.isSpecified
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.graphics.toComposeRect
@@ -308,7 +308,7 @@
var currentColor = paragraphIntrinsics.builder.textStyle.color
var currentShadow = paragraphIntrinsics.builder.textStyle.shadow
var currentTextDecoration = paragraphIntrinsics.builder.textStyle.textDecoration
- if (color.isSet && color != currentColor) {
+ if (color.isSpecified && color != currentColor) {
toRebuild = true
currentColor = color
}
@@ -501,7 +501,7 @@
}
private fun applyStyles(from: SpanStyle, to: SkTextStyle) {
- if (from.color != Color.Unset) {
+ if (from.color != Color.Unspecified) {
to.setColor(from.color.toArgb())
}
from.fontFamily?.let {
@@ -514,7 +514,7 @@
from.textDecoration?.let {
to.decorationStyle = it.toSkDecorationStyle(from.color)
}
- if (from.background != Color.Unset) {
+ if (from.background != Color.Unspecified) {
to.background = Paint().apply {
color = from.background.toArgb()
}
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/SpanStyleTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/SpanStyleTest.kt
index cbc9ed0..b9b56b9 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/SpanStyleTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/SpanStyleTest.kt
@@ -42,13 +42,13 @@
fun `constructor with default values`() {
val style = SpanStyle()
- assertThat(style.color).isEqualTo(Color.Unset)
+ assertThat(style.color).isEqualTo(Color.Unspecified)
assertThat(style.fontSize.isInherit).isTrue()
assertThat(style.fontWeight).isNull()
assertThat(style.fontStyle).isNull()
assertThat(style.letterSpacing.isInherit).isTrue()
assertThat(style.localeList).isNull()
- assertThat(style.background).isEqualTo(Color.Unset)
+ assertThat(style.background).isEqualTo(Color.Unspecified)
assertThat(style.textDecoration).isNull()
assertThat(style.fontFamily).isNull()
}
@@ -156,7 +156,7 @@
fun `merge with other's color is null should use this' color`() {
val style = SpanStyle(color = Color.Red)
- val newSpanStyle = style.merge(SpanStyle(color = Color.Unset))
+ val newSpanStyle = style.merge(SpanStyle(color = Color.Unspecified))
assertThat(newSpanStyle.color).isEqualTo(style.color)
}
@@ -327,7 +327,7 @@
fun `merge with other's background is null should use this' background`() {
val style = SpanStyle(background = Color.Red)
- val newSpanStyle = style.merge(SpanStyle(background = Color.Unset))
+ val newSpanStyle = style.merge(SpanStyle(background = Color.Unspecified))
assertThat(newSpanStyle.background).isEqualTo(style.background)
}
@@ -413,20 +413,20 @@
}
@Test
- fun `lerp color with a and b are Unset`() {
- val style1 = SpanStyle(color = Color.Unset)
- val style2 = SpanStyle(color = Color.Unset)
+ fun `lerp color with a and b are Unspecified`() {
+ val style1 = SpanStyle(color = Color.Unspecified)
+ val style2 = SpanStyle(color = Color.Unspecified)
val newSpanStyle = lerp(start = style1, stop = style2, fraction = 0.3f)
- assertThat(newSpanStyle.color).isEqualTo(Color.Unset)
+ assertThat(newSpanStyle.color).isEqualTo(Color.Unspecified)
}
@Test
fun `lerp color with a is set, and b is Unset`() {
val t = 0.3f
val color1 = Color.Red
- val color2 = Color.Unset
+ val color2 = Color.Unspecified
val style1 = SpanStyle(color = color1)
val style2 = SpanStyle(color = color2)
@@ -632,18 +632,18 @@
@Test
fun `lerp background with a and b are Null and t is smaller than half`() {
- val style1 = SpanStyle(background = Color.Unset)
- val style2 = SpanStyle(background = Color.Unset)
+ val style1 = SpanStyle(background = Color.Unspecified)
+ val style2 = SpanStyle(background = Color.Unspecified)
val newSpanStyle = lerp(start = style1, stop = style2, fraction = 0.1f)
- assertThat(newSpanStyle.background).isEqualTo(Color.Unset)
+ assertThat(newSpanStyle.background).isEqualTo(Color.Unspecified)
}
@Test
fun `lerp background with a is Null and b is not Null`() {
val t = 0.1f
- val color1 = Color.Unset
+ val color1 = Color.Unspecified
val style1 = SpanStyle(background = color1)
val color2 = Color.Red
val style2 = SpanStyle(background = color2)
@@ -658,11 +658,11 @@
val t = 0.1f
val color1 = Color.Red
val style1 = SpanStyle(background = color1)
- val style2 = SpanStyle(background = Color.Unset)
+ val style2 = SpanStyle(background = Color.Unspecified)
val newSpanStyle = lerp(start = style1, stop = style2, fraction = t)
- assertThat(newSpanStyle.background).isEqualTo(lerp(color1, Color.Unset, t))
+ assertThat(newSpanStyle.background).isEqualTo(lerp(color1, Color.Unspecified, t))
}
@Test
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleTest.kt
index ae6ee97..99a0210 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextStyleTest.kt
@@ -47,13 +47,13 @@
fun `constructor with default values`() {
val style = TextStyle()
- assertThat(style.color).isEqualTo(Color.Unset)
+ assertThat(style.color).isEqualTo(Color.Unspecified)
assertThat(style.fontSize.isInherit).isTrue()
assertThat(style.fontWeight).isNull()
assertThat(style.fontStyle).isNull()
assertThat(style.letterSpacing.isInherit).isTrue()
assertThat(style.localeList).isNull()
- assertThat(style.background).isEqualTo(Color.Unset)
+ assertThat(style.background).isEqualTo(Color.Unspecified)
assertThat(style.textDecoration).isNull()
assertThat(style.fontFamily).isNull()
}
@@ -161,7 +161,7 @@
fun `merge with other's color is null should use this' color`() {
val style = TextStyle(color = Color.Red)
- val newStyle = style.merge(TextStyle(color = Color.Unset))
+ val newStyle = style.merge(TextStyle(color = Color.Unspecified))
assertThat(newStyle.color).isEqualTo(style.color)
}
@@ -332,7 +332,7 @@
fun `merge with other's background is null should use this' background`() {
val style = TextStyle(background = Color.Red)
- val newStyle = style.merge(TextStyle(background = Color.Unset))
+ val newStyle = style.merge(TextStyle(background = Color.Unspecified))
assertThat(newStyle.background).isEqualTo(style.background)
}
@@ -777,24 +777,24 @@
@Test
fun `lerp background with a and b are Null and t is smaller than half`() {
- val style1 = TextStyle(background = Color.Unset)
- val style2 = TextStyle(background = Color.Unset)
+ val style1 = TextStyle(background = Color.Unspecified)
+ val style2 = TextStyle(background = Color.Unspecified)
val newStyle = lerp(start = style1, stop = style2, fraction = 0.1f)
- assertThat(newStyle.background).isEqualTo(Color.Unset)
+ assertThat(newStyle.background).isEqualTo(Color.Unspecified)
}
@Test
fun `lerp background with a is Null and b is not Null`() {
val t = 0.1f
- val style1 = TextStyle(background = Color.Unset)
+ val style1 = TextStyle(background = Color.Unspecified)
val color2 = Color.Red
val style2 = TextStyle(background = color2)
val newStyle = lerp(start = style1, stop = style2, fraction = t)
- assertThat(newStyle.background).isEqualTo(lerp(Color.Unset, color2, t))
+ assertThat(newStyle.background).isEqualTo(lerp(Color.Unspecified, color2, t))
}
@Test
@@ -802,11 +802,11 @@
val t = 0.1f
val color1 = Color.Red
val style1 = TextStyle(background = color1)
- val style2 = TextStyle(background = Color.Unset)
+ val style2 = TextStyle(background = Color.Unspecified)
val newStyle = lerp(start = style1, stop = style2, fraction = t)
- assertThat(newStyle.background).isEqualTo(lerp(color1, Color.Unset, t))
+ assertThat(newStyle.background).isEqualTo(lerp(color1, Color.Unspecified, t))
}
@Test
diff --git a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/TextUnit.kt b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/TextUnit.kt
index e6dcad2..3c7f5c2 100644
--- a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/TextUnit.kt
+++ b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/TextUnit.kt
@@ -421,7 +421,8 @@
@PublishedApi
internal fun checkArithmetic(a: TextUnit, b: TextUnit, c: TextUnit) {
- require(a.type != TextUnitType.Inherit && b.type != TextUnitType.Inherit &&
+ require(
+ a.type != TextUnitType.Inherit && b.type != TextUnitType.Inherit &&
c.type != TextUnitType.Inherit
) {
"Cannot perform operation for Inherit type."
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index be053ac..4da3e0e 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -107,7 +107,7 @@
}
public final class ComposedModifierKt {
- method public static androidx.compose.ui.Modifier composed(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
+ method public static androidx.compose.ui.Modifier composed(androidx.compose.ui.Modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> inspectorInfo, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
method public static androidx.compose.ui.Modifier materialize(androidx.compose.runtime.Composer<?>, androidx.compose.ui.Modifier modifier);
}
@@ -2124,10 +2124,35 @@
property public default Object? valueOverride;
}
+ public final class InspectableValueKt {
+ method public static inline kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> debugInspectorInfo(kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> definitions);
+ method public static kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> getNoInspectorInfo();
+ field public static final boolean DebugInspectorInfo = true;
+ }
+
public final class InspectionModeKt {
method public static androidx.compose.runtime.ProvidableAmbient<java.lang.Boolean> getInspectionMode();
}
+ public final class InspectorInfo {
+ ctor public InspectorInfo();
+ method public String? getName();
+ method public androidx.compose.ui.platform.ValueElementSequence getProperties();
+ method public Object? getValue();
+ method public void setName(String? p);
+ method public void setValue(Object? p);
+ property public final String? name;
+ property public final androidx.compose.ui.platform.ValueElementSequence properties;
+ property public final Object? value;
+ }
+
+ public abstract class InspectorValueInfo implements androidx.compose.ui.platform.InspectableValue {
+ ctor public InspectorValueInfo(kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> info);
+ property public kotlin.sequences.Sequence<androidx.compose.ui.platform.ValueElement> inspectableElements;
+ property public String? nameFallback;
+ property public Object? valueOverride;
+ }
+
public final class JvmActualsKt {
}
@@ -2142,7 +2167,7 @@
public interface TextToolbar {
method public androidx.compose.ui.platform.TextToolbarStatus getStatus();
method public void hide();
- method public void showMenu(androidx.compose.ui.geometry.Rect rect, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCopyRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onPasteRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCutRequested);
+ method public void showMenu(androidx.compose.ui.geometry.Rect rect, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCopyRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onPasteRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCutRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onSelectAllRequested);
property public abstract androidx.compose.ui.platform.TextToolbarStatus status;
}
@@ -2169,6 +2194,12 @@
property public final Object? value;
}
+ public final class ValueElementSequence implements kotlin.sequences.Sequence<androidx.compose.ui.platform.ValueElement> {
+ ctor public ValueElementSequence();
+ method public java.util.Iterator<androidx.compose.ui.platform.ValueElement> iterator();
+ method public operator void set(String name, Object? value);
+ }
+
public final class WrapperKt {
method public static androidx.compose.runtime.Composition setContent(androidx.activity.ComponentActivity, optional androidx.compose.runtime.Recomposer recomposer, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.runtime.Composition setContent(android.view.ViewGroup, androidx.compose.runtime.Recomposer recomposer, optional androidx.compose.runtime.CompositionReference? parentComposition, kotlin.jvm.functions.Function0<kotlin.Unit> content);
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index be053ac..4da3e0e 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -107,7 +107,7 @@
}
public final class ComposedModifierKt {
- method public static androidx.compose.ui.Modifier composed(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
+ method public static androidx.compose.ui.Modifier composed(androidx.compose.ui.Modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> inspectorInfo, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
method public static androidx.compose.ui.Modifier materialize(androidx.compose.runtime.Composer<?>, androidx.compose.ui.Modifier modifier);
}
@@ -2124,10 +2124,35 @@
property public default Object? valueOverride;
}
+ public final class InspectableValueKt {
+ method public static inline kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> debugInspectorInfo(kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> definitions);
+ method public static kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> getNoInspectorInfo();
+ field public static final boolean DebugInspectorInfo = true;
+ }
+
public final class InspectionModeKt {
method public static androidx.compose.runtime.ProvidableAmbient<java.lang.Boolean> getInspectionMode();
}
+ public final class InspectorInfo {
+ ctor public InspectorInfo();
+ method public String? getName();
+ method public androidx.compose.ui.platform.ValueElementSequence getProperties();
+ method public Object? getValue();
+ method public void setName(String? p);
+ method public void setValue(Object? p);
+ property public final String? name;
+ property public final androidx.compose.ui.platform.ValueElementSequence properties;
+ property public final Object? value;
+ }
+
+ public abstract class InspectorValueInfo implements androidx.compose.ui.platform.InspectableValue {
+ ctor public InspectorValueInfo(kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> info);
+ property public kotlin.sequences.Sequence<androidx.compose.ui.platform.ValueElement> inspectableElements;
+ property public String? nameFallback;
+ property public Object? valueOverride;
+ }
+
public final class JvmActualsKt {
}
@@ -2142,7 +2167,7 @@
public interface TextToolbar {
method public androidx.compose.ui.platform.TextToolbarStatus getStatus();
method public void hide();
- method public void showMenu(androidx.compose.ui.geometry.Rect rect, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCopyRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onPasteRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCutRequested);
+ method public void showMenu(androidx.compose.ui.geometry.Rect rect, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCopyRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onPasteRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCutRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onSelectAllRequested);
property public abstract androidx.compose.ui.platform.TextToolbarStatus status;
}
@@ -2169,6 +2194,12 @@
property public final Object? value;
}
+ public final class ValueElementSequence implements kotlin.sequences.Sequence<androidx.compose.ui.platform.ValueElement> {
+ ctor public ValueElementSequence();
+ method public java.util.Iterator<androidx.compose.ui.platform.ValueElement> iterator();
+ method public operator void set(String name, Object? value);
+ }
+
public final class WrapperKt {
method public static androidx.compose.runtime.Composition setContent(androidx.activity.ComponentActivity, optional androidx.compose.runtime.Recomposer recomposer, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.runtime.Composition setContent(android.view.ViewGroup, androidx.compose.runtime.Recomposer recomposer, optional androidx.compose.runtime.CompositionReference? parentComposition, kotlin.jvm.functions.Function0<kotlin.Unit> content);
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index c54a165..396691e 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -107,7 +107,7 @@
}
public final class ComposedModifierKt {
- method public static androidx.compose.ui.Modifier composed(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
+ method public static androidx.compose.ui.Modifier composed(androidx.compose.ui.Modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> inspectorInfo, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
method public static androidx.compose.ui.Modifier materialize(androidx.compose.runtime.Composer<?>, androidx.compose.ui.Modifier modifier);
}
@@ -2201,10 +2201,35 @@
property public default Object? valueOverride;
}
+ public final class InspectableValueKt {
+ method public static inline kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> debugInspectorInfo(kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> definitions);
+ method public static kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> getNoInspectorInfo();
+ field public static final boolean DebugInspectorInfo = true;
+ }
+
public final class InspectionModeKt {
method public static androidx.compose.runtime.ProvidableAmbient<java.lang.Boolean> getInspectionMode();
}
+ public final class InspectorInfo {
+ ctor public InspectorInfo();
+ method public String? getName();
+ method public androidx.compose.ui.platform.ValueElementSequence getProperties();
+ method public Object? getValue();
+ method public void setName(String? p);
+ method public void setValue(Object? p);
+ property public final String? name;
+ property public final androidx.compose.ui.platform.ValueElementSequence properties;
+ property public final Object? value;
+ }
+
+ public abstract class InspectorValueInfo implements androidx.compose.ui.platform.InspectableValue {
+ ctor public InspectorValueInfo(kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> info);
+ property public kotlin.sequences.Sequence<androidx.compose.ui.platform.ValueElement> inspectableElements;
+ property public String? nameFallback;
+ property public Object? valueOverride;
+ }
+
public final class JvmActualsKt {
}
@@ -2219,7 +2244,7 @@
public interface TextToolbar {
method public androidx.compose.ui.platform.TextToolbarStatus getStatus();
method public void hide();
- method public void showMenu(androidx.compose.ui.geometry.Rect rect, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCopyRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onPasteRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCutRequested);
+ method public void showMenu(androidx.compose.ui.geometry.Rect rect, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCopyRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onPasteRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCutRequested, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onSelectAllRequested);
property public abstract androidx.compose.ui.platform.TextToolbarStatus status;
}
@@ -2246,6 +2271,12 @@
property public final Object? value;
}
+ public final class ValueElementSequence implements kotlin.sequences.Sequence<androidx.compose.ui.platform.ValueElement> {
+ ctor public ValueElementSequence();
+ method public java.util.Iterator<androidx.compose.ui.platform.ValueElement> iterator();
+ method public operator void set(String name, Object? value);
+ }
+
public final class WrapperKt {
method public static androidx.compose.runtime.Composition setContent(androidx.activity.ComponentActivity, optional androidx.compose.runtime.Recomposer recomposer, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.runtime.Composition setContent(android.view.ViewGroup, androidx.compose.runtime.Recomposer recomposer, optional androidx.compose.runtime.CompositionReference? parentComposition, kotlin.jvm.functions.Function0<kotlin.Unit> content);
diff --git a/compose/ui/ui/build.gradle b/compose/ui/ui/build.gradle
index cb79921..5898f25 100644
--- a/compose/ui/ui/build.gradle
+++ b/compose/ui/ui/build.gradle
@@ -118,6 +118,7 @@
}
desktopTest.dependencies {
+ implementation project(':ui:ui-test')
implementation(TRUTH)
implementation(JUNIT)
implementation(MOCKITO_CORE)
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/InspectorInfoInComposedModifierSamples.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/InspectorInfoInComposedModifierSamples.kt
new file mode 100644
index 0000000..aebb89e
--- /dev/null
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/InspectorInfoInComposedModifierSamples.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.compose.ui.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.unit.Dp
+
+@Composable
+@Sampled
+fun InspectorInfoInComposedModifierSample() {
+
+ // let's create you own custom stateful modifier
+ fun Modifier.myColorModifier(color: Color) = composed (
+ // pass inspector information for debug
+ inspectorInfo = debugInspectorInfo {
+ // name should match the name of the modifier
+ name = "myColorModifier"
+ // specify a single argument as the value when the argument name is irrelevant
+ value = color
+ },
+ // pass your modifier implementation that resolved per modified element
+ factory = {
+ // add your modifier implementation here
+ Modifier
+ }
+ )
+}
+
+@Composable
+@Sampled
+fun InspectorInfoInComposedModifierWithArgumentsSample() {
+
+ // let's create you own custom stateful modifier with multiple arguments
+ fun Modifier.myModifier(width: Dp, height: Dp, color: Color) = composed (
+ // pass inspector information for debug
+ inspectorInfo = debugInspectorInfo {
+ // name should match the name of the modifier
+ name = "myModifier"
+ // add name and value of each argument
+ properties["width"] = width
+ properties["height"] = height
+ properties["color"] = color
+ },
+ // pass your modifier implementation that resolved per modified element
+ factory = {
+ // add your modifier implementation here
+ Modifier
+ }
+ )
+}
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/OnSizeChangedSamples.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/OnSizeChangedSamples.kt
index c737f36d..e0d0b81 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/OnSizeChangedSamples.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/OnSizeChangedSamples.kt
@@ -27,7 +27,10 @@
fun OnSizeChangedSample(name: String) {
// Use onSizeChanged() for diagnostics. Use Layout or SubcomposeLayout if you want
// to use the size of one component to affect the size of another component.
- Text("Hello $name", Modifier.onSizeChanged { size ->
- println("The size of the Text in pixels is $size")
- })
+ Text(
+ "Hello $name",
+ Modifier.onSizeChanged { size ->
+ println("The size of the Text in pixels is $size")
+ }
+ )
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
index 115c3b7..5fa8eb6 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
@@ -30,9 +30,9 @@
import android.widget.FrameLayout
import androidx.activity.ComponentActivity
import androidx.compose.foundation.BaseTextField
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Text
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.selection.toggleable
import androidx.compose.runtime.Recomposer
@@ -47,6 +47,8 @@
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.SemanticsActions
import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.textSelectionRange
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextRange
@@ -55,13 +57,14 @@
import androidx.core.view.ViewCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import androidx.ui.test.SemanticsMatcher
import androidx.ui.test.assert
-import androidx.ui.test.createAndroidComposeRule
import androidx.ui.test.assertIsOff
import androidx.ui.test.assertIsOn
import androidx.ui.test.assertTextEquals
+import androidx.ui.test.createAndroidComposeRule
import androidx.ui.test.onNodeWithTag
import androidx.ui.test.performClick
import androidx.ui.test.performSemanticsAction
@@ -85,11 +88,15 @@
import org.mockito.ArgumentMatcher
import org.mockito.ArgumentMatchers.any
import org.mockito.internal.matchers.apachecommons.ReflectionEquals
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
@MediumTest
@RunWith(JUnit4::class)
-@OptIn(ExperimentalFoundationApi::class)
-@ExperimentalLayoutNodeApi
+@OptIn(
+ ExperimentalFoundationApi::class,
+ ExperimentalLayoutNodeApi::class
+)
class AndroidAccessibilityTest {
@get:Rule
val rule = createAndroidComposeRule<ComponentActivity>(false, true)
@@ -102,6 +109,8 @@
private val argument = ArgumentCaptor.forClass(AccessibilityEvent::class.java)
private var isTextFieldVisible by mutableStateOf(true)
+ private var textFieldSelectionOneLatch = CountDownLatch(1)
+ private var textFieldSelectionZeroLatch = CountDownLatch(1)
companion object {
private const val ToggleableTag = "toggleable"
@@ -140,7 +149,18 @@
)
if (isTextFieldVisible) {
BaseTextField(
- modifier = Modifier.testTag(TextFieldTag),
+ modifier = Modifier
+ .semantics {
+ // Make sure this block will be executed when selection changes.
+ this.textSelectionRange = value.selection
+ if (value.selection == TextRange(1)) {
+ textFieldSelectionOneLatch.countDown()
+ }
+ if (value.selection == TextRange(0)) {
+ textFieldSelectionZeroLatch.countDown()
+ }
+ }
+ .testTag(TextFieldTag),
value = value,
onValueChange = { value = it },
onTextLayout = { textLayoutResult = it }
@@ -252,8 +272,12 @@
argument.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1)
argument.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 1)
rule.runOnUiThread {
+ textFieldSelectionOneLatch = CountDownLatch(1)
provider.performAction(textFieldNode.id, ACTION_SET_SELECTION, argument)
}
+ if (!textFieldSelectionOneLatch.await(1, TimeUnit.SECONDS)) {
+ throw AssertionError("Failed to wait for text selection change.")
+ }
rule.onNodeWithTag(TextFieldTag)
.assert(
SemanticsMatcher.expectValue(
@@ -271,12 +295,16 @@
false
)
rule.runOnUiThread {
+ textFieldSelectionZeroLatch = CountDownLatch(1)
provider.performAction(
textFieldNode.id,
ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
argument
)
}
+ if (!textFieldSelectionZeroLatch.await(1, TimeUnit.SECONDS)) {
+ throw AssertionError("Failed to wait for text selection change.")
+ }
rule.onNodeWithTag(TextFieldTag)
.assert(
SemanticsMatcher.expectValue(
@@ -287,6 +315,7 @@
}
@Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
fun testAddExtraDataToAccessibilityNodeInfo() {
val textFieldNode = rule.onNodeWithTag(TextFieldTag)
.fetchSemanticsNode("couldn't find node with tag $TextFieldTag")
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidComposeViewAccessibilityDelegateCompatTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidComposeViewAccessibilityDelegateCompatTest.kt
index 875f781..e868612f 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidComposeViewAccessibilityDelegateCompatTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidComposeViewAccessibilityDelegateCompatTest.kt
@@ -134,7 +134,8 @@
}
Build.VERSION.SDK_INT >= 19 -> {
info.extras.getCharSequence(
- "androidx.view.accessibility.AccessibilityNodeInfoCompat.STATE_DESCRIPTION_KEY")
+ "androidx.view.accessibility.AccessibilityNodeInfoCompat.STATE_DESCRIPTION_KEY"
+ )
}
else -> {
null
@@ -231,10 +232,10 @@
)
assertEquals(
AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_CHARACTER or
- AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_WORD or
- AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PARAGRAPH or
- AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_LINE or
- AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PAGE,
+ AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_WORD or
+ AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PARAGRAPH or
+ AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_LINE or
+ AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PAGE,
info.movementGranularities
)
if (Build.VERSION.SDK_INT >= 26) {
@@ -272,7 +273,7 @@
argThat(
ArgumentMatcher {
it.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED &&
- it.contentChangeTypes == AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE
+ it.contentChangeTypes == AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE
}
)
)
@@ -297,7 +298,7 @@
argThat(
ArgumentMatcher {
it.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED &&
- it.contentChangeTypes == AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE
+ it.contentChangeTypes == AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE
}
)
)
@@ -306,12 +307,12 @@
argThat(
ArgumentMatcher {
it.eventType == AccessibilityEvent.TYPE_VIEW_SCROLLED && it.scrollY == 2 &&
- it.maxScrollY == 5 &&
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- it.scrollDeltaY == 2
- } else {
- true
- }
+ it.maxScrollY == 5 &&
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ it.scrollDeltaY == 2
+ } else {
+ true
+ }
}
)
)
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
index 6620cea..62d761c 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
@@ -29,6 +29,7 @@
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.annotation.RequiresApi
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
@@ -2814,6 +2815,38 @@
validateSquareColors(outerColor = Color.Blue, innerColor = Color.Blue, size = 10)
}
+ @Test
+ fun remeasureOnParentDataChanged() {
+ var measuredLatch = CountDownLatch(1)
+ var size = 10
+ var sizeState by mutableStateOf(size)
+
+ class ParentInt(val x: Int) : ParentDataModifier {
+ override fun Density.modifyParentData(parentData: Any?): Any? = x
+ }
+ activityTestRule.runOnUiThread {
+ activity.setContent {
+ Layout({ Box(ParentInt(sizeState)) }) { measurables, constraints ->
+ val boxSize = measurables[0].parentData as Int
+ assertEquals(size, boxSize)
+ val placeable = measurables[0].measure(constraints)
+ measuredLatch.countDown()
+ layout(boxSize, boxSize) {
+ placeable.place(0, 0)
+ }
+ }
+ }
+ }
+
+ assertTrue(measuredLatch.await(1, TimeUnit.SECONDS))
+ activityTestRule.runOnUiThread {
+ size = 20
+ sizeState = 20
+ measuredLatch = CountDownLatch(1)
+ }
+ assertTrue(measuredLatch.await(1, TimeUnit.SECONDS))
+ }
+
private fun composeSquares(model: SquareModel) {
activityTestRule.runOnUiThreadIR {
activity.setContent {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/DrawReorderingTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/DrawReorderingTest.kt
index 0f2e2f8..09c67f0 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/DrawReorderingTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/DrawReorderingTest.kt
@@ -80,19 +80,21 @@
fun testDrawingOrderWhenWePlaceItemsInTheNaturalOrder() {
rule.runOnUiThread {
activity.setContent {
- Layout(children = {
- FixedSize(
- 10,
- PaddingModifier(10)
- .background(Color.White)
- )
- FixedSize(
- 30,
- Modifier.drawLayer()
- .background(Color.Red)
- .drawLatchModifier()
- )
- }) { measurables, _ ->
+ Layout(
+ children = {
+ FixedSize(
+ 10,
+ PaddingModifier(10)
+ .background(Color.White)
+ )
+ FixedSize(
+ 30,
+ Modifier.drawLayer()
+ .background(Color.Red)
+ .drawLatchModifier()
+ )
+ }
+ ) { measurables, _ ->
val newConstraints = Constraints.fixed(30, 30)
val placeables = measurables.map { m ->
m.measure(newConstraints)
@@ -118,19 +120,21 @@
fun testDrawingOrderWhenWePlaceItemsInTheReverseOrder() {
rule.runOnUiThread {
activity.setContent {
- Layout(children = {
- FixedSize(
- 10,
- PaddingModifier(10)
- .background(Color.White)
- )
- FixedSize(
- 30,
- Modifier.drawLayer()
- .background(Color.Red)
- .drawLatchModifier()
- )
- }) { measurables, _ ->
+ Layout(
+ children = {
+ FixedSize(
+ 10,
+ PaddingModifier(10)
+ .background(Color.White)
+ )
+ FixedSize(
+ 30,
+ Modifier.drawLayer()
+ .background(Color.Red)
+ .drawLatchModifier()
+ )
+ }
+ ) { measurables, _ ->
val newConstraints = Constraints.fixed(30, 30)
val placeables = measurables.map { m ->
m.measure(newConstraints)
@@ -156,20 +160,22 @@
fun testDrawingOrderIsOverriddenWithZIndexWhenWePlaceItemsInTheReverseOrder() {
rule.runOnUiThread {
activity.setContent {
- Layout(children = {
- FixedSize(
- 10,
- PaddingModifier(10)
- .background(Color.White)
- )
- FixedSize(
- 30,
- Modifier.drawLayer()
- .background(Color.Red)
- .zIndex(1f)
- .drawLatchModifier()
- )
- }) { measurables, _ ->
+ Layout(
+ children = {
+ FixedSize(
+ 10,
+ PaddingModifier(10)
+ .background(Color.White)
+ )
+ FixedSize(
+ 30,
+ Modifier.drawLayer()
+ .background(Color.Red)
+ .zIndex(1f)
+ .drawLatchModifier()
+ )
+ }
+ ) { measurables, _ ->
val newConstraints = Constraints.fixed(30, 30)
val placeables = measurables.map { m ->
m.measure(newConstraints)
@@ -195,25 +201,27 @@
fun testCustomDrawingOrderForThreeItems() {
rule.runOnUiThread {
activity.setContent {
- Layout(children = {
- FixedSize(
- 30,
- Modifier.drawLayer()
- .background(Color.Red)
- .drawLatchModifier()
- )
- FixedSize(
- 10,
- PaddingModifier(10)
- .background(Color.White)
- )
- FixedSize(
- 30,
- Modifier.drawLayer()
- .background(Color.Blue)
- .drawLatchModifier()
- )
- }) { measurables, _ ->
+ Layout(
+ children = {
+ FixedSize(
+ 30,
+ Modifier.drawLayer()
+ .background(Color.Red)
+ .drawLatchModifier()
+ )
+ FixedSize(
+ 10,
+ PaddingModifier(10)
+ .background(Color.White)
+ )
+ FixedSize(
+ 30,
+ Modifier.drawLayer()
+ .background(Color.Blue)
+ .drawLatchModifier()
+ )
+ }
+ ) { measurables, _ ->
val newConstraints = Constraints.fixed(30, 30)
val placeables = measurables.map { m ->
m.measure(newConstraints)
@@ -240,9 +248,11 @@
val latch = CountDownLatch(1)
rule.runOnUiThread {
activity.setContent {
- Layout(children = {
- FixedSize(30)
- }) { measurables, constraints ->
+ Layout(
+ children = {
+ FixedSize(30)
+ }
+ ) { measurables, constraints ->
val placeables = measurables.first().measure(constraints)
layout(30, 30) {
placeables.place(0, 0)
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/InvalidatingNotPlacedChildTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/InvalidatingNotPlacedChildTest.kt
index 1dc4ed5..1579f71 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/InvalidatingNotPlacedChildTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/InvalidatingNotPlacedChildTest.kt
@@ -16,6 +16,7 @@
package androidx.compose.ui.draw
+import android.os.Build
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
@@ -32,11 +33,11 @@
import androidx.compose.ui.layout.assertCenterPixelColor
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp
+import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import androidx.ui.test.captureToBitmap
import androidx.ui.test.createComposeRule
import androidx.ui.test.onNodeWithTag
-import androidx.ui.test.runOnIdle
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -50,6 +51,7 @@
val composeTestRule = createComposeRule()
@Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
fun childIsDisplayedWhenItWasNotPlacedOriginallyButPlacedLater() {
val shouldPlace = mutableStateOf(false)
composeTestRule.setContent {
@@ -80,6 +82,7 @@
}
@Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
fun grandChildIsDisplayedWhenItWasNotPlacedOriginallyButPlacedLater() {
val shouldPlace = mutableStateOf(false)
composeTestRule.setContent {
@@ -112,6 +115,7 @@
}
@Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
fun grandChildIsDisplayedCorrectlyWhenTheColorWasChangedWhileNotPlaced() {
val shouldPlace = mutableStateOf(false)
var color by mutableStateOf(Color.Gray)
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusManagerAmbientTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusManagerAmbientTest.kt
index 109f154b..43bb8e0 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusManagerAmbientTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusManagerAmbientTest.kt
@@ -49,10 +49,11 @@
rule.setFocusableContent {
focusManager = FocusManagerAmbient.current
focusRequester = FocusRequester()
- Box(modifier = Modifier
- .focusRequester(focusRequester)
- .focusObserver { focusState = it }
- .focus()
+ Box(
+ modifier = Modifier
+ .focusRequester(focusRequester)
+ .focusObserver { focusState = it }
+ .focus()
)
}
rule.runOnIdle {
@@ -78,16 +79,21 @@
rule.setFocusableContent {
focusManager = FocusManagerAmbient.current
focusRequester = FocusRequester()
- Box(modifier = Modifier
- .focusObserver { grandparentFocusState = it }
- .focus()) {
- Box(modifier = Modifier
- .focusObserver { parentFocusState = it }
- .focus()) {
- Box(modifier = Modifier
- .focusRequester(focusRequester)
- .focusObserver { focusState = it }
+ Box(
+ modifier = Modifier
+ .focusObserver { grandparentFocusState = it }
+ .focus()
+ ) {
+ Box(
+ modifier = Modifier
+ .focusObserver { parentFocusState = it }
.focus()
+ ) {
+ Box(
+ modifier = Modifier
+ .focusRequester(focusRequester)
+ .focusObserver { focusState = it }
+ .focus()
)
}
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
index b9f6f47..98333c9 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
@@ -529,33 +529,43 @@
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(pif2)
- assertThat(log1[1].pointerEvent).isEqualTo(pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 1f) }
- ))
+ assertThat(log1[1].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 1f) }
+ )
+ )
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(pif3)
- assertThat(log1[2].pointerEvent).isEqualTo(pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 2f) }
- ))
+ assertThat(log1[2].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 2f) }
+ )
+ )
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[3].pointerInputFilter).isEqualTo(pif3)
- assertThat(log1[3].pointerEvent).isEqualTo(pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 3f) }
- ))
+ assertThat(log1[3].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 3f) }
+ )
+ )
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[4].pointerInputFilter).isEqualTo(pif2)
- assertThat(log1[4].pointerEvent).isEqualTo(pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 4f) }
- ))
+ assertThat(log1[4].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 4f) }
+ )
+ )
assertThat(log1[4].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[5].pointerInputFilter).isEqualTo(pif1)
- assertThat(log1[5].pointerEvent).isEqualTo(pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 5f) }
- ))
+ assertThat(log1[5].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 5f) }
+ )
+ )
assertThat(log1[5].pass).isEqualTo(PointerEventPass.Main)
assertThat(result.changes.values.first())
@@ -653,21 +663,27 @@
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(pif2)
- assertThat(log1[1].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 1f) }
- ))
+ assertThat(log1[1].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 1f) }
+ )
+ )
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(pif2)
- assertThat(log1[2].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 2f) }
- ))
+ assertThat(log1[2].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 2f) }
+ )
+ )
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[3].pointerInputFilter).isEqualTo(pif1)
- assertThat(log1[3].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 3f) }
- ))
+ assertThat(log1[3].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 3f) }
+ )
+ )
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Main)
assertThat(log2[0].pointerInputFilter).isEqualTo(pif3)
@@ -675,21 +691,27 @@
assertThat(log2[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log2[1].pointerInputFilter).isEqualTo(pif4)
- assertThat(log2[1].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, -1f) }
- ))
+ assertThat(log2[1].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, -1f) }
+ )
+ )
assertThat(log2[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log2[2].pointerInputFilter).isEqualTo(pif4)
- assertThat(log2[2].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, -2f) }
- ))
+ assertThat(log2[2].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, -2f) }
+ )
+ )
assertThat(log2[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log2[3].pointerInputFilter).isEqualTo(pif3)
- assertThat(log2[3].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, -3f) }
- ))
+ assertThat(log2[3].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, -3f) }
+ )
+ )
assertThat(log2[3].pass).isEqualTo(PointerEventPass.Main)
assertThat(result.changes).hasSize(2)
@@ -783,34 +805,44 @@
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[1].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 1f) }
- ))
+ assertThat(log1[1].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 1f) }
+ )
+ )
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[2].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 2f) }
- ))
+ assertThat(log1[2].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 2f) }
+ )
+ )
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[3].pointerInputFilter).isEqualTo(child2)
- assertThat(log1[3].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, 1f) }
- ))
+ assertThat(log1[3].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, 1f) }
+ )
+ )
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[4].pointerInputFilter).isEqualTo(child2)
- assertThat(log1[4].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, 4f) }
- ))
+ assertThat(log1[4].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, 4f) }
+ )
+ )
assertThat(log1[4].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[5].pointerInputFilter).isEqualTo(parent)
- assertThat(log1[5].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 20f) },
- expectedEvent2.apply { consumePositionChange(0f, 40f) }
- ))
+ assertThat(log1[5].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 20f) },
+ expectedEvent2.apply { consumePositionChange(0f, 40f) }
+ )
+ )
assertThat(log1[5].pass).isEqualTo(PointerEventPass.Main)
assertThat(result.changes).hasSize(2)
@@ -883,24 +915,30 @@
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(child2)
- assertThat(log1[1].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 1f) },
- expectedEvent2.apply { consumePositionChange(0f, 1f) }
- ))
+ assertThat(log1[1].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 1f) },
+ expectedEvent2.apply { consumePositionChange(0f, 1f) }
+ )
+ )
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(child2)
- assertThat(log1[2].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 2f) },
- expectedEvent2.apply { consumePositionChange(0f, 2f) }
- ))
+ assertThat(log1[2].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 2f) },
+ expectedEvent2.apply { consumePositionChange(0f, 2f) }
+ )
+ )
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[3].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[3].pointerEvent).isEqualTo(pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 3f) },
- expectedEvent2.apply { consumePositionChange(0f, 3f) }
- ))
+ assertThat(log1[3].pointerEvent).isEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 3f) },
+ expectedEvent2.apply { consumePositionChange(0f, 3f) }
+ )
+ )
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Main)
assertThat(result.changes).hasSize(2)
@@ -1957,17 +1995,20 @@
assertThat(areEqual(hitPathTracker.root, expectedRoot)).isTrue()
- val log1 = log.getOnCancelLog().filter { it.pointerInputFilter == leaf1 ||
- it.pointerInputFilter == middle1 ||
- it.pointerInputFilter == root
+ val log1 = log.getOnCancelLog().filter {
+ it.pointerInputFilter == leaf1 ||
+ it.pointerInputFilter == middle1 ||
+ it.pointerInputFilter == root
}
- val log2 = log.getOnCancelLog().filter { it.pointerInputFilter == leaf2 ||
+ val log2 = log.getOnCancelLog().filter {
+ it.pointerInputFilter == leaf2 ||
it.pointerInputFilter == middle2 ||
it.pointerInputFilter == root
}
- val log3 = log.getOnCancelLog().filter { it.pointerInputFilter == leaf3 ||
+ val log3 = log.getOnCancelLog().filter {
+ it.pointerInputFilter == leaf3 ||
it.pointerInputFilter == middle3 ||
it.pointerInputFilter == root
}
@@ -3639,7 +3680,8 @@
val dispatchingPif = PointerInputFilterMock(
log,
- initHandler = { dispatcher = it })
+ initHandler = { dispatcher = it }
+ )
val parentPif = PointerInputFilterMock(
log,
onCustomEvent = { _, pointerEventPass ->
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterTest.kt
index eedbc858..7f47345 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterTest.kt
@@ -4426,7 +4426,7 @@
)
internal typealias PointerEventHandler =
- (PointerEvent, PointerEventPass, IntSize) -> List<PointerInputChange>
+ (PointerEvent, PointerEventPass, IntSize) -> List<PointerInputChange>
private fun PointerEventHandler.invokeOverAllPasses(
pointerEvent: PointerEvent,
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnSizeChangedTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnSizeChangedTest.kt
index 8b5ecb7..a0311df 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnSizeChangedTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnSizeChangedTest.kt
@@ -64,10 +64,12 @@
rule.runOnUiThread {
activity.setContent {
with (DensityAmbient.current) {
- Box(Modifier.padding(10.toDp()).onSizeChanged {
- changedSize = it
- latch.countDown()
- }) {
+ Box(
+ Modifier.padding(10.toDp()).onSizeChanged {
+ changedSize = it
+ latch.countDown()
+ }
+ ) {
Box(Modifier.size(sizePx.toDp()))
}
}
@@ -97,10 +99,12 @@
rule.runOnUiThread {
activity.setContent {
with (DensityAmbient.current) {
- Box(Modifier.padding(sizePx.toDp()).onSizeChanged {
- changedSize = it
- latch.countDown()
- }) {
+ Box(
+ Modifier.padding(sizePx.toDp()).onSizeChanged {
+ changedSize = it
+ latch.countDown()
+ }
+ ) {
Box(Modifier.size(10.toDp()))
}
}
@@ -128,10 +132,12 @@
rule.runOnUiThread {
activity.setContent {
with (DensityAmbient.current) {
- Box(Modifier.padding(10.toDp()).onSizeChanged {
- changedSize = it
- latch.countDown()
- }) {
+ Box(
+ Modifier.padding(10.toDp()).onSizeChanged {
+ changedSize = it
+ latch.countDown()
+ }
+ ) {
Box(Modifier.size(sizePx.toDp()))
}
}
@@ -168,10 +174,12 @@
changedSize2 = it
latch2.countDown()
} else Modifier
- Box(Modifier.padding(10.toDp()).onSizeChanged {
- changedSize1 = it
- latch1.countDown()
- }.then(mod)) {
+ Box(
+ Modifier.padding(10.toDp()).onSizeChanged {
+ changedSize1 = it
+ latch1.countDown()
+ }.then(mod)
+ ) {
Box(Modifier.size(10.toDp()))
}
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt
index 83e6014..1a6d80c 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt
@@ -162,7 +162,7 @@
measuresCount++
val placeable = subcompose(Unit) {
recompositionsCount1++
- Box(Modifier.size(20.dp)) {
+ NonInlineBox(Modifier.size(20.dp)) {
model.value // model read
recompositionsCount2++
}
@@ -183,6 +183,11 @@
}
}
+ @Composable
+ private fun NonInlineBox(modifier: Modifier, children: @Composable () -> Unit) {
+ Box(modifier = modifier) { children() }
+ }
+
@Test
fun recompositionOfTheFirstSlotDoestAffectTheSecond() {
val model = mutableStateOf(0)
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/AndroidViewCompatTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/AndroidViewCompatTest.kt
index 5a902cd..4fe6689 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/AndroidViewCompatTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/AndroidViewCompatTest.kt
@@ -482,8 +482,9 @@
Box(Modifier.padding(paddingDp)) {
AndroidView(::FrameLayout) {
it.setContent {
- Box(Modifier.padding(paddingDp)
- .onGloballyPositioned { coordinates = it }
+ Box(
+ Modifier.padding(paddingDp)
+ .onGloballyPositioned { coordinates = it }
)
}
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt
index 0baa5d6..7f4fff1 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt
@@ -94,7 +94,7 @@
@Test
fun toggleFlagOnDialog() {
var properties: AndroidDialogProperties?
- by mutableStateOf(AndroidDialogProperties(SecureFlagPolicy.SecureOff))
+ by mutableStateOf(AndroidDialogProperties(SecureFlagPolicy.SecureOff))
rule.setContent {
TestDialog(properties)
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt
index 72599a0..f970558 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt
@@ -99,7 +99,7 @@
@Test
fun toggleFlagOnPopup() {
var properties: AndroidPopupProperties?
- by mutableStateOf(AndroidPopupProperties(SecureFlagPolicy.SecureOff))
+ by mutableStateOf(AndroidPopupProperties(SecureFlagPolicy.SecureOff))
rule.setContent {
TestPopup(properties)
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTestUtils.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTestUtils.kt
index 842f0e0..f0c2cd2 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTestUtils.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTestUtils.kt
@@ -61,7 +61,9 @@
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- window.setFlags(WindowManager.LayoutParams.FLAG_SECURE,
- WindowManager.LayoutParams.FLAG_SECURE)
+ window.setFlags(
+ WindowManager.LayoutParams.FLAG_SECURE,
+ WindowManager.LayoutParams.FLAG_SECURE
+ )
}
}
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.kt
index a3473a9..026f064 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.kt
@@ -346,7 +346,8 @@
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !info.text.isNullOrEmpty() &&
- semanticsNode.config.contains(SemanticsActions.GetTextLayoutResult)) {
+ semanticsNode.config.contains(SemanticsActions.GetTextLayoutResult)
+ ) {
info.unwrap().availableExtraData = listOf(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)
}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidTextToolbar.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidTextToolbar.kt
index 6cf2ba6..209ed0d 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidTextToolbar.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidTextToolbar.kt
@@ -35,17 +35,18 @@
rect: Rect,
onCopyRequested: ActionCallback?,
onPasteRequested: ActionCallback?,
- onCutRequested: ActionCallback?
+ onCutRequested: ActionCallback?,
+ onSelectAllRequested: ActionCallback?
) {
textToolbarStatus = TextToolbarStatus.Shown
if (Build.VERSION.SDK_INT >= 23) {
val actionModeCallback =
FloatingTextActionModeCallback(
TextActionModeCallback(
- view = view,
onCopyRequested = onCopyRequested,
onCutRequested = onCutRequested,
- onPasteRequested = onPasteRequested
+ onPasteRequested = onPasteRequested,
+ onSelectAllRequested = onSelectAllRequested
)
)
actionModeCallback.setRect(rect)
@@ -57,10 +58,10 @@
val actionModeCallback =
PrimaryTextActionModeCallback(
TextActionModeCallback(
- view = view,
onCopyRequested = onCopyRequested,
onPasteRequested = onPasteRequested,
- onCutRequested = onCutRequested
+ onCutRequested = onCutRequested,
+ onSelectAllRequested = onSelectAllRequested
)
)
actionMode = view.startActionMode(actionModeCallback)
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/actionmodecallback/TextActionModeCallback.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/actionmodecallback/TextActionModeCallback.kt
index 13a8bb4..b57eb8a 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/actionmodecallback/TextActionModeCallback.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/actionmodecallback/TextActionModeCallback.kt
@@ -19,18 +19,18 @@
import android.view.ActionMode
import android.view.Menu
import android.view.MenuItem
-import android.view.View
import androidx.compose.ui.platform.ActionCallback
internal const val MENU_ITEM_COPY = 0
internal const val MENU_ITEM_PASTE = 1
internal const val MENU_ITEM_CUT = 2
+internal const val MENU_ITEM_SELECT_ALL = 3
internal class TextActionModeCallback(
- private val view: View,
private val onCopyRequested: ActionCallback? = null,
private val onPasteRequested: ActionCallback? = null,
- private val onCutRequested: ActionCallback? = null
+ private val onCutRequested: ActionCallback? = null,
+ private val onSelectAllRequested: ActionCallback? = null
) : ActionMode.Callback {
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
requireNotNull(menu)
@@ -50,6 +50,11 @@
menu.add(0, MENU_ITEM_CUT, 2, android.R.string.cut)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
}
+
+ onSelectAllRequested?.let {
+ menu.add(0, MENU_ITEM_SELECT_ALL, 3, android.R.string.selectAll)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
+ }
return true
}
@@ -62,6 +67,7 @@
MENU_ITEM_COPY -> onCopyRequested?.invoke()
MENU_ITEM_PASTE -> onPasteRequested?.invoke()
MENU_ITEM_CUT -> onCutRequested?.invoke()
+ MENU_ITEM_SELECT_ALL -> onSelectAllRequested?.invoke()
else -> return false
}
mode?.finish()
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.kt
index 082bff6..1920f11 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.kt
@@ -165,13 +165,16 @@
} else {
WindowManager.LayoutParams.FLAG_SECURE.inv()
},
- WindowManager.LayoutParams.FLAG_SECURE)
+ WindowManager.LayoutParams.FLAG_SECURE
+ )
}
fun setProperties(properties: DialogProperties?) {
if (properties != null && properties is AndroidDialogProperties) {
- setSecureFlagEnabled(properties.securePolicy
- .shouldApplySecureFlag(composeView.isFlagSecureEnabled()))
+ setSecureFlagEnabled(
+ properties.securePolicy
+ .shouldApplySecureFlag(composeView.isFlagSecureEnabled())
+ )
} else {
setSecureFlagEnabled(composeView.isFlagSecureEnabled())
}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.kt
index 1676e88..4e5941e 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.kt
@@ -268,8 +268,10 @@
fun setProperties(properties: PopupProperties?) {
if (properties != null && properties is AndroidPopupProperties) {
- setSecureFlagEnabled(properties.securePolicy
- .shouldApplySecureFlag(composeView.isFlagSecureEnabled()))
+ setSecureFlagEnabled(
+ properties.securePolicy
+ .shouldApplySecureFlag(composeView.isFlagSecureEnabled())
+ )
} else {
setSecureFlagEnabled(composeView.isFlagSecureEnabled())
}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposedModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposedModifier.kt
index 3c0a2e7..9c6a48e 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposedModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposedModifier.kt
@@ -19,6 +19,9 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ComposeCompilerApi
import androidx.compose.runtime.Composer
+import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.platform.InspectorValueInfo
+import androidx.compose.ui.platform.NoInspectorInfo
/**
* Declare a just-in-time composition of a [Modifier] that will be composed for each element it
@@ -26,16 +29,25 @@
* instance-specific state for each modified element, allowing the same [Modifier] instance to be
* safely reused for multiple elements while maintaining element-specific state.
*
+ * If [inspectorInfo] is specified this modifier will be visible to tools during development.
+ * Specify the name and arguments of the original modifier.
+ *
+ * Example usage:
+ * @sample androidx.compose.ui.samples.InspectorInfoInComposedModifierSample
+ * @sample androidx.compose.ui.samples.InspectorInfoInComposedModifierWithArgumentsSample
+ *
* [materialize] must be called to create instance-specific modifiers if you are directly
* applying a [Modifier] to an element tree node.
*/
fun Modifier.composed(
+ inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo,
factory: @Composable Modifier.() -> Modifier
-): Modifier = this.then(ComposedModifier(factory))
+): Modifier = this.then(ComposedModifier(inspectorInfo, factory))
-private data class ComposedModifier(
+private class ComposedModifier(
+ inspectorInfo: InspectorInfo.() -> Unit,
val factory: @Composable Modifier.() -> Modifier
-) : Modifier.Element
+) : Modifier.Element, InspectorValueInfo(inspectorInfo)
/**
* Materialize any instance-specific [composed modifiers][composed] for applying to a raw tree node.
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
index 307e39b..ec171fa 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
@@ -225,7 +225,7 @@
* A function used to react to and modify [PointerInputChange]s.
*/
typealias PointerInputHandler =
- (PointerEvent, PointerEventPass, IntSize) -> List<PointerInputChange>
+ (PointerEvent, PointerEventPass, IntSize) -> List<PointerInputChange>
/**
* The base type for all custom events.
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
index 51446b0..e88873b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
@@ -764,6 +764,12 @@
// a new one.
requestRemeasure()
}
+ // If the parent data has changed, the parent needs remeasurement.
+ val oldParentData = parentData
+ outerMeasurablePlaceable.recalculateParentData()
+ if (oldParentData != parentData) {
+ parent?.requestRemeasure()
+ }
if (invalidateParentLayer || startZIndex != outerZIndexModifier ||
shouldInvalidateParentLayer()
) {
@@ -869,7 +875,7 @@
private fun hasNewPositioningCallback(): Boolean {
return modifier.foldOut(false) { mod, hasNewCallback ->
hasNewCallback ||
- (mod is OnGloballyPositionedModifier && mod !in onPositionedCallbacks)
+ (mod is OnGloballyPositionedModifier && mod !in onPositionedCallbacks)
}
}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OuterMeasurablePlaceable.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OuterMeasurablePlaceable.kt
index 048a50c..367f36b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OuterMeasurablePlaceable.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OuterMeasurablePlaceable.kt
@@ -43,7 +43,8 @@
var measureIteration = -1L
private set
- override val parentData: Any? get() = outerWrapper.parentData
+ override var parentData: Any? = null
+ private set
/**
* The function to be executed when the parent layout measures its children.
@@ -129,4 +130,11 @@
override fun minIntrinsicHeight(width: Int): Int = outerWrapper.minIntrinsicHeight(width)
override fun maxIntrinsicHeight(width: Int): Int = outerWrapper.maxIntrinsicHeight(width)
+
+ /**
+ * Recalculates the parent data.
+ */
+ fun recalculateParentData() {
+ parentData = outerWrapper.parentData
+ }
}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/InspectableValue.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/InspectableValue.kt
index 906f965..a02b18d 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/InspectableValue.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/InspectableValue.kt
@@ -17,6 +17,17 @@
package androidx.compose.ui.platform
/**
+ * An empty [InspectorInfo] DSL.
+ */
+val NoInspectorInfo: InspectorInfo.() -> Unit = {}
+
+/**
+ * True, if this is a debug build
+ */
+// TODO(b/170125592): Replace this with an actual debug setting...
+const val DebugInspectorInfo = true
+
+/**
* A compose value that is inspectable by tools. It gives access to private parts of a value.
*/
interface InspectableValue {
@@ -25,7 +36,7 @@
* The elements of a compose value.
*/
val inspectableElements: Sequence<ValueElement>
- get() = sequenceOf()
+ get() = emptySequence()
/**
* Use this name as the reference name shown in tools of this value if there is no explicit
@@ -47,3 +58,69 @@
* The [name] typically refers to a (possibly private) property name with its corresponding [value].
*/
data class ValueElement(val name: String, val value: Any?)
+
+/**
+ * A builder for an [InspectableValue].
+ */
+class InspectorInfo {
+ /**
+ * Provides a [InspectableValue.nameFallback].
+ */
+ var name: String? = null
+
+ /**
+ * Provides a [InspectableValue.valueOverride].
+ */
+ var value: Any? = null
+
+ /**
+ * Provides a [InspectableValue.inspectableElements].
+ */
+ val properties = ValueElementSequence()
+}
+
+/**
+ * A builder for a sequence of [ValueElement].
+ */
+class ValueElementSequence : Sequence<ValueElement> {
+ private val elements = mutableListOf<ValueElement>()
+
+ override fun iterator(): Iterator<ValueElement> = elements.iterator()
+
+ /**
+ * Specify a sub element with name and value.
+ */
+ operator fun set(name: String, value: Any?) {
+ elements.add(ValueElement(name, value))
+ }
+}
+
+/**
+ * Implementation of [InspectableValue] based on a builder [InspectorInfo] DSL.
+ */
+abstract class InspectorValueInfo(private val info: InspectorInfo.() -> Unit) : InspectableValue {
+ private var _values: InspectorInfo? = null
+
+ private val values: InspectorInfo
+ get() {
+ val valueInfo = _values ?: InspectorInfo().apply { info() }
+ _values = valueInfo
+ return valueInfo
+ }
+
+ override val nameFallback: String?
+ get() = values.name
+
+ override val valueOverride: Any?
+ get() = values.value
+
+ override val inspectableElements: Sequence<ValueElement>
+ get() = values.properties
+}
+
+/**
+ * Factory method for avoiding DSL allocation when no debug inspector info is needed.
+ */
+inline fun debugInspectorInfo(
+ crossinline definitions: InspectorInfo.() -> Unit
+): InspectorInfo.() -> Unit = if (DebugInspectorInfo) ({ definitions() }) else NoInspectorInfo
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/TextToolbar.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/TextToolbar.kt
index 7ef7e1c..cd994e99 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/TextToolbar.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/TextToolbar.kt
@@ -36,7 +36,8 @@
rect: Rect,
onCopyRequested: ActionCallback? = null,
onPasteRequested: ActionCallback? = null,
- onCutRequested: ActionCallback? = null
+ onCutRequested: ActionCallback? = null,
+ onSelectAllRequested: ActionCallback? = null
)
/**
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SelectionManager.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SelectionManager.kt
index d727b5a..b6cbf8e 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SelectionManager.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SelectionManager.kt
@@ -464,11 +464,11 @@
}
}
-private fun merge(lhs: Selection?, rhs: Selection?): Selection? {
+internal fun merge(lhs: Selection?, rhs: Selection?): Selection? {
return lhs?.merge(rhs) ?: rhs
}
-private fun getCurrentSelectedText(
+internal fun getCurrentSelectedText(
selectable: Selectable,
selection: Selection
): AnnotatedString {
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/Key.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/Key.kt
index 6d7897c..b1044d4 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/Key.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/Key.kt
@@ -16,6 +16,8 @@
package androidx.compose.ui.input.key
+import java.awt.event.KeyEvent
+
// TODO(demin): implement most of key codes
/**
@@ -23,297 +25,299 @@
*
* @param keyCode an integer code representing the key pressed.
*/
+// TODO: In AWT most modifiers have the same keycode. The only way how to distinguish them is
+// by using `location` property. The same about numpad location.
actual inline class Key(val keyCode: Int) {
actual companion object {
actual val Unknown = Key(0)
- actual val SoftLeft = Key(0)
- actual val SoftRight = Key(0)
- actual val Home = Key(0)
- actual val Back = Key(0)
- actual val Help = Key(0)
- actual val NavigatePrevious = Key(0)
- actual val NavigateNext = Key(0)
- actual val NavigateIn = Key(0)
- actual val NavigateOut = Key(0)
- actual val SystemNavigationUp = Key(0)
- actual val SystemNavigationDown = Key(0)
- actual val SystemNavigationLeft = Key(0)
- actual val SystemNavigationRight = Key(0)
- actual val Call = Key(0)
- actual val EndCall = Key(0)
- actual val DPadUp = Key(0)
- actual val DPadDown = Key(0)
- actual val DPadLeft = Key(0)
- actual val DPadRight = Key(0)
- actual val DPadCenter = Key(0)
- actual val DPadUpLeft = Key(0)
- actual val DPadDownLeft = Key(0)
- actual val DPadUpRight = Key(0)
- actual val DPadDownRight = Key(0)
- actual val VolumeUp = Key(0)
- actual val VolumeDown = Key(0)
- actual val Power = Key(0)
- actual val Camera = Key(0)
- actual val Clear = Key(0)
- actual val Number0 = Key(0)
- actual val Number1 = Key(0)
- actual val Number2 = Key(0)
- actual val Number3 = Key(0)
- actual val Number4 = Key(0)
- actual val Number5 = Key(0)
- actual val Number6 = Key(0)
- actual val Number7 = Key(0)
- actual val Number8 = Key(0)
- actual val Number9 = Key(0)
- actual val Number11 = Key(0)
- actual val Number12 = Key(0)
- actual val Plus = Key(0)
- actual val Minus = Key(0)
- actual val Multiply = Key(0)
- actual val Equals = Key(0)
- actual val Pound = Key(0)
- actual val A = Key(0)
- actual val B = Key(0)
- actual val C = Key(0)
- actual val D = Key(0)
- actual val E = Key(0)
- actual val F = Key(0)
- actual val G = Key(0)
- actual val H = Key(0)
- actual val I = Key(0)
- actual val J = Key(0)
- actual val K = Key(0)
- actual val L = Key(0)
- actual val M = Key(0)
- actual val N = Key(0)
- actual val O = Key(0)
- actual val P = Key(0)
- actual val Q = Key(0)
- actual val R = Key(0)
- actual val S = Key(0)
- actual val T = Key(0)
- actual val U = Key(0)
- actual val V = Key(0)
- actual val W = Key(0)
- actual val X = Key(0)
- actual val Y = Key(0)
- actual val Z = Key(0)
- actual val Comma = Key(0)
- actual val Period = Key(0)
- actual val AltLeft = Key(0)
- actual val AltRight = Key(0)
- actual val ShiftLeft = Key(0)
- actual val ShiftRight = Key(0)
- actual val Tab = Key(0)
- actual val Spacebar = Key(0)
- actual val Symbol = Key(0)
- actual val Browser = Key(0)
- actual val Envelope = Key(0)
- actual val Enter = Key(0)
- actual val Backspace = Key(0)
- actual val Delete = Key(0)
- actual val Escape = Key(0)
- actual val CtrlLeft = Key(0)
- actual val CtrlRight = Key(0)
- actual val CapsLock = Key(0)
- actual val ScrollLock = Key(0)
- actual val MetaLeft = Key(0)
- actual val MetaRight = Key(0)
- actual val Function = Key(0)
- actual val PrintScreen = Key(0)
- actual val Break = Key(0)
- actual val MoveHome = Key(0)
- actual val MoveEnd = Key(0)
- actual val Insert = Key(0)
- actual val Cut = Key(0)
- actual val Copy = Key(0)
- actual val Paste = Key(0)
- actual val Grave = Key(0)
- actual val LeftBracket = Key(0)
- actual val RightBracket = Key(0)
- actual val Slash = Key(0)
- actual val Backslash = Key(0)
- actual val Semicolon = Key(0)
- actual val Apostrophe = Key(0)
- actual val At = Key(0)
- actual val Number = Key(0)
- actual val HeadsetHook = Key(0)
- actual val Focus = Key(0)
- actual val Menu = Key(0)
- actual val Notification = Key(0)
- actual val Search = Key(0)
- actual val PageUp = Key(0)
- actual val PageDown = Key(0)
- actual val PictureSymbols = Key(0)
- actual val SwitchCharset = Key(0)
- actual val ButtonA = Key(0)
- actual val ButtonB = Key(0)
- actual val ButtonC = Key(0)
- actual val ButtonX = Key(0)
- actual val ButtonY = Key(0)
- actual val ButtonZ = Key(0)
- actual val ButtonL1 = Key(0)
- actual val ButtonR1 = Key(0)
- actual val ButtonL2 = Key(0)
- actual val ButtonR2 = Key(0)
- actual val ButtonThumbLeft = Key(0)
- actual val ButtonThumbRight = Key(0)
- actual val ButtonStart = Key(0)
- actual val ButtonSelect = Key(0)
- actual val ButtonMode = Key(0)
- actual val Button1 = Key(0)
- actual val Button2 = Key(0)
- actual val Button3 = Key(0)
- actual val Button4 = Key(0)
- actual val Button5 = Key(0)
- actual val Button6 = Key(0)
- actual val Button7 = Key(0)
- actual val Button8 = Key(0)
- actual val Button9 = Key(0)
- actual val Button10 = Key(0)
- actual val Button11 = Key(0)
- actual val Button12 = Key(0)
- actual val Button13 = Key(0)
- actual val Button14 = Key(0)
- actual val Button15 = Key(0)
- actual val Button16 = Key(0)
- actual val Forward = Key(0)
- actual val F1 = Key(0)
- actual val F2 = Key(0)
- actual val F3 = Key(0)
- actual val F4 = Key(0)
- actual val F5 = Key(0)
- actual val F6 = Key(0)
- actual val F7 = Key(0)
- actual val F8 = Key(0)
- actual val F9 = Key(0)
- actual val F10 = Key(0)
- actual val F11 = Key(0)
- actual val F12 = Key(0)
- actual val NumLock = Key(0)
- actual val NumPad0 = Key(0)
- actual val NumPad1 = Key(0)
- actual val NumPad2 = Key(0)
- actual val NumPad3 = Key(0)
- actual val NumPad4 = Key(0)
- actual val NumPad5 = Key(0)
- actual val NumPad6 = Key(0)
- actual val NumPad7 = Key(0)
- actual val NumPad8 = Key(0)
- actual val NumPad9 = Key(0)
- actual val NumPadDivide = Key(0)
- actual val NumPadMultiply = Key(0)
- actual val NumPadSubtract = Key(0)
- actual val NumPadAdd = Key(0)
- actual val NumPadDot = Key(0)
- actual val NumPadComma = Key(0)
- actual val NumPadEnter = Key(0)
- actual val NumPadEquals = Key(0)
- actual val NumPadLeftParenthesis = Key(0)
- actual val NumPadRightParenthesis = Key(0)
- actual val MediaPlay = Key(0)
- actual val MediaPause = Key(0)
- actual val MediaPlayPause = Key(0)
- actual val MediaStop = Key(0)
- actual val MediaRecord = Key(0)
- actual val MediaNext = Key(0)
- actual val MediaPrevious = Key(0)
- actual val MediaRewind = Key(0)
- actual val MediaFastForward = Key(0)
- actual val MediaClose = Key(0)
- actual val MediaAudioTrack = Key(0)
- actual val MediaEject = Key(0)
- actual val MediaTopMenu = Key(0)
- actual val MediaSkipForward = Key(0)
- actual val MediaSkipBackward = Key(0)
- actual val MediaStepForward = Key(0)
- actual val MediaStepBackward = Key(0)
- actual val MicrophoneMute = Key(0)
- actual val VolumeMute = Key(0)
- actual val Info = Key(0)
- actual val ChannelUp = Key(0)
- actual val ChannelDown = Key(0)
- actual val ZoomIn = Key(0)
- actual val ZoomOut = Key(0)
- actual val Tv = Key(0)
- actual val Window = Key(0)
- actual val Guide = Key(0)
- actual val Dvr = Key(0)
- actual val Bookmark = Key(0)
- actual val Captions = Key(0)
- actual val Settings = Key(0)
- actual val TvPower = Key(0)
- actual val TvInput = Key(0)
- actual val SetTopBoxPower = Key(0)
- actual val SetTopBoxInput = Key(0)
- actual val AvReceiverPower = Key(0)
- actual val AvReceiverInput = Key(0)
- actual val ProgramRed = Key(0)
- actual val ProgramGreen = Key(0)
- actual val ProgramYellow = Key(0)
- actual val ProgramBlue = Key(0)
- actual val AppSwitch = Key(0)
- actual val LanguageSwitch = Key(0)
- actual val MannerMode = Key(0)
- actual val Toggle2D3D = Key(0)
- actual val Contacts = Key(0)
- actual val Calendar = Key(0)
- actual val Music = Key(0)
- actual val Calculator = Key(0)
- actual val ZenkakuHankaru = Key(0)
- actual val Eisu = Key(0)
- actual val Muhenkan = Key(0)
- actual val Henkan = Key(0)
- actual val KatakanaHiragana = Key(0)
- actual val Yen = Key(0)
- actual val Ro = Key(0)
- actual val Kana = Key(0)
- actual val Assist = Key(0)
- actual val BrightnessDown = Key(0)
- actual val BrightnessUp = Key(0)
- actual val Sleep = Key(0)
- actual val WakeUp = Key(0)
- actual val SoftSleep = Key(0)
- actual val Pairing = Key(0)
- actual val LastChannel = Key(0)
- actual val TvDataService = Key(0)
- actual val VoiceAssist = Key(0)
- actual val TvRadioService = Key(0)
- actual val TvTeletext = Key(0)
- actual val TvNumberEntry = Key(0)
- actual val TvTerrestrialAnalog = Key(0)
- actual val TvTerrestrialDigital = Key(0)
- actual val TvSatellite = Key(0)
- actual val TvSatelliteBs = Key(0)
- actual val TvSatelliteCs = Key(0)
- actual val TvSatelliteService = Key(0)
- actual val TvNetwork = Key(0)
- actual val TvAntennaCable = Key(0)
- actual val TvInputHdmi1 = Key(0)
- actual val TvInputHdmi2 = Key(0)
- actual val TvInputHdmi3 = Key(0)
- actual val TvInputHdmi4 = Key(0)
- actual val TvInputComposite1 = Key(0)
- actual val TvInputComposite2 = Key(0)
- actual val TvInputComponent1 = Key(0)
- actual val TvInputComponent2 = Key(0)
- actual val TvInputVga1 = Key(0)
- actual val TvAudioDescription = Key(0)
- actual val TvAudioDescriptionMixingVolumeUp = Key(0)
- actual val TvAudioDescriptionMixingVolumeDown = Key(0)
- actual val TvZoomMode = Key(0)
- actual val TvContentsMenu = Key(0)
- actual val TvMediaContextMenu = Key(0)
- actual val TvTimerProgramming = Key(0)
- actual val StemPrimary = Key(0)
- actual val Stem1 = Key(0)
- actual val Stem2 = Key(0)
- actual val Stem3 = Key(0)
- actual val AllApps = Key(0)
- actual val Refresh = Key(0)
- actual val ThumbsUp = Key(0)
- actual val ThumbsDown = Key(0)
- actual val ProfileSwitch = Key(0)
+ actual val SoftLeft = Key(-1)
+ actual val SoftRight = Key(-1)
+ actual val Home = Key(KeyEvent.VK_HOME)
+ actual val Back = Key(-1)
+ actual val Help = Key(KeyEvent.VK_HELP)
+ actual val NavigatePrevious = Key(-1)
+ actual val NavigateNext = Key(-1)
+ actual val NavigateIn = Key(-1)
+ actual val NavigateOut = Key(-1)
+ actual val SystemNavigationUp = Key(-1)
+ actual val SystemNavigationDown = Key(-1)
+ actual val SystemNavigationLeft = Key(-1)
+ actual val SystemNavigationRight = Key(-1)
+ actual val Call = Key(-1)
+ actual val EndCall = Key(-1)
+ actual val DPadUp = Key(KeyEvent.VK_KP_UP)
+ actual val DPadDown = Key(KeyEvent.VK_KP_DOWN)
+ actual val DPadLeft = Key(KeyEvent.VK_KP_LEFT)
+ actual val DPadRight = Key(KeyEvent.VK_KP_RIGHT)
+ actual val DPadCenter = Key(-1)
+ actual val DPadUpLeft = Key(-1)
+ actual val DPadDownLeft = Key(-1)
+ actual val DPadUpRight = Key(-1)
+ actual val DPadDownRight = Key(-1)
+ actual val VolumeUp = Key(-1)
+ actual val VolumeDown = Key(-1)
+ actual val Power = Key(-1)
+ actual val Camera = Key(-1)
+ actual val Clear = Key(-1)
+ actual val Number0 = Key(KeyEvent.VK_0)
+ actual val Number1 = Key(KeyEvent.VK_1)
+ actual val Number2 = Key(KeyEvent.VK_2)
+ actual val Number3 = Key(KeyEvent.VK_3)
+ actual val Number4 = Key(KeyEvent.VK_4)
+ actual val Number5 = Key(KeyEvent.VK_5)
+ actual val Number6 = Key(KeyEvent.VK_6)
+ actual val Number7 = Key(KeyEvent.VK_7)
+ actual val Number8 = Key(KeyEvent.VK_8)
+ actual val Number9 = Key(KeyEvent.VK_9)
+ actual val Number11 = Key(-1)
+ actual val Number12 = Key(-1)
+ actual val Plus = Key(KeyEvent.VK_PLUS)
+ actual val Minus = Key(KeyEvent.VK_MINUS)
+ actual val Multiply = Key(KeyEvent.VK_MULTIPLY)
+ actual val Equals = Key(KeyEvent.VK_EQUALS)
+ actual val Pound = Key(-1)
+ actual val A = Key(KeyEvent.VK_A)
+ actual val B = Key(KeyEvent.VK_B)
+ actual val C = Key(KeyEvent.VK_C)
+ actual val D = Key(KeyEvent.VK_D)
+ actual val E = Key(KeyEvent.VK_E)
+ actual val F = Key(KeyEvent.VK_F)
+ actual val G = Key(KeyEvent.VK_G)
+ actual val H = Key(KeyEvent.VK_H)
+ actual val I = Key(KeyEvent.VK_I)
+ actual val J = Key(KeyEvent.VK_J)
+ actual val K = Key(KeyEvent.VK_K)
+ actual val L = Key(KeyEvent.VK_L)
+ actual val M = Key(KeyEvent.VK_M)
+ actual val N = Key(KeyEvent.VK_N)
+ actual val O = Key(KeyEvent.VK_O)
+ actual val P = Key(KeyEvent.VK_P)
+ actual val Q = Key(KeyEvent.VK_Q)
+ actual val R = Key(KeyEvent.VK_R)
+ actual val S = Key(KeyEvent.VK_S)
+ actual val T = Key(KeyEvent.VK_T)
+ actual val U = Key(KeyEvent.VK_U)
+ actual val V = Key(KeyEvent.VK_V)
+ actual val W = Key(KeyEvent.VK_W)
+ actual val X = Key(KeyEvent.VK_X)
+ actual val Y = Key(KeyEvent.VK_Y)
+ actual val Z = Key(KeyEvent.VK_Z)
+ actual val Comma = Key(KeyEvent.VK_COMMA)
+ actual val Period = Key(KeyEvent.VK_PERIOD)
+ actual val AltLeft = Key(KeyEvent.VK_ALT)
+ actual val AltRight = Key(KeyEvent.VK_ALT)
+ actual val ShiftLeft = Key(KeyEvent.VK_SHIFT)
+ actual val ShiftRight = Key(KeyEvent.VK_SHIFT)
+ actual val Tab = Key(KeyEvent.VK_TAB)
+ actual val Spacebar = Key(KeyEvent.VK_SPACE)
+ actual val Symbol = Key(-1)
+ actual val Browser = Key(-1)
+ actual val Envelope = Key(-1)
+ actual val Enter = Key(KeyEvent.VK_ENTER)
+ actual val Backspace = Key(KeyEvent.VK_BACK_SPACE)
+ actual val Delete = Key(KeyEvent.VK_DELETE)
+ actual val Escape = Key(KeyEvent.VK_ESCAPE)
+ actual val CtrlLeft = Key(KeyEvent.VK_CONTROL)
+ actual val CtrlRight = Key(KeyEvent.VK_CONTROL)
+ actual val CapsLock = Key(KeyEvent.VK_CAPS_LOCK)
+ actual val ScrollLock = Key(KeyEvent.VK_SCROLL_LOCK)
+ actual val MetaLeft = Key(KeyEvent.VK_META)
+ actual val MetaRight = Key(KeyEvent.VK_META)
+ actual val Function = Key(-1)
+ actual val PrintScreen = Key(KeyEvent.VK_PRINTSCREEN)
+ actual val Break = Key(-1)
+ actual val MoveHome = Key(-1)
+ actual val MoveEnd = Key(-1)
+ actual val Insert = Key(-1)
+ actual val Cut = Key(-1)
+ actual val Copy = Key(-1)
+ actual val Paste = Key(-1)
+ actual val Grave = Key(KeyEvent.VK_BACK_QUOTE)
+ actual val LeftBracket = Key(KeyEvent.VK_OPEN_BRACKET)
+ actual val RightBracket = Key(KeyEvent.VK_CLOSE_BRACKET)
+ actual val Slash = Key(KeyEvent.VK_SLASH)
+ actual val Backslash = Key(KeyEvent.VK_BACK_SLASH)
+ actual val Semicolon = Key(KeyEvent.VK_SEMICOLON)
+ actual val Apostrophe = Key(KeyEvent.VK_QUOTE)
+ actual val At = Key(KeyEvent.VK_AT)
+ actual val Number = Key(-1)
+ actual val HeadsetHook = Key(-1)
+ actual val Focus = Key(-1)
+ actual val Menu = Key(-1)
+ actual val Notification = Key(-1)
+ actual val Search = Key(-1)
+ actual val PageUp = Key(KeyEvent.VK_PAGE_UP)
+ actual val PageDown = Key(KeyEvent.VK_PAGE_UP)
+ actual val PictureSymbols = Key(-1)
+ actual val SwitchCharset = Key(-1)
+ actual val ButtonA = Key(-1)
+ actual val ButtonB = Key(-1)
+ actual val ButtonC = Key(-1)
+ actual val ButtonX = Key(-1)
+ actual val ButtonY = Key(-1)
+ actual val ButtonZ = Key(-1)
+ actual val ButtonL1 = Key(-1)
+ actual val ButtonR1 = Key(-1)
+ actual val ButtonL2 = Key(-1)
+ actual val ButtonR2 = Key(-1)
+ actual val ButtonThumbLeft = Key(-1)
+ actual val ButtonThumbRight = Key(-1)
+ actual val ButtonStart = Key(-1)
+ actual val ButtonSelect = Key(-1)
+ actual val ButtonMode = Key(-1)
+ actual val Button1 = Key(-1)
+ actual val Button2 = Key(-1)
+ actual val Button3 = Key(-1)
+ actual val Button4 = Key(-1)
+ actual val Button5 = Key(-1)
+ actual val Button6 = Key(-1)
+ actual val Button7 = Key(-1)
+ actual val Button8 = Key(-1)
+ actual val Button9 = Key(-1)
+ actual val Button10 = Key(-1)
+ actual val Button11 = Key(-1)
+ actual val Button12 = Key(-1)
+ actual val Button13 = Key(-1)
+ actual val Button14 = Key(-1)
+ actual val Button15 = Key(-1)
+ actual val Button16 = Key(-1)
+ actual val Forward = Key(-1)
+ actual val F1 = Key(KeyEvent.VK_F1)
+ actual val F2 = Key(KeyEvent.VK_F2)
+ actual val F3 = Key(KeyEvent.VK_F3)
+ actual val F4 = Key(KeyEvent.VK_F4)
+ actual val F5 = Key(KeyEvent.VK_F5)
+ actual val F6 = Key(KeyEvent.VK_F6)
+ actual val F7 = Key(KeyEvent.VK_F7)
+ actual val F8 = Key(KeyEvent.VK_F8)
+ actual val F9 = Key(KeyEvent.VK_F9)
+ actual val F10 = Key(KeyEvent.VK_F10)
+ actual val F11 = Key(KeyEvent.VK_F11)
+ actual val F12 = Key(KeyEvent.VK_F12)
+ actual val NumLock = Key(KeyEvent.VK_NUM_LOCK)
+ actual val NumPad0 = Key(KeyEvent.VK_NUMPAD0)
+ actual val NumPad1 = Key(KeyEvent.VK_NUMPAD1)
+ actual val NumPad2 = Key(KeyEvent.VK_NUMPAD2)
+ actual val NumPad3 = Key(KeyEvent.VK_NUMPAD3)
+ actual val NumPad4 = Key(KeyEvent.VK_NUMPAD4)
+ actual val NumPad5 = Key(KeyEvent.VK_NUMPAD5)
+ actual val NumPad6 = Key(KeyEvent.VK_NUMPAD6)
+ actual val NumPad7 = Key(KeyEvent.VK_NUMPAD7)
+ actual val NumPad8 = Key(KeyEvent.VK_NUMPAD8)
+ actual val NumPad9 = Key(KeyEvent.VK_NUMPAD9)
+ actual val NumPadDivide = Key(KeyEvent.VK_DIVIDE)
+ actual val NumPadMultiply = Key(KeyEvent.VK_MULTIPLY)
+ actual val NumPadSubtract = Key(KeyEvent.VK_SUBTRACT)
+ actual val NumPadAdd = Key(KeyEvent.VK_ADD)
+ actual val NumPadDot = Key(KeyEvent.VK_PERIOD)
+ actual val NumPadComma = Key(KeyEvent.VK_COMMA)
+ actual val NumPadEnter = Key(KeyEvent.VK_ENTER)
+ actual val NumPadEquals = Key(KeyEvent.VK_EQUALS)
+ actual val NumPadLeftParenthesis = Key(KeyEvent.VK_LEFT_PARENTHESIS)
+ actual val NumPadRightParenthesis = Key(KeyEvent.VK_RIGHT_PARENTHESIS)
+ actual val MediaPlay = Key(-1)
+ actual val MediaPause = Key(-1)
+ actual val MediaPlayPause = Key(-1)
+ actual val MediaStop = Key(-1)
+ actual val MediaRecord = Key(-1)
+ actual val MediaNext = Key(-1)
+ actual val MediaPrevious = Key(-1)
+ actual val MediaRewind = Key(-1)
+ actual val MediaFastForward = Key(-1)
+ actual val MediaClose = Key(-1)
+ actual val MediaAudioTrack = Key(-1)
+ actual val MediaEject = Key(-1)
+ actual val MediaTopMenu = Key(-1)
+ actual val MediaSkipForward = Key(-1)
+ actual val MediaSkipBackward = Key(-1)
+ actual val MediaStepForward = Key(-1)
+ actual val MediaStepBackward = Key(-1)
+ actual val MicrophoneMute = Key(-1)
+ actual val VolumeMute = Key(-1)
+ actual val Info = Key(-1)
+ actual val ChannelUp = Key(-1)
+ actual val ChannelDown = Key(-1)
+ actual val ZoomIn = Key(-1)
+ actual val ZoomOut = Key(-1)
+ actual val Tv = Key(-1)
+ actual val Window = Key(-1)
+ actual val Guide = Key(-1)
+ actual val Dvr = Key(-1)
+ actual val Bookmark = Key(-1)
+ actual val Captions = Key(-1)
+ actual val Settings = Key(-1)
+ actual val TvPower = Key(-1)
+ actual val TvInput = Key(-1)
+ actual val SetTopBoxPower = Key(-1)
+ actual val SetTopBoxInput = Key(-1)
+ actual val AvReceiverPower = Key(-1)
+ actual val AvReceiverInput = Key(-1)
+ actual val ProgramRed = Key(-1)
+ actual val ProgramGreen = Key(-1)
+ actual val ProgramYellow = Key(-1)
+ actual val ProgramBlue = Key(-1)
+ actual val AppSwitch = Key(-1)
+ actual val LanguageSwitch = Key(-1)
+ actual val MannerMode = Key(-1)
+ actual val Toggle2D3D = Key(-1)
+ actual val Contacts = Key(-1)
+ actual val Calendar = Key(-1)
+ actual val Music = Key(-1)
+ actual val Calculator = Key(-1)
+ actual val ZenkakuHankaru = Key(-1)
+ actual val Eisu = Key(-1)
+ actual val Muhenkan = Key(-1)
+ actual val Henkan = Key(-1)
+ actual val KatakanaHiragana = Key(-1)
+ actual val Yen = Key(-1)
+ actual val Ro = Key(-1)
+ actual val Kana = Key(-1)
+ actual val Assist = Key(-1)
+ actual val BrightnessDown = Key(-1)
+ actual val BrightnessUp = Key(-1)
+ actual val Sleep = Key(-1)
+ actual val WakeUp = Key(-1)
+ actual val SoftSleep = Key(-1)
+ actual val Pairing = Key(-1)
+ actual val LastChannel = Key(-1)
+ actual val TvDataService = Key(-1)
+ actual val VoiceAssist = Key(-1)
+ actual val TvRadioService = Key(-1)
+ actual val TvTeletext = Key(-1)
+ actual val TvNumberEntry = Key(-1)
+ actual val TvTerrestrialAnalog = Key(-1)
+ actual val TvTerrestrialDigital = Key(-1)
+ actual val TvSatellite = Key(-1)
+ actual val TvSatelliteBs = Key(-1)
+ actual val TvSatelliteCs = Key(-1)
+ actual val TvSatelliteService = Key(-1)
+ actual val TvNetwork = Key(-1)
+ actual val TvAntennaCable = Key(-1)
+ actual val TvInputHdmi1 = Key(-1)
+ actual val TvInputHdmi2 = Key(-1)
+ actual val TvInputHdmi3 = Key(-1)
+ actual val TvInputHdmi4 = Key(-1)
+ actual val TvInputComposite1 = Key(-1)
+ actual val TvInputComposite2 = Key(-1)
+ actual val TvInputComponent1 = Key(-1)
+ actual val TvInputComponent2 = Key(-1)
+ actual val TvInputVga1 = Key(-1)
+ actual val TvAudioDescription = Key(-1)
+ actual val TvAudioDescriptionMixingVolumeUp = Key(-1)
+ actual val TvAudioDescriptionMixingVolumeDown = Key(-1)
+ actual val TvZoomMode = Key(-1)
+ actual val TvContentsMenu = Key(-1)
+ actual val TvMediaContextMenu = Key(-1)
+ actual val TvTimerProgramming = Key(-1)
+ actual val StemPrimary = Key(-1)
+ actual val Stem1 = Key(-1)
+ actual val Stem2 = Key(-1)
+ actual val Stem3 = Key(-1)
+ actual val AllApps = Key(-1)
+ actual val Refresh = Key(-1)
+ actual val ThumbsUp = Key(-1)
+ actual val ThumbsDown = Key(-1)
+ actual val ProfileSwitch = Key(-1)
}
actual override fun toString(): String {
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/KeyEventDesktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/KeyEventDesktop.kt
new file mode 100644
index 0000000..78d70c5
--- /dev/null
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/KeyEventDesktop.kt
@@ -0,0 +1,51 @@
+/*
+ * 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.compose.ui.input.key
+
+import java.awt.event.KeyEvent.KEY_PRESSED
+import java.awt.event.KeyEvent.KEY_RELEASED
+import java.awt.event.KeyEvent as KeyEventAwt
+
+@OptIn(ExperimentalKeyInput::class)
+internal inline class KeyEventDesktop(val keyEvent: KeyEventAwt) : KeyEvent {
+
+ override val key: Key
+ get() = Key(keyEvent.keyCode)
+
+ override val utf16CodePoint: Int
+ get() = keyEvent.keyChar.toInt()
+
+ override val type: KeyEventType
+ get() = when (keyEvent.id) {
+ KEY_PRESSED -> KeyEventType.KeyDown
+ KEY_RELEASED -> KeyEventType.KeyUp
+ else -> KeyEventType.Unknown
+ }
+
+ override val alt: Alt
+ get() = AltDesktop(keyEvent)
+}
+
+@OptIn(ExperimentalKeyInput::class)
+internal inline class AltDesktop(val keyEvent: KeyEventAwt) : Alt {
+
+ override val isLeftAltPressed
+ get() = keyEvent.isAltDown
+
+ override val isRightAltPressed
+ get() = keyEvent.isAltGraphDown
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/Shortcut.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/Shortcut.kt
new file mode 100644
index 0000000..1c7ac55
--- /dev/null
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/key/Shortcut.kt
@@ -0,0 +1,87 @@
+/*
+ * 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.compose.ui.input.key
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+
+data class KeysSet(val keys: List<Key>) {
+ operator fun plus(key: Key): KeysSet {
+ return KeysSet(keys + key)
+ }
+
+ fun isSubset(of: KeysSet) = of.keys.containsAll(keys)
+}
+
+operator fun Key.plus(other: Key): KeysSet {
+ return KeysSet(listOf(this, other))
+}
+
+@ExperimentalKeyInput
+class KeysSetInstance(val keysSet: KeysSet) {
+ var activeKeys = listOf<Key>()
+
+ fun process(event: KeyEvent): Boolean {
+ return if (keysSet.keys.contains(event.key)) {
+ when (event.type) {
+ KeyEventType.KeyDown -> {
+ val newKeys = activeKeys + event.key
+ if (newKeys.size == keysSet.keys.size) {
+ activeKeys = listOf()
+ true
+ } else {
+ activeKeys = newKeys
+ false
+ }
+ }
+ KeyEventType.KeyUp -> {
+ activeKeys = activeKeys - event.key
+ false
+ }
+ else -> false
+ }
+ } else {
+ false
+ }
+ }
+}
+
+@ExperimentalKeyInput
+class ShortcutInstance(val keysSet: KeysSet, val callback: () -> Unit) {
+ private val keysSetInstance = KeysSetInstance(keysSet)
+
+ fun process(event: KeyEvent): Boolean {
+ if (keysSetInstance.process(event)) {
+ callback()
+ return true
+ } else {
+ return false
+ }
+ }
+}
+
+@ExperimentalKeyInput
+@Composable
+fun ShortcutHandler(keysSet: KeysSet, onShortcut: () -> Unit): (KeyEvent) -> Boolean {
+ val instance = remember { ShortcutInstance(keysSet, onShortcut) }
+ return instance::process
+}
+
+@ExperimentalKeyInput
+@Composable
+fun ShortcutHandler(key: Key, onShortcut: () -> Unit) =
+ ShortcutHandler(KeysSet(listOf(key)), onShortcut)
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopAnimationClock.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopAnimationClock.kt
index f790d2c..6b5b470 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopAnimationClock.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopAnimationClock.kt
@@ -25,11 +25,10 @@
) : AnimationClockObservable {
private val manual = ManualAnimationClock(0, dispatchOnSubscribe = false)
+ val hasObservers get() = manual.hasObservers
+
fun onFrame(nanoTime: Long) {
manual.clockTimeMillis = nanoTime / 1_000_000L
- if (manual.hasObservers) {
- invalidate()
- }
}
override fun subscribe(observer: AnimationClockObserver) {
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopClipboardManager.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopClipboardManager.kt
index 152a5c1..1b87281 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopClipboardManager.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopClipboardManager.kt
@@ -17,15 +17,18 @@
package androidx.compose.ui.platform
import androidx.compose.ui.text.AnnotatedString
+import java.awt.Toolkit
+import java.awt.datatransfer.StringSelection
// TODO(demin): implement ClipboardManager
class DesktopClipboardManager : ClipboardManager {
+ val systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
override fun getText(): AnnotatedString? {
println("ClipboardManager.getText not implemented yet")
return null
}
override fun setText(annotatedString: AnnotatedString) {
- println("ClipboardManager.setText not implemented yet")
+ systemClipboard.setContents(StringSelection(annotatedString.text), null)
}
}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopComponent.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopComponent.kt
new file mode 100644
index 0000000..7a1be55
--- /dev/null
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopComponent.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.compose.ui.platform
+
+import java.awt.Point
+import java.awt.im.InputMethodRequests
+
+interface DesktopComponent : DesktopInputComponent
+
+object DummyDesktopComponent : DesktopComponent {
+ override fun enableInput(inputMethodRequests: InputMethodRequests) {}
+ override fun disableInput() {}
+ override fun locationOnScreen() = Point(0, 0)
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwner.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwner.kt
index 8d3700d9..db95b35 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwner.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwner.kt
@@ -107,6 +107,7 @@
container.register(this)
snapshotObserver.enableStateUpdatesObserving(true)
root.attach(this)
+ _focusManager.takeFocus()
}
fun dispose() {
@@ -123,6 +124,8 @@
override val clipboardManager = DesktopClipboardManager()
+ internal val selectionManager = SelectionManagerTracker()
+
override val textToolbar = DesktopTextToolbar()
override val semanticsOwner: SemanticsOwner = SemanticsOwner(root)
@@ -131,12 +134,12 @@
override val autofill: Autofill? get() = null
- // TODO(demin): implement sending key events from OS
- // (see Ralston Da Silva comment in
- // [https://android-review.googlesource.com/c/platform/frameworks/support/+/1372126/6])
- // implement also key codes in androidx.compose.ui.input.key.Key
+ val keyboard: Keyboard?
+ get() = container.keyboard
+
override fun sendKeyEvent(keyEvent: KeyEvent): Boolean {
- return keyInputModifier.processKeyInput(keyEvent)
+ return keyboard?.processKeyInput(keyEvent) ?: false ||
+ keyInputModifier.processKeyInput(keyEvent)
}
override var showLayoutBounds = false
@@ -156,19 +159,22 @@
override val measureIteration: Long get() = measureAndLayoutDelegate.measureIteration
override fun measureAndLayout() {
- measureAndLayoutDelegate.measureAndLayout()
+ if (measureAndLayoutDelegate.measureAndLayout()) {
+ container.invalidate()
+ }
measureAndLayoutDelegate.dispatchOnPositionedCallbacks()
- container.invalidate()
}
override fun onRequestMeasure(layoutNode: LayoutNode) {
- measureAndLayoutDelegate.requestRemeasure(layoutNode)
- container.invalidate()
+ if (measureAndLayoutDelegate.requestRemeasure(layoutNode)) {
+ container.invalidate()
+ }
}
override fun onRequestRelayout(layoutNode: LayoutNode) {
- measureAndLayoutDelegate.requestRelayout(layoutNode)
- container.invalidate()
+ if (measureAndLayoutDelegate.requestRelayout(layoutNode)) {
+ container.invalidate()
+ }
}
override val hasPendingMeasureOrLayout
@@ -208,7 +214,10 @@
) = SkijaLayer(
density,
drawLayerModifier,
- invalidateParentLayer
+ invalidateParentLayer = {
+ invalidateParentLayer()
+ container.invalidate()
+ }
) { canvas ->
observeDrawModelReads(this) {
drawBlock(canvas)
@@ -226,8 +235,6 @@
}
fun draw(canvas: org.jetbrains.skija.Canvas) {
- measureAndLayoutDelegate.measureAndLayout()
- measureAndLayoutDelegate.dispatchOnPositionedCallbacks()
root.draw(DesktopCanvas(canvas))
}
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwners.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwners.kt
index 1fcdc2c..fb56f9a 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwners.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwners.kt
@@ -15,8 +15,11 @@
*/
package androidx.compose.ui.platform
+import androidx.compose.runtime.Recomposer
import androidx.compose.runtime.staticAmbientOf
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.key.ExperimentalKeyInput
+import androidx.compose.ui.input.key.KeyEventDesktop
import androidx.compose.ui.input.mouse.MouseScrollEvent
import androidx.compose.ui.input.pointer.PointerId
import androidx.compose.ui.input.pointer.PointerInputData
@@ -24,24 +27,35 @@
import androidx.compose.ui.input.pointer.PointerInputEventData
import androidx.compose.ui.node.InternalCoreApi
import androidx.compose.ui.unit.Uptime
+import kotlinx.coroutines.yield
import org.jetbrains.skija.Canvas
-import java.awt.Component
import java.awt.event.InputMethodEvent
-import java.awt.im.InputMethodRequests
+import java.awt.event.KeyEvent
val DesktopOwnersAmbient = staticAmbientOf<DesktopOwners>()
@OptIn(InternalCoreApi::class)
class DesktopOwners(
- component: Component,
- val invalidate: () -> Unit
+ component: DesktopComponent = DummyDesktopComponent,
+ invalidate: () -> Unit
) {
+ private val _invalidate = invalidate
+ private var willRenderInThisFrame = false
+
+ fun invalidate() {
+ if (!willRenderInThisFrame) {
+ _invalidate()
+ }
+ }
+
val list = LinkedHashSet<DesktopOwner>()
+ @ExperimentalKeyInput
+ var keyboard: Keyboard? = null
private var pointerId = 0L
private var isMousePressed = false
- internal val animationClock = DesktopAnimationClock(invalidate)
+ internal val animationClock = DesktopAnimationClock(::invalidate)
internal val platformInputService: DesktopPlatformInput = DesktopPlatformInput(component)
fun register(desktopOwner: DesktopOwner) {
@@ -54,53 +68,92 @@
invalidate()
}
- fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
- animationClock.onFrame(nanoTime)
+ suspend fun onFrame(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
+ willRenderInThisFrame = true
+
+ try {
+ animationClock.onFrame(nanoTime)
+
+ // We have to wait recomposition if we want to draw actual animation state
+ // (state can be changed in animationClock.onFrame).
+ // Otherwise there may be a situation when we draw multiple frames with the same
+ // animation state (for example, when FPS always below FPS limit).
+ awaitRecompose()
+
+ for (owner in list) {
+ owner.setSize(width, height)
+ owner.measureAndLayout()
+ }
+ } finally {
+ willRenderInThisFrame = false
+ }
+
for (owner in list) {
- owner.setSize(width, height)
owner.draw(canvas)
}
+
+ if (animationClock.hasObservers) {
+ _invalidate()
+ }
}
+ private suspend fun awaitRecompose() {
+ // We should wait next dispatcher frame because Recomposer doesn't have
+ // pending changes yet, it will only schedule Recomposer.scheduleRecompose in
+ // FrameManager.schedule
+ yield()
+
+ // we can't stuck in infinite loop (because of double dispatching in FrameManager.schedule)
+ while (Recomposer.current().hasInvalidations()) {
+ yield()
+ }
+ }
+
+ val lastOwner: DesktopOwner?
+ get() = list.lastOrNull()
+
fun onMousePressed(x: Int, y: Int) {
isMousePressed = true
- list.lastOrNull()?.processPointerInput(pointerInputEvent(x, y, isMousePressed))
+ lastOwner?.processPointerInput(pointerInputEvent(x, y, isMousePressed))
}
fun onMouseReleased(x: Int, y: Int) {
isMousePressed = false
- list.lastOrNull()?.processPointerInput(pointerInputEvent(x, y, isMousePressed))
+ lastOwner?.processPointerInput(pointerInputEvent(x, y, isMousePressed))
pointerId += 1
}
fun onMouseDragged(x: Int, y: Int) {
- list.lastOrNull()?.processPointerInput(pointerInputEvent(x, y, isMousePressed))
+ lastOwner?.processPointerInput(pointerInputEvent(x, y, isMousePressed))
}
fun onMouseScroll(x: Int, y: Int, event: MouseScrollEvent) {
val position = Offset(x.toFloat(), y.toFloat())
- list.lastOrNull()?.onMouseScroll(position, event)
+ lastOwner?.onMouseScroll(position, event)
}
fun onMouseMoved(x: Int, y: Int) {
val position = Offset(x.toFloat(), y.toFloat())
- list.lastOrNull()?.onPointerMove(position)
+ lastOwner?.onPointerMove(position)
}
- fun onKeyPressed(code: Int, char: Char) {
- platformInputService.onKeyPressed(code, char)
+ private fun consumeKeyEventOr(event: KeyEvent, or: () -> Unit) {
+ val consumed = list.lastOrNull()?.sendKeyEvent(KeyEventDesktop(event)) ?: false
+ if (!consumed) {
+ or()
+ }
}
- fun onKeyReleased(code: Int, char: Char) {
- platformInputService.onKeyReleased(code, char)
+ fun onKeyPressed(event: KeyEvent) = consumeKeyEventOr(event) {
+ platformInputService.onKeyPressed(event.keyCode, event.keyChar)
}
- fun onKeyTyped(char: Char) {
- platformInputService.onKeyTyped(char)
+ fun onKeyReleased(event: KeyEvent) = consumeKeyEventOr(event) {
+ platformInputService.onKeyReleased(event.keyCode, event.keyChar)
}
- fun getInputMethodRequests(): InputMethodRequests? {
- return platformInputService.getInputMethodRequests()
+ fun onKeyTyped(event: KeyEvent) = consumeKeyEventOr(event) {
+ platformInputService.onKeyTyped(event.keyChar)
}
fun onInputMethodTextChanged(event: InputMethodEvent) {
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatform.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatform.kt
index 2f3ae48..8bd07f7 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatform.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatform.kt
@@ -18,28 +18,30 @@
import androidx.compose.runtime.staticAmbientOf
-val DesktopPlatformAmbient = staticAmbientOf(::identifyCurrent)
-
-/**
- * Identify OS on which the application is currently running.
- *
- * If it is needed to know the current platform in @Composable function,
- * use [DesktopPlatformAmbient] instead of this function.
- *
- * identifyCurrent() should be used preferable only in initialization code.
- */
-private fun identifyCurrent(): DesktopPlatform {
- val name = System.getProperty("os.name")
- return when {
- name.startsWith("Linux") -> DesktopPlatform.Linux
- name.startsWith("Win") -> DesktopPlatform.Windows
- name == "Mac OS X" -> DesktopPlatform.MacOS
- else -> throw Error("Unsupported OS $name")
- }
-}
+val DesktopPlatformAmbient = staticAmbientOf(DesktopPlatform::Current)
enum class DesktopPlatform {
Linux,
Windows,
- MacOS
+ MacOS;
+
+ companion object {
+ /**
+ * Identify OS on which the application is currently running.
+ *
+ * If it is needed to know the current platform in @Composable function,
+ * use [DesktopPlatformAmbient] instead of this function, so composable functions can
+ * change their behaviour if we change platform in tests or in application settings
+ * (some applications maybe will have this setting)
+ */
+ val Current: DesktopPlatform by lazy {
+ val name = System.getProperty("os.name")
+ when {
+ name.startsWith("Linux") -> Linux
+ name.startsWith("Win") -> Windows
+ name == "Mac OS X" -> MacOS
+ else -> throw Error("Unsupported OS $name")
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatformInput.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatformInput.kt
index ce281b3..bab8084 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatformInput.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatformInput.kt
@@ -27,13 +27,13 @@
import androidx.compose.ui.text.input.SetComposingTextEditOp
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.substring
-import java.awt.Component
+import java.awt.Point
import java.awt.Rectangle
-import java.awt.event.FocusEvent
import java.awt.event.InputMethodEvent
import java.awt.event.KeyEvent
import java.awt.font.TextHitInfo
import java.awt.im.InputMethodRequests
+import java.lang.UnsupportedOperationException
import java.text.AttributedCharacterIterator
import java.text.AttributedString
import java.text.CharacterIterator
@@ -41,7 +41,14 @@
import kotlin.math.max
import kotlin.math.min
-internal class DesktopPlatformInput(val component: Component) : PlatformTextInputService {
+interface DesktopInputComponent {
+ fun enableInput(inputMethodRequests: InputMethodRequests)
+ fun disableInput()
+ fun locationOnScreen(): Point
+}
+
+internal class DesktopPlatformInput(val component: DesktopComponent) :
+ PlatformTextInputService {
data class CurrentInput(
var value: TextFieldValue,
val onEditCommand: ((List<EditOperation>) -> Unit),
@@ -62,19 +69,16 @@
onEditCommand: (List<EditOperation>) -> Unit,
onImeActionPerformed: (ImeAction) -> Unit
) {
- currentInput = CurrentInput(
+ val input = CurrentInput(
value, onEditCommand, onImeActionPerformed, imeAction
)
+ currentInput = input
- triggerFocus()
- }
-
- private fun triggerFocus() {
- val focusGainedEvent = FocusEvent(component, FocusEvent.FOCUS_GAINED)
- component.inputContext.dispatchEvent(focusGainedEvent)
+ component.enableInput(methodRequestsForInput(input))
}
override fun stopInput() {
+ component.disableInput()
currentInput = null
}
@@ -176,88 +180,83 @@
}
}
- fun getInputMethodRequests(): InputMethodRequests? {
- return currentInput?.let { input ->
- object : InputMethodRequests {
- override fun getLocationOffset(x: Int, y: Int): TextHitInfo? {
- println("InputMethodRequests.getLocationOffset")
- return null
+ fun methodRequestsForInput(input: CurrentInput) =
+ object : InputMethodRequests {
+ override fun getLocationOffset(x: Int, y: Int): TextHitInfo? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun cancelLatestCommittedText(
+ attributes: Array<AttributedCharacterIterator.Attribute>?
+ ): AttributedCharacterIterator? {
+ return null
+ }
+
+ override fun getInsertPositionOffset(): Int {
+ val composedStartIndex = input.value.composition?.start ?: 0
+ val composedEndIndex = input.value.composition?.end ?: 0
+
+ val caretIndex = input.value.selection.start
+ if (caretIndex < composedStartIndex) {
+ return caretIndex
+ }
+ if (caretIndex < composedEndIndex) {
+ return composedStartIndex
+ }
+ return caretIndex - (composedEndIndex - composedStartIndex)
+ }
+
+ override fun getCommittedTextLength() =
+ input.value.text.length - (input.value.composition?.length ?: 0)
+
+ override fun getSelectedText(
+ attributes: Array<AttributedCharacterIterator.Attribute>?
+ ): AttributedCharacterIterator {
+ if (charKeyPressed) {
+ needToDeletePreviousChar = true
+ }
+ val str = input.value.text.substring(input.value.selection)
+ return AttributedString(str).iterator
+ }
+
+ override fun getTextLocation(offset: TextHitInfo) =
+ input.focusedRect?.let {
+ Rectangle(
+ it.right.toInt() + component.locationOnScreen().x,
+ it.bottom.toInt() + component.locationOnScreen().y,
+ 0, 0
+ )
}
- override fun cancelLatestCommittedText(
- attributes: Array<AttributedCharacterIterator.Attribute>?
- ): AttributedCharacterIterator? {
- println("InputMethodRequests.cancelLatestCommittedText")
- return null
+ override fun getCommittedText(
+ beginIndex: Int,
+ endIndex: Int,
+ attributes: Array<AttributedCharacterIterator.Attribute>?
+ ): AttributedCharacterIterator {
+
+ val comp = input.value.composition
+ val text = input.value.text
+ if (comp == null) {
+ val res = text.substring(beginIndex, endIndex)
+ return AttributedString(res).iterator
}
- override fun getInsertPositionOffset(): Int {
- val composedStartIndex = input.value.composition?.start ?: 0
- val composedEndIndex = input.value.composition?.end ?: 0
+ val composedStartIndex = comp.start
+ val composedEndIndex = comp.end
- val caretIndex = input.value.selection.start
- if (caretIndex < composedStartIndex) {
- return caretIndex
- }
- if (caretIndex < composedEndIndex) {
- return composedStartIndex
- }
- return caretIndex - (composedEndIndex - composedStartIndex)
+ val committed: String
+ if (beginIndex < composedStartIndex) {
+ val end = min(endIndex, composedStartIndex)
+ committed = text.substring(beginIndex, end)
+ } else if (composedEndIndex <= endIndex) {
+ val begin = max(composedEndIndex, beginIndex)
+ committed = text.substring(begin, endIndex)
+ } else {
+ committed = ""
}
-
- override fun getCommittedTextLength() =
- input.value.text.length - (input.value.composition?.length ?: 0)
-
- override fun getSelectedText(
- attributes: Array<AttributedCharacterIterator.Attribute>?
- ): AttributedCharacterIterator {
- if (charKeyPressed) {
- needToDeletePreviousChar = true
- }
- val str = input.value.text.substring(input.value.selection)
- return AttributedString(str).iterator
- }
-
- override fun getTextLocation(offset: TextHitInfo) =
- input.focusedRect?.let {
- Rectangle(
- it.right.toInt() + component.locationOnScreen.x,
- it.bottom.toInt() + component.locationOnScreen.y,
- 0, 0
- )
- }
-
- override fun getCommittedText(
- beginIndex: Int,
- endIndex: Int,
- attributes: Array<AttributedCharacterIterator.Attribute>?
- ): AttributedCharacterIterator {
-
- val comp = input.value.composition
- val text = input.value.text
- if (comp == null) {
- val res = text.substring(beginIndex, endIndex)
- return AttributedString(res).iterator
- }
-
- val composedStartIndex = comp.start
- val composedEndIndex = comp.end
-
- val committed: String
- if (beginIndex < composedStartIndex) {
- val end = min(endIndex, composedStartIndex)
- committed = text.substring(beginIndex, end)
- } else if (composedEndIndex <= endIndex) {
- val begin = max(composedEndIndex, beginIndex)
- committed = text.substring(begin, endIndex)
- } else {
- committed = ""
- }
- return AttributedString(committed).iterator
- }
+ return AttributedString(committed).iterator
}
}
- }
}
private fun AttributedCharacterIterator.toStringUntil(index: Int): String {
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelection.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelection.kt
index 5bb4d16..b58ac1b 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelection.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelection.kt
@@ -22,6 +22,7 @@
import androidx.compose.ui.Layout
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
+import androidx.compose.ui.focus.ExperimentalFocus
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.gesture.DragObserver
import androidx.compose.ui.gesture.rawDragGestureFilter
@@ -29,6 +30,7 @@
import androidx.compose.ui.onGloballyPositioned
import androidx.compose.ui.selection.Selection
import androidx.compose.ui.selection.SelectionRegistrarAmbient
+import androidx.compose.ui.selection.SelectionRegistrarImpl
import kotlin.math.max
@Composable
@@ -89,16 +91,22 @@
}
}
+@OptIn(ExperimentalFocus::class)
@Composable
fun DesktopSelectionContainer(
selection: Selection?,
onSelectionChange: (Selection?) -> Unit,
children: @Composable () -> Unit
) {
- val registrarImpl = remember { DesktopSelectionRegistrar() }
+ val registrarImpl = remember { SelectionRegistrarImpl() }
val manager = remember { DesktopSelectionManager(registrarImpl) }
- manager.onSelectionChange = onSelectionChange
+ val managerTracker = SelectionManagerTrackerAmbient.current
+
+ manager.onSelectionChange = {
+ managerTracker.recentManager = manager
+ onSelectionChange(it)
+ }
manager.selection = selection
val gestureModifiers =
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelectionClipboard.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelectionClipboard.kt
new file mode 100644
index 0000000..6e505b29
--- /dev/null
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelectionClipboard.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.compose.ui.platform
+
+import androidx.compose.runtime.staticAmbientOf
+import androidx.compose.ui.input.key.Key
+import androidx.compose.ui.input.key.plus
+
+val SelectionManagerTrackerAmbient = staticAmbientOf<SelectionManagerTracker>()
+
+class SelectionManagerTracker {
+ internal var recentManager: DesktopSelectionManager? = null
+}
+
+val copyToClipboardKeySet by lazy {
+ when (DesktopPlatform.Current) {
+ DesktopPlatform.MacOS -> Key.MetaLeft + Key.C
+ else -> Key.CtrlLeft + Key.C
+ }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelectionManager.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelectionManager.kt
index 253b6c7..8cf64c5 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelectionManager.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopSelectionManager.kt
@@ -21,8 +21,12 @@
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.selection.Selectable
import androidx.compose.ui.selection.Selection
+import androidx.compose.ui.selection.SelectionRegistrarImpl
+import androidx.compose.ui.selection.getCurrentSelectedText
+import androidx.compose.ui.selection.merge
+import androidx.compose.ui.text.AnnotatedString
-internal class DesktopSelectionManager(private val selectionRegistrar: DesktopSelectionRegistrar) {
+internal class DesktopSelectionManager(private val selectionRegistrar: SelectionRegistrarImpl) {
private var dragBeginPosition = Offset.Zero
private var dragTotalDistance = Offset.Zero
@@ -91,8 +95,30 @@
require(coordinates.isAttached)
return coordinates
}
-}
-private fun merge(lhs: Selection?, rhs: Selection?): Selection? {
- return lhs?.merge(rhs) ?: rhs
+ internal fun getSelectedText(): AnnotatedString? {
+ val selectables = selectionRegistrar.sort(requireContainerCoordinates())
+ var selectedText: AnnotatedString? = null
+
+ selection?.let {
+ for (handler in selectables) {
+ // Continue if the current selectable is before the selection starts.
+ if (handler != it.start.selectable && handler != it.end.selectable &&
+ selectedText == null
+ ) continue
+
+ val currentSelectedText = getCurrentSelectedText(
+ selectable = handler,
+ selection = it
+ )
+ selectedText = selectedText?.plus(currentSelectedText) ?: currentSelectedText
+
+ // Break if the current selectable is the last selected selectable.
+ if (handler == it.end.selectable && !it.handlesCrossed ||
+ handler == it.start.selectable && it.handlesCrossed
+ ) break
+ }
+ }
+ return selectedText
+ }
}
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopTextToolbar.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopTextToolbar.kt
index e6a499d..a0b6ee8 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopTextToolbar.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopTextToolbar.kt
@@ -31,7 +31,8 @@
rect: Rect,
onCopyRequested: ActionCallback?,
onPasteRequested: ActionCallback?,
- onCutRequested: ActionCallback?
+ onCutRequested: ActionCallback?,
+ onSelectAllRequested: ActionCallback?
) {
println("TextToolbar.showMenu not implemented yet")
}
diff --git a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/FrameDispatcher.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/FrameDispatcher.kt
similarity index 91%
rename from compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/FrameDispatcher.kt
rename to compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/FrameDispatcher.kt
index 96803b3..6f2d283 100644
--- a/compose/desktop/desktop/src/jvmMain/kotlin/androidx/compose/desktop/FrameDispatcher.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/FrameDispatcher.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.compose.desktop
+package androidx.compose.ui.platform
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers
@@ -29,9 +29,9 @@
*
* Frames executed not more frequent than [framesPerSecond]
*/
-internal class FrameDispatcher(
+class FrameDispatcher(
private val onFrame: suspend (nanoTime: Long) -> Unit,
- private val framesPerSecond: () -> Int,
+ private val framesPerSecond: () -> Float,
private val nanoTime: () -> Long = System::nanoTime,
context: CoroutineContext = Dispatchers.Main
) {
@@ -47,7 +47,7 @@
val elapsed = nanoTime() - frameNanoTime
val refreshRate = framesPerSecond()
- val singleFrameNanos = 1_000_000_000 / refreshRate
+ val singleFrameNanos = (1_000_000_000 / refreshRate).toLong()
val needToWaitMillis = maxOf(0, singleFrameNanos - elapsed) / 1_000_000
delayOrYield(needToWaitMillis)
}
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/Keyboard.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/Keyboard.kt
new file mode 100644
index 0000000..efc9bfa
--- /dev/null
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/Keyboard.kt
@@ -0,0 +1,65 @@
+/*
+ * 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.compose.ui.platform
+
+import androidx.compose.ui.input.key.ExperimentalKeyInput
+import androidx.compose.ui.input.key.Key
+import androidx.compose.ui.input.key.KeyEvent
+import androidx.compose.ui.input.key.KeysSet
+import androidx.compose.ui.input.key.ShortcutInstance
+import java.lang.RuntimeException
+
+class AmbiguousShortcut(val superKeysSet: KeysSet) : RuntimeException()
+
+interface KeyboardShortcutHandler {
+ fun cancel()
+}
+
+@ExperimentalKeyInput
+class Keyboard {
+ private val shortcuts = mutableListOf<ShortcutInstance>()
+
+ fun shortcut(key: Key, callback: () -> Unit) = shortcut(KeysSet(listOf(key)), callback)
+
+ fun shortcut(keysSet: KeysSet, callback: () -> Unit): KeyboardShortcutHandler {
+ checkAmbiguityOfShortcut(keysSet)
+ val instance = ShortcutInstance(keysSet, callback)
+ shortcuts.add(instance)
+ return object : KeyboardShortcutHandler {
+ override fun cancel() {
+ shortcuts.remove(instance)
+ }
+ }
+ }
+
+ private fun checkAmbiguityOfShortcut(keysSet: KeysSet) {
+ shortcuts.forEach {
+ if (keysSet.isSubset(it.keysSet)) {
+ throw(AmbiguousShortcut(it.keysSet))
+ }
+ }
+ }
+
+ internal fun processKeyInput(keyEvent: KeyEvent): Boolean {
+ shortcuts.forEach {
+ if (it.process(keyEvent)) {
+ return true
+ }
+ }
+ return false
+ }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.kt
index 692d3f5..abdaf46 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.kt
@@ -49,6 +49,7 @@
private var outlineCache = OutlineCache(density, size, modifier.shape)
private val pictureRecorder = PictureRecorder()
private var picture: Picture? = null
+ private var isDestroyed = false
override var modifier: DrawLayerModifier = modifier
set(value) {
@@ -62,6 +63,7 @@
override fun destroy() {
picture?.close()
pictureRecorder.close()
+ isDestroyed = true
}
override fun resize(size: IntSize) {
@@ -85,8 +87,11 @@
}
override fun invalidate() {
- picture = null
- invalidateParentLayer()
+ if (!isDestroyed && picture != null) {
+ picture?.close()
+ picture = null
+ invalidateParentLayer()
+ }
}
override fun drawLayer(canvas: Canvas) {
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/Wrapper.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/Wrapper.kt
index 3d98db3..671389d 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/Wrapper.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/Wrapper.kt
@@ -23,10 +23,11 @@
import androidx.compose.runtime.Providers
import androidx.compose.runtime.Recomposer
import androidx.compose.runtime.compositionFor
+import androidx.compose.ui.input.key.ExperimentalKeyInput
import androidx.compose.ui.node.ExperimentalLayoutNodeApi
import androidx.compose.ui.node.LayoutNode
-@OptIn(ExperimentalComposeApi::class)
+@OptIn(ExperimentalComposeApi::class, ExperimentalKeyInput::class)
fun DesktopOwner.setContent(content: @Composable () -> Unit): Composition {
FrameManager.ensureStarted()
@@ -37,13 +38,23 @@
}
}
+ keyboard?.shortcut(copyToClipboardKeySet) {
+ selectionManager.recentManager?.let { selector ->
+ selector.getSelectedText()?.let {
+ clipboardManager.setText(it)
+ }
+ }
+ }
+
return composition
}
+@OptIn(ExperimentalKeyInput::class)
@Composable
private fun ProvideDesktopAmbients(owner: DesktopOwner, content: @Composable () -> Unit) {
Providers(
- DesktopOwnersAmbient provides owner.container
+ DesktopOwnersAmbient provides owner.container,
+ SelectionManagerTrackerAmbient provides owner.selectionManager
) {
ProvideCommonAmbients(
owner = owner,
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
index 37a2e36..4d50d82 100644
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
@@ -16,26 +16,62 @@
package androidx.compose.ui.platform
+import androidx.compose.animation.animate
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.TweenSpec
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumnFor
import androidx.compose.runtime.ExperimentalComposeApi
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.Snapshot
+import androidx.compose.ui.Layout
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clipToBounds
+import androidx.compose.ui.drawLayer
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.gesture.scrollorientationlocking.Orientation
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.mouse.MouseScrollEvent
+import androidx.compose.ui.input.mouse.MouseScrollUnit
import androidx.compose.ui.node.ExperimentalLayoutNodeApi
import androidx.compose.ui.node.LayoutNode
-import org.jetbrains.skiko.Library
+import androidx.compose.ui.unit.dp
+import androidx.ui.test.DesktopScreenshotTestRule
+import androidx.ui.test.initCompose
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Rule
import org.junit.Test
-import java.awt.Component
-@OptIn(ExperimentalLayoutNodeApi::class, ExperimentalComposeApi::class)
+@OptIn(
+ ExperimentalLayoutNodeApi::class,
+ ExperimentalComposeApi::class,
+ ExperimentalCoroutinesApi::class
+)
class DesktopOwnerTest {
+ @get:Rule
+ val screenshotRule = DesktopScreenshotTestRule("ui/ui-desktop/ui")
+
@Test
fun `single invalidate with multiple observers and single state change`() {
- Library.load("/", "skiko")
+ initCompose()
var invalidateCount = 0
val owners = DesktopOwners(
- component = object : Component() {},
invalidate = {
invalidateCount++
}
@@ -60,4 +96,283 @@
assertEquals(1, invalidateCount - oldInvalidateCount)
}
+
+ @Test(timeout = 5000)
+ fun `rendering of Box state change`() = renderingTest(width = 40, height = 40) {
+ var size by mutableStateOf(20.dp)
+ setContent {
+ Box(Modifier.size(size).background(Color.Blue))
+ }
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame1_initial_size_20")
+ assertFalse(hasRenders())
+
+ size = 10.dp
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame2_change_size_to_10")
+ assertFalse(hasRenders())
+
+ size = 5.dp
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame3_change_size_to_5")
+ assertFalse(hasRenders())
+
+ size = 10.dp
+ size = 20.dp
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame4_change_size_to_10_and_20")
+ assertFalse(hasRenders())
+
+ size = 20.dp
+ assertFalse(hasRenders())
+ }
+
+ @Test(timeout = 5000)
+ fun `rendering of Canvas state change`() = renderingTest(width = 40, height = 40) {
+ var x by mutableStateOf(0f)
+ var clipToBounds by mutableStateOf(false)
+ setContent {
+ val modifier = if (clipToBounds) {
+ Modifier.size(20.dp).clipToBounds()
+ } else {
+ Modifier.size(20.dp)
+ }
+ Canvas(modifier) {
+ drawRect(
+ color = Color.Red,
+ topLeft = Offset(x, 0f),
+ size = Size(10f, 10f)
+ )
+ }
+ }
+
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame1_initial")
+ assertFalse(hasRenders())
+
+ x = 15f
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame2_translate")
+ assertFalse(hasRenders())
+
+ clipToBounds = true
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame3_clipToBounds")
+ assertFalse(hasRenders())
+ }
+
+ @Test(timeout = 5000)
+ fun `rendering of Layout state change`() = renderingTest(width = 40, height = 40) {
+ var width by mutableStateOf(10)
+ var height by mutableStateOf(20)
+ var x by mutableStateOf(0)
+ setContent {
+ Row(Modifier.height(height.dp)) {
+ Layout({
+ Box(Modifier.fillMaxSize().background(Color.Green))
+ }) { measureables, constraints ->
+ val placeables = measureables.map { it.measure(constraints) }
+ layout(width, constraints.maxHeight) {
+ placeables.forEach { it.place(x, 0) }
+ }
+ }
+
+ Box(Modifier.background(Color.Red).size(10.dp))
+ }
+ }
+
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame1_initial")
+ assertFalse(hasRenders())
+
+ width = 20
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame2_change_width")
+ assertFalse(hasRenders())
+
+ x = 10
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame3_change_x")
+ assertFalse(hasRenders())
+
+ height = 10
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame4_change_height")
+ assertFalse(hasRenders())
+
+ width = 10
+ height = 20
+ x = 0
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame5_change_all")
+ assertFalse(hasRenders())
+
+ width = 10
+ height = 20
+ x = 0
+ assertFalse(hasRenders())
+ }
+
+ @Test(timeout = 5000)
+ fun `rendering of layer offset`() = renderingTest(width = 40, height = 40) {
+ var translationX by mutableStateOf(10f)
+ var offsetX by mutableStateOf(10.dp)
+ setContent {
+ Box(Modifier.offset(x = offsetX).drawLayer(translationX = translationX)) {
+ Box(Modifier.background(Color.Green).size(10.dp))
+ }
+ }
+
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame1_initial")
+ assertFalse(hasRenders())
+
+ offsetX -= 10.dp
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame2_offset")
+ assertFalse(hasRenders())
+
+ translationX -= 10f
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame3_translation")
+ assertFalse(hasRenders())
+
+ offsetX += 10.dp
+ translationX += 10f
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame4_offset_and_translation")
+ assertFalse(hasRenders())
+ }
+
+ @Test(timeout = 5000)
+ fun `rendering of transition`() = renderingTest(width = 40, height = 40) {
+ var targetValue by mutableStateOf(10f)
+
+ setContent {
+ val value = animate(
+ targetValue,
+ animSpec = TweenSpec(durationMillis = 30, easing = LinearEasing)
+ )
+ Box(Modifier.size(value.dp).background(Color.Blue))
+ }
+
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame1_initial")
+
+ currentTimeMillis = 20
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame2_20ms")
+
+ currentTimeMillis = 30
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame3_30ms")
+ assertFalse(hasRenders())
+
+ targetValue = 40f
+ currentTimeMillis = 30
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame4_30ms_target40")
+
+ currentTimeMillis = 40
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame5_40ms_target40")
+
+ currentTimeMillis = 50
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame6_50ms_target40")
+
+ currentTimeMillis = 60
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame7_60ms_target40")
+ assertFalse(hasRenders())
+ }
+
+ @Test(timeout = 5000)
+ fun `rendering of clickable`() = renderingTest(width = 40, height = 40) {
+ setContent {
+ Box(Modifier.size(20.dp).background(Color.Blue).clickable {})
+ }
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame1_initial")
+ assertFalse(hasRenders())
+
+ owners.onMousePressed(2, 2)
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame2_onMousePressed")
+ assertFalse(hasRenders())
+
+ owners.onMouseMoved(1, 1)
+ assertFalse(hasRenders())
+
+ owners.onMouseReleased(1, 1)
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame3_onMouseReleased")
+
+ owners.onMouseMoved(1, 1)
+ owners.onMousePressed(3, 3)
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame4_onMouseMoved_onMousePressed")
+ assertFalse(hasRenders())
+ }
+
+ @Test(timeout = 5000)
+ fun `rendering of LazyColumn`() = renderingTest(
+ width = 40,
+ height = 40,
+ platform = DesktopPlatform.Windows // scrolling behave differently on different platforms
+ ) {
+ var height by mutableStateOf(10.dp)
+ setContent {
+ Box(Modifier.padding(10.dp)) {
+ LazyColumnFor(
+ listOf(Color.Red, Color.Green, Color.Blue, Color.Black, Color.Gray)
+ ) { color ->
+ Box(Modifier.size(width = 30.dp, height = height).background(color))
+ }
+ }
+ }
+
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame1_initial")
+ assertFalse(hasRenders())
+
+ owners.onMouseScroll(
+ 10,
+ 10,
+ MouseScrollEvent(MouseScrollUnit.Page(1f), Orientation.Vertical)
+ )
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame2_onMouseScroll")
+ assertFalse(hasRenders())
+
+ owners.onMouseScroll(
+ 10,
+ 10,
+ MouseScrollEvent(MouseScrollUnit.Page(10f), Orientation.Vertical)
+ )
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame3_onMouseScroll")
+ assertFalse(hasRenders())
+
+ height = 5.dp
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame4_change_height")
+ assertFalse(hasRenders())
+ }
+
+ @Test(timeout = 5000)
+ fun `rendering, change state before first onRender`() = renderingTest(
+ width = 40,
+ height = 40
+ ) {
+ var size by mutableStateOf(20.dp)
+ setContent {
+ Box(Modifier.size(size).background(Color.Blue))
+ }
+
+ size = 10.dp
+ awaitNextRender()
+ screenshotRule.snap(surface, "frame1_initial")
+ assertFalse(hasRenders())
+ }
}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt
new file mode 100644
index 0000000..bf20216
--- /dev/null
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.compose.ui.platform
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Providers
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import androidx.ui.test.initCompose
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.yield
+import org.jetbrains.skija.Canvas
+import org.jetbrains.skija.Surface
+
+internal fun renderingTest(
+ width: Int,
+ height: Int,
+ platform: DesktopPlatform = DesktopPlatform.Linux,
+ block: suspend RenderingTestScope.() -> Unit
+) = runBlocking(Dispatchers.Main) {
+ initCompose()
+ val scope = RenderingTestScope(width, height, platform)
+ try {
+ scope.block()
+ } finally {
+ scope.owner?.dispose()
+ scope.frameDispatcher.cancel()
+ }
+}
+
+internal class RenderingTestScope(
+ private val width: Int,
+ private val height: Int,
+ private val platform: DesktopPlatform
+) {
+ var currentTimeMillis = 0L
+
+ val frameDispatcher = FrameDispatcher(
+ onFrame = { onRender(it) },
+ framesPerSecond = { Float.POSITIVE_INFINITY },
+ nanoTime = { currentTimeMillis * 1_000_000 }
+ )
+
+ val surface: Surface = Surface.makeRasterN32Premul(width, height)
+ val canvas: Canvas = surface.canvas
+ val owners = DesktopOwners(
+ invalidate = frameDispatcher::scheduleFrame
+ )
+ var owner: DesktopOwner? = null
+
+ private var onRender = CompletableDeferred<Unit>()
+
+ fun setContent(content: @Composable () -> Unit) {
+ owner?.dispose()
+ val owner = DesktopOwner(owners)
+ owner.setContent {
+ Providers(DesktopPlatformAmbient provides platform) {
+ content()
+ }
+ }
+ this.owner = owner
+ }
+
+ private suspend fun onRender(timeNanos: Long) {
+ canvas.clear(Color.Transparent.toArgb())
+ owners.onFrame(canvas, width, height, timeNanos)
+ onRender.complete(Unit)
+ }
+
+ suspend fun awaitNextRender() {
+ onRender = CompletableDeferred()
+ onRender.await()
+ }
+
+ suspend fun hasRenders(): Boolean {
+ onRender = CompletableDeferred()
+ // repeat multiple times because rendering can be dispatched on the next frames
+ repeat(10) {
+ yield()
+ }
+ return onRender.isCompleted
+ }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawDragGestureFilterTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawDragGestureFilterTest.kt
index b7a03a0..3841389 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawDragGestureFilterTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawDragGestureFilterTest.kt
@@ -781,9 +781,9 @@
// Assert
if (!blocked && (
- filterOrientation == Orientation.Horizontal && dx != 0f ||
- filterOrientation == Orientation.Vertical && dy != 0f
- )
+ filterOrientation == Orientation.Horizontal && dx != 0f ||
+ filterOrientation == Orientation.Vertical && dy != 0f
+ )
) {
assertThat(scrollOrientationLocker.getPointersFor(listOf(move), otherOrientation))
.hasSize(0)
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawScaleGestureFilterTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawScaleGestureFilterTest.kt
index fbec627..c9b2f60 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawScaleGestureFilterTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawScaleGestureFilterTest.kt
@@ -676,7 +676,7 @@
)
.isEqualTo(Offset(-1f, 0f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -712,7 +712,7 @@
// Assert
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -720,7 +720,7 @@
)
.isEqualTo(Offset(0f, -1f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -742,7 +742,7 @@
val result = filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(change1, change2))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -750,7 +750,7 @@
)
.isEqualTo(Offset(-1f, -1f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -773,7 +773,7 @@
change2 = change2.moveTo(10.milliseconds, 6f, 0f)
scaleObserver.resultingScaleChange = .75f
var result = filter::onPointerEvent.invokeOverPasses(
- pointerEventOf(change1, change2),
+ pointerEventOf(change1, change2),
listOf(
PointerEventPass.Initial,
PointerEventPass.Main
@@ -786,7 +786,7 @@
// Assert
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -794,7 +794,7 @@
)
.isEqualTo(Offset(1f, 0f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -817,7 +817,7 @@
change2 = change2.moveTo(10.milliseconds, 0f, 6f)
scaleObserver.resultingScaleChange = .75f
var result = filter::onPointerEvent.invokeOverPasses(
- pointerEventOf(change1, change2),
+ pointerEventOf(change1, change2),
listOf(
PointerEventPass.Initial,
PointerEventPass.Main
@@ -830,7 +830,7 @@
// Assert
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -838,7 +838,7 @@
)
.isEqualTo(Offset(0f, 1f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -877,7 +877,7 @@
change2 = change2.moveTo(10.milliseconds, 8f, 0f)
scaleObserver.resultingScaleChange = 2f
var result = filter::onPointerEvent.invokeOverPasses(
- pointerEventOf(change1, change2),
+ pointerEventOf(change1, change2),
listOf(
PointerEventPass.Initial,
PointerEventPass.Main
@@ -892,7 +892,7 @@
// Assert
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -900,7 +900,7 @@
)
.isEqualTo(Offset(-1f, 0f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -923,7 +923,7 @@
change2 = change2.moveTo(10.milliseconds, 0f, 8f)
scaleObserver.resultingScaleChange = 2f
var result = filter::onPointerEvent.invokeOverPasses(
- pointerEventOf(change1, change2),
+ pointerEventOf(change1, change2),
listOf(
PointerEventPass.Initial,
PointerEventPass.Main
@@ -936,7 +936,7 @@
// Assert
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -944,7 +944,7 @@
)
.isEqualTo(Offset(0f, -1f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -967,7 +967,7 @@
change2 = change2.moveTo(10.milliseconds, 4f, 0f)
scaleObserver.resultingScaleChange = .75f
var result = filter::onPointerEvent.invokeOverPasses(
- pointerEventOf(change1, change2),
+ pointerEventOf(change1, change2),
listOf(
PointerEventPass.Initial,
PointerEventPass.Main
@@ -980,7 +980,7 @@
// Assert
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -988,7 +988,7 @@
)
.isEqualTo(Offset(1f, 0f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -1011,7 +1011,7 @@
change2 = change2.moveTo(10.milliseconds, 0f, 4f)
scaleObserver.resultingScaleChange = .75f
var result = filter::onPointerEvent.invokeOverPasses(
- pointerEventOf(change1, change2),
+ pointerEventOf(change1, change2),
listOf(
PointerEventPass.Initial,
PointerEventPass.Main
@@ -1024,7 +1024,7 @@
// Assert
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -1032,7 +1032,7 @@
)
.isEqualTo(Offset(0f, 1f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -1055,7 +1055,7 @@
change2 = change2.moveTo(10.milliseconds, 0f, 3f)
scaleObserver.resultingScaleChange = 2f
var result = filter::onPointerEvent.invokeOverPasses(
- pointerEventOf(change1, change2),
+ pointerEventOf(change1, change2),
listOf(
PointerEventPass.Initial,
PointerEventPass.Main
@@ -1068,7 +1068,7 @@
// Assert
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -1076,7 +1076,7 @@
)
.isEqualTo(Offset(.5f, -1.5f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -1099,7 +1099,7 @@
change2 = change2.moveTo(10.milliseconds, 0f, 2f)
scaleObserver.resultingScaleChange = .75f
var result = filter::onPointerEvent.invokeOverPasses(
- pointerEventOf(change1, change2),
+ pointerEventOf(change1, change2),
listOf(
PointerEventPass.Initial,
PointerEventPass.Main
@@ -1112,7 +1112,7 @@
// Assert
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
@@ -1120,7 +1120,7 @@
)
.isEqualTo(Offset(2f, -1f))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
1
)
@@ -1175,7 +1175,7 @@
val result = filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(change1, change2))
assertThat(
- result.changes.first {
+ result.changes.first {
it.id == PointerId(
0
)
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/selection/SelectionManagerTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/selection/SelectionManagerTest.kt
index fcdcf38..a4927cc 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/selection/SelectionManagerTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/selection/SelectionManagerTest.kt
@@ -382,6 +382,7 @@
eq(Rect.Zero),
any(),
isNull(),
+ isNull(),
isNull()
)
}
diff --git a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContactsBasedTest.kt b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContactsBasedTest.kt
index 02f4af1..c5e24d6 100644
--- a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContactsBasedTest.kt
+++ b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContactsBasedTest.kt
@@ -37,8 +37,11 @@
@get:Rule
var storagePermissions =
- GrantPermissionRule.grant(Manifest.permission.READ_CONTACTS, Manifest.permission
- .WRITE_CONTACTS)!!
+ GrantPermissionRule.grant(
+ Manifest.permission.READ_CONTACTS,
+ Manifest.permission
+ .WRITE_CONTACTS
+ )!!
@Before
fun setup() {
diff --git a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentDeleteTest.kt b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentDeleteTest.kt
index d88350d..c0efdb2 100644
--- a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentDeleteTest.kt
+++ b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentDeleteTest.kt
@@ -116,12 +116,18 @@
@Test
fun testDeleteAllItems() {
- val beforeDeletionCursor = contentResolver.query(MediaStore.Images.Media
- .EXTERNAL_CONTENT_URI, arrayOf(MediaStore.Images.Media.TITLE), null, null, null)!!
+ val beforeDeletionCursor = contentResolver.query(
+ MediaStore.Images.Media
+ .EXTERNAL_CONTENT_URI,
+ arrayOf(MediaStore.Images.Media.TITLE), null, null, null
+ )!!
assertThat(beforeDeletionCursor.count).isEqualTo(3)
assertThat(imageAccessor.deleteAll()).isEqualTo(3)
- val afterDeletionCursor = contentResolver.query(MediaStore.Images.Media
- .EXTERNAL_CONTENT_URI, arrayOf(MediaStore.Images.Media.TITLE), null, null, null)!!
+ val afterDeletionCursor = contentResolver.query(
+ MediaStore.Images.Media
+ .EXTERNAL_CONTENT_URI,
+ arrayOf(MediaStore.Images.Media.TITLE), null, null, null
+ )!!
assertThat(afterDeletionCursor.count).isEqualTo(0)
}
diff --git a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentQueryTest.kt b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentQueryTest.kt
index 935650c..60612ec 100644
--- a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentQueryTest.kt
+++ b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentQueryTest.kt
@@ -51,8 +51,11 @@
@JvmField
@Rule
var storagePermissions =
- GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission
- .WRITE_EXTERNAL_STORAGE)!!
+ GrantPermissionRule.grant(
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission
+ .WRITE_EXTERNAL_STORAGE
+ )!!
@Before
fun setup() {
@@ -80,10 +83,14 @@
// For the tests to work properly in terms of the expected results, the provider should not
// have prior rows, so make sure we delete everything at the end of the tests for proper
// local testing.
- contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- MediaStore.Images.Media.MIME_TYPE + "=?", arrayOf("image/jpeg"))
- contentResolver.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
- "", null)
+ contentResolver.delete(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ MediaStore.Images.Media.MIME_TYPE + "=?", arrayOf("image/jpeg")
+ )
+ contentResolver.delete(
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+ "", null
+ )
}
@ContentAccessObject(Image::class)
@@ -197,23 +204,28 @@
@Test
fun testUseUriInAnnotation() {
val imageAccessorEntityWithNoUri = ContentAccess.getAccessor(
- ImageAccessorEntityWithNoUri::class, contentResolver)
+ ImageAccessorEntityWithNoUri::class, contentResolver
+ )
assertThat(imageAccessorEntityWithNoUri.getSingleElement()!!.title).isEqualTo("title1")
}
@Test
fun testUseUriInArgument() {
val imageAccessorEntityWithNoUri = ContentAccess.getAccessor(
- ImageAccessorEntityWithNoUri::class, contentResolver)
- assertThat(imageAccessorEntityWithNoUri
- .getSingleElementWithArgumentUri("content://media/external/images/media")!!.title)
+ ImageAccessorEntityWithNoUri::class, contentResolver
+ )
+ assertThat(
+ imageAccessorEntityWithNoUri
+ .getSingleElementWithArgumentUri("content://media/external/images/media")!!.title
+ )
.isEqualTo("title1")
}
@Test
fun testUseEntityInAnnotation() {
val imageAccessorWithNoEntity = ContentAccess.getAccessor(
- ImageAccessorWithNoEntity::class, contentResolver)
+ ImageAccessorWithNoEntity::class, contentResolver
+ )
assertThat(imageAccessorWithNoEntity.getSingleElement()!!.title).isEqualTo("title1")
}
@@ -368,8 +380,10 @@
@Test
fun testProperlyQueriesWithSelectionAndSelectionArgs() {
- val result = imageAccessor.getPojoMatchingSelectionWithSelectionArgs("title2",
- "description2")
+ val result = imageAccessor.getPojoMatchingSelectionWithSelectionArgs(
+ "title2",
+ "description2"
+ )
assertThat(result.size).isEqualTo(1)
assertThat(result.first().description).isEqualTo("description2")
}
@@ -387,8 +401,10 @@
@Test
fun testOrderByMultipleFields() {
// Delete all the added ones
- contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- MediaStore.Images.Media.MIME_TYPE + "=?", arrayOf("image/jpeg"))
+ contentResolver.delete(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ MediaStore.Images.Media.MIME_TYPE + "=?", arrayOf("image/jpeg")
+ )
val values = ContentValues().apply {
put(TITLE, "title1")
diff --git a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentUpdateTest.kt b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentUpdateTest.kt
index 377db1b..0e408bd 100644
--- a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentUpdateTest.kt
+++ b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/ContentUpdateTest.kt
@@ -86,11 +86,13 @@
@Test
fun testUseUriInAnnotation() {
val contactsAccessorEntityWithNoUri = ContentAccess.getAccessor(
- ContactsAccessorEntityWithNoUri::class, contentResolver)
+ ContactsAccessorEntityWithNoUri::class, contentResolver
+ )
assertThat(contactsAccessorEntityWithNoUri.updateAllDisplayNames("updated-displayName"))
.isEqualTo(2)
val cursor = contentResolver.query(
- CONTENT_URI, arrayOf(DISPLAY_NAME), null, null, null)!!
+ CONTENT_URI, arrayOf(DISPLAY_NAME), null, null, null
+ )!!
cursor.moveToFirst()
assertThat(cursor.getString(0)).isEqualTo("updated-displayName")
}
@@ -98,13 +100,17 @@
@Test
fun testUseUriInArgument() {
val contactsAccessorEntityWithNoUri = ContentAccess.getAccessor(
- ContactsAccessorEntityWithNoUri::class, contentResolver)
- assertThat(contactsAccessorEntityWithNoUri.updateDisplayNameWithUriArgument(
- "updated-displayName",
- "content://com.android.contacts/raw_contacts")
+ ContactsAccessorEntityWithNoUri::class, contentResolver
+ )
+ assertThat(
+ contactsAccessorEntityWithNoUri.updateDisplayNameWithUriArgument(
+ "updated-displayName",
+ "content://com.android.contacts/raw_contacts"
+ )
).isEqualTo(2)
val cursor = contentResolver.query(
- CONTENT_URI, arrayOf(DISPLAY_NAME), null, null, null)!!
+ CONTENT_URI, arrayOf(DISPLAY_NAME), null, null, null
+ )!!
cursor.moveToFirst()
assertThat(cursor.getString(0)).isEqualTo("updated-displayName")
}
@@ -112,22 +118,39 @@
@Test
fun testUseEntityInAnnotation() {
val contactsAccessorWithNoEntity = ContentAccess.getAccessor(
- ContactsAccessorWithNoEntity::class, contentResolver)
- assertThat(contactsAccessorWithNoEntity
- .updateDisplayName("updated-description")).isEqualTo(2)
- val cursor = contentResolver.query(CONTENT_URI, arrayOf(
- DISPLAY_NAME), null, null, null)!!
+ ContactsAccessorWithNoEntity::class, contentResolver
+ )
+ assertThat(
+ contactsAccessorWithNoEntity
+ .updateDisplayName("updated-description")
+ ).isEqualTo(2)
+ val cursor = contentResolver.query(
+ CONTENT_URI,
+ arrayOf(
+ DISPLAY_NAME
+ ),
+ null, null, null
+ )!!
cursor.moveToFirst()
assertThat(cursor.getString(0)).isEqualTo("updated-description")
}
@Test
fun testUpdatesAllColumns() {
- assertThat(contactsAccessor.updateDisplayNamesAndDisplayNamesPrimary("updated-display-name",
- "updated-display-name-source"))
+ assertThat(
+ contactsAccessor.updateDisplayNamesAndDisplayNamesPrimary(
+ "updated-display-name",
+ "updated-display-name-source"
+ )
+ )
.isEqualTo(2)
- val cursor = contentResolver.query(CONTENT_URI, arrayOf(
- DISPLAY_NAME, DISPLAY_NAME_SOURCE), null, null, null)!!
+ val cursor = contentResolver.query(
+ CONTENT_URI,
+ arrayOf(
+ DISPLAY_NAME, DISPLAY_NAME_SOURCE
+ ),
+ null, null, null
+ )!!
cursor.moveToFirst()
assertThat(cursor.getString(0)).isEqualTo("updated-display-name")
assertThat(cursor.getString(1)).isEqualTo("updated-display-name-source")
@@ -136,12 +159,21 @@
@Test
fun testSuspendingUpdatesAllColumns() {
runBlocking {
- assertThat(contactsAccessor.suspendingUpdateDisplayNamesAndDisplayNamesPrimary
- ("updated-display-name",
- "updated-display-name-source"))
+ assertThat(
+ contactsAccessor.suspendingUpdateDisplayNamesAndDisplayNamesPrimary
+ (
+ "updated-display-name",
+ "updated-display-name-source"
+ )
+ )
.isEqualTo(2)
- val cursor = contentResolver.query(CONTENT_URI, arrayOf(
- DISPLAY_NAME, DISPLAY_NAME_SOURCE), null, null, null)!!
+ val cursor = contentResolver.query(
+ CONTENT_URI,
+ arrayOf(
+ DISPLAY_NAME, DISPLAY_NAME_SOURCE
+ ),
+ null, null, null
+ )!!
cursor.moveToFirst()
assertThat(cursor.getString(0)).isEqualTo("updated-display-name")
assertThat(cursor.getString(1)).isEqualTo("updated-display-name-source")
@@ -150,11 +182,18 @@
@Test
fun testUpdatesColumnsWithSelection() {
- assertThat(contactsAccessor.updateDisplayNameWithWhereConditionNoSelectionArgs(
- "updated-display-name")
+ assertThat(
+ contactsAccessor.updateDisplayNameWithWhereConditionNoSelectionArgs(
+ "updated-display-name"
+ )
).isEqualTo(1)
- val cursor = contentResolver.query(CONTENT_URI, arrayOf(
- DISPLAY_NAME), null, null, null)!!
+ val cursor = contentResolver.query(
+ CONTENT_URI,
+ arrayOf(
+ DISPLAY_NAME
+ ),
+ null, null, null
+ )!!
cursor.moveToFirst()
assertThat(cursor.getString(0)).isEqualTo("updated-display-name")
}
@@ -167,8 +206,13 @@
"displayName2"
)
).isEqualTo(1)
- val cursor = contentResolver.query(CONTENT_URI, arrayOf(
- DISPLAY_NAME), "$DISPLAY_NAME_SOURCE=?", arrayOf("displayNameSource2"), null)!!
+ val cursor = contentResolver.query(
+ CONTENT_URI,
+ arrayOf(
+ DISPLAY_NAME
+ ),
+ "$DISPLAY_NAME_SOURCE=?", arrayOf("displayNameSource2"), null
+ )!!
cursor.moveToFirst()
assertThat(cursor.getString(0)).isEqualTo("updated-display-name")
}
diff --git a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/MediaStoreEntitiesTest.kt b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/MediaStoreEntitiesTest.kt
index 6def392..d79f87f 100644
--- a/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/MediaStoreEntitiesTest.kt
+++ b/contentaccess/integration-tests/testapp/src/androidTest/java/androidx/contentaccess/integration/testapp/MediaStoreEntitiesTest.kt
@@ -39,15 +39,20 @@
@After
fun deleteAllAdded() {
- contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- MediaStore.Images.Media.MIME_TYPE + "=?", arrayOf("image/jpeg"))
+ contentResolver.delete(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ MediaStore.Images.Media.MIME_TYPE + "=?", arrayOf("image/jpeg")
+ )
}
@JvmField
@Rule
var storagePermissions =
- GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission
- .WRITE_EXTERNAL_STORAGE)!!
+ GrantPermissionRule.grant(
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission
+ .WRITE_EXTERNAL_STORAGE
+ )!!
@ContentAccessObject
@Suppress("deprecation")
diff --git a/core/core-appdigest/api/current.txt b/core/core-appdigest/api/current.txt
index 523c63b..6272e90 100644
--- a/core/core-appdigest/api/current.txt
+++ b/core/core-appdigest/api/current.txt
@@ -12,8 +12,8 @@
field @Deprecated public static final int TYPE_WHOLE_MD5 = 2; // 0x2
field public static final int TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 = 1; // 0x1
field @Deprecated public static final int TYPE_WHOLE_SHA1 = 4; // 0x4
- field public static final int TYPE_WHOLE_SHA256 = 8; // 0x8
- field public static final int TYPE_WHOLE_SHA512 = 16; // 0x10
+ field @Deprecated public static final int TYPE_WHOLE_SHA256 = 8; // 0x8
+ field @Deprecated public static final int TYPE_WHOLE_SHA512 = 16; // 0x10
}
public final class Checksums {
diff --git a/core/core-appdigest/api/public_plus_experimental_current.txt b/core/core-appdigest/api/public_plus_experimental_current.txt
index 523c63b..6272e90 100644
--- a/core/core-appdigest/api/public_plus_experimental_current.txt
+++ b/core/core-appdigest/api/public_plus_experimental_current.txt
@@ -12,8 +12,8 @@
field @Deprecated public static final int TYPE_WHOLE_MD5 = 2; // 0x2
field public static final int TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 = 1; // 0x1
field @Deprecated public static final int TYPE_WHOLE_SHA1 = 4; // 0x4
- field public static final int TYPE_WHOLE_SHA256 = 8; // 0x8
- field public static final int TYPE_WHOLE_SHA512 = 16; // 0x10
+ field @Deprecated public static final int TYPE_WHOLE_SHA256 = 8; // 0x8
+ field @Deprecated public static final int TYPE_WHOLE_SHA512 = 16; // 0x10
}
public final class Checksums {
diff --git a/core/core-appdigest/api/restricted_current.txt b/core/core-appdigest/api/restricted_current.txt
index 523c63b..6272e90 100644
--- a/core/core-appdigest/api/restricted_current.txt
+++ b/core/core-appdigest/api/restricted_current.txt
@@ -12,8 +12,8 @@
field @Deprecated public static final int TYPE_WHOLE_MD5 = 2; // 0x2
field public static final int TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 = 1; // 0x1
field @Deprecated public static final int TYPE_WHOLE_SHA1 = 4; // 0x4
- field public static final int TYPE_WHOLE_SHA256 = 8; // 0x8
- field public static final int TYPE_WHOLE_SHA512 = 16; // 0x10
+ field @Deprecated public static final int TYPE_WHOLE_SHA256 = 8; // 0x8
+ field @Deprecated public static final int TYPE_WHOLE_SHA512 = 16; // 0x10
}
public final class Checksums {
diff --git a/core/core-appdigest/src/main/java/androidx/core/appdigest/Checksum.java b/core/core-appdigest/src/main/java/androidx/core/appdigest/Checksum.java
index 10c9c91..2debfff 100644
--- a/core/core-appdigest/src/main/java/androidx/core/appdigest/Checksum.java
+++ b/core/core-appdigest/src/main/java/androidx/core/appdigest/Checksum.java
@@ -57,8 +57,8 @@
* MD5 hash computed over all file bytes.
*
* @see Checksums#getChecksums
- * @deprecated Use SHA2 family of hashes (SHA256/SHA512) instead.
- * MD5 is cryptographically broken and unsuitable for further use.
+ * @deprecated Not platform enforced. Cryptographically broken and unsuitable for further use.
+ * Use platform enforced digests e.g. {@link #TYPE_WHOLE_MERKLE_ROOT_4K_SHA256}.
* Provided for completeness' sake and to support legacy usecases.
*/
@Deprecated
@@ -68,8 +68,8 @@
* SHA1 hash computed over all file bytes.
*
* @see Checksums#getChecksums
- * @deprecated Use SHA2 family of hashes (SHA256/SHA512) instead.
- * SHA1 is broken and should not be used.
+ * @deprecated Not platform enforced. Broken and should not be used.
+ * Use platform enforced digests e.g. {@link #TYPE_WHOLE_MERKLE_ROOT_4K_SHA256}.
* Provided for completeness' sake and to support legacy usecases.
*/
@Deprecated
@@ -77,6 +77,9 @@
/**
* SHA256 hash computed over all file bytes.
+ * @deprecated Not platform enforced.
+ * Use platform enforced digests e.g. {@link #TYPE_WHOLE_MERKLE_ROOT_4K_SHA256}.
+ * Provided for completeness' sake and to support legacy usecases.
*
* @see Checksums#getChecksums
*/
@@ -84,6 +87,9 @@
/**
* SHA512 hash computed over all file bytes.
+ * @deprecated Not platform enforced.
+ * Use platform enforced digests e.g. {@link #TYPE_WHOLE_MERKLE_ROOT_4K_SHA256}.
+ * Provided for completeness' sake and to support legacy usecases.
*
* @see Checksums#getChecksums
*/
diff --git a/core/core-appdigest/src/main/java/androidx/core/appdigest/Checksums.java b/core/core-appdigest/src/main/java/androidx/core/appdigest/Checksums.java
index 5364cbe..63ea5ccc 100644
--- a/core/core-appdigest/src/main/java/androidx/core/appdigest/Checksums.java
+++ b/core/core-appdigest/src/main/java/androidx/core/appdigest/Checksums.java
@@ -96,11 +96,13 @@
* @param packageName whose checksums to return.
* @param required explicitly request the checksum types. Will incur significant
* CPU/memory/disk usage.
- * @param trustedInstallers for checksums enforced by Installer, which ones to be trusted.
- * {@link #TRUST_ALL} will return checksums from any Installer,
- * {@link #TRUST_NONE} disables optimized Installer-enforced checksums,
+ * @param trustedInstallers for checksums enforced by installer, which installers are to be
+ * trusted.
+ * {@link #TRUST_ALL} will return checksums from any installer,
+ * {@link #TRUST_NONE} disables optimized installer-enforced checksums,
* otherwise the list has to be non-empty list of certificates.
* @param executor for calculating checksums.
+ * @throws IllegalArgumentException if the list of trusted installer certificates is empty.
* @throws PackageManager.NameNotFoundException if a package with the given name cannot be
* found on the system.
*/
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index 89b508a..ddcab54 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -2331,6 +2331,7 @@
method @Deprecated public static float getTranslationX(android.view.View!);
method @Deprecated public static float getTranslationY(android.view.View!);
method public static float getTranslationZ(android.view.View);
+ method public static androidx.core.view.WindowInsetsControllerCompat? getWindowInsetsController(android.view.View);
method public static int getWindowSystemUiVisibility(android.view.View);
method @Deprecated public static float getX(android.view.View!);
method @Deprecated public static float getY(android.view.View!);
@@ -2567,6 +2568,7 @@
}
public final class WindowCompat {
+ method public static androidx.core.view.WindowInsetsControllerCompat? getInsetsController(android.view.Window, android.view.View);
method public static <T extends android.view.View> T requireViewById(android.view.Window, @IdRes int);
method public static void setDecorFitsSystemWindows(android.view.Window, boolean);
field public static final int FEATURE_ACTION_BAR = 8; // 0x8
@@ -2638,6 +2640,18 @@
method public static int tappableElement();
}
+ public final class WindowInsetsControllerCompat {
+ ctor public WindowInsetsControllerCompat(android.view.Window, android.view.View);
+ method public int getSystemBarsBehavior();
+ method public void hide(int);
+ method public void setSystemBarsBehavior(int);
+ method public void show(int);
+ method @RequiresApi(30) public static androidx.core.view.WindowInsetsControllerCompat toWindowInsetsControllerCompat(android.view.WindowInsetsController);
+ field public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1; // 0x1
+ field public static final int BEHAVIOR_SHOW_BARS_BY_TOUCH = 0; // 0x0
+ field public static final int BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 2; // 0x2
+ }
+
}
package androidx.core.view.accessibility {
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index c412aac..10d51ef 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -2329,6 +2329,7 @@
method @Deprecated public static float getTranslationX(android.view.View!);
method @Deprecated public static float getTranslationY(android.view.View!);
method public static float getTranslationZ(android.view.View);
+ method public static androidx.core.view.WindowInsetsControllerCompat? getWindowInsetsController(android.view.View);
method public static int getWindowSystemUiVisibility(android.view.View);
method @Deprecated public static float getX(android.view.View!);
method @Deprecated public static float getY(android.view.View!);
@@ -2565,6 +2566,7 @@
}
public final class WindowCompat {
+ method public static androidx.core.view.WindowInsetsControllerCompat? getInsetsController(android.view.Window, android.view.View);
method public static <T extends android.view.View> T requireViewById(android.view.Window, @IdRes int);
method public static void setDecorFitsSystemWindows(android.view.Window, boolean);
field public static final int FEATURE_ACTION_BAR = 8; // 0x8
@@ -2636,6 +2638,18 @@
method public static int tappableElement();
}
+ public final class WindowInsetsControllerCompat {
+ ctor public WindowInsetsControllerCompat(android.view.Window, android.view.View);
+ method public int getSystemBarsBehavior();
+ method public void hide(int);
+ method public void setSystemBarsBehavior(int);
+ method public void show(int);
+ method @RequiresApi(30) public static androidx.core.view.WindowInsetsControllerCompat toWindowInsetsControllerCompat(android.view.WindowInsetsController);
+ field public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1; // 0x1
+ field public static final int BEHAVIOR_SHOW_BARS_BY_TOUCH = 0; // 0x0
+ field public static final int BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 2; // 0x2
+ }
+
}
package androidx.core.view.accessibility {
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index a21ee1d..b7eedf7 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -2725,6 +2725,7 @@
method @Deprecated public static float getTranslationX(android.view.View!);
method @Deprecated public static float getTranslationY(android.view.View!);
method public static float getTranslationZ(android.view.View);
+ method public static androidx.core.view.WindowInsetsControllerCompat? getWindowInsetsController(android.view.View);
method public static int getWindowSystemUiVisibility(android.view.View);
method @Deprecated public static float getX(android.view.View!);
method @Deprecated public static float getY(android.view.View!);
@@ -2979,6 +2980,7 @@
}
public final class WindowCompat {
+ method public static androidx.core.view.WindowInsetsControllerCompat? getInsetsController(android.view.Window, android.view.View);
method public static <T extends android.view.View> T requireViewById(android.view.Window, @IdRes int);
method public static void setDecorFitsSystemWindows(android.view.Window, boolean);
field public static final int FEATURE_ACTION_BAR = 8; // 0x8
@@ -3053,6 +3055,18 @@
@IntDef(flag=true, value={androidx.core.view.WindowInsetsCompat.Type.STATUS_BARS, androidx.core.view.WindowInsetsCompat.Type.NAVIGATION_BARS, androidx.core.view.WindowInsetsCompat.Type.CAPTION_BAR, androidx.core.view.WindowInsetsCompat.Type.IME, androidx.core.view.WindowInsetsCompat.Type.WINDOW_DECOR, androidx.core.view.WindowInsetsCompat.Type.SYSTEM_GESTURES, androidx.core.view.WindowInsetsCompat.Type.MANDATORY_SYSTEM_GESTURES, androidx.core.view.WindowInsetsCompat.Type.TAPPABLE_ELEMENT, androidx.core.view.WindowInsetsCompat.Type.DISPLAY_CUTOUT}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface WindowInsetsCompat.Type.InsetsType {
}
+ public final class WindowInsetsControllerCompat {
+ ctor public WindowInsetsControllerCompat(android.view.Window, android.view.View);
+ method public int getSystemBarsBehavior();
+ method public void hide(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int);
+ method public void setSystemBarsBehavior(int);
+ method public void show(@androidx.core.view.WindowInsetsCompat.Type.InsetsType int);
+ method @RequiresApi(30) public static androidx.core.view.WindowInsetsControllerCompat toWindowInsetsControllerCompat(android.view.WindowInsetsController);
+ field public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1; // 0x1
+ field public static final int BEHAVIOR_SHOW_BARS_BY_TOUCH = 0; // 0x0
+ field public static final int BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 2; // 0x2
+ }
+
}
package androidx.core.view.accessibility {
diff --git a/core/core/src/androidTest/AndroidManifest.xml b/core/core/src/androidTest/AndroidManifest.xml
index 1a7d967..d8170ee 100644
--- a/core/core/src/androidTest/AndroidManifest.xml
+++ b/core/core/src/androidTest/AndroidManifest.xml
@@ -86,7 +86,7 @@
<provider
android:name="androidx.core.content.FileProvider"
- android:authorities="moocow"
+ android:authorities="moocow;additional.authority"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
diff --git a/core/core/src/androidTest/java/androidx/core/content/FileProviderTest.java b/core/core/src/androidTest/java/androidx/core/content/FileProviderTest.java
index 5877c84..3160a43 100644
--- a/core/core/src/androidTest/java/androidx/core/content/FileProviderTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/FileProviderTest.java
@@ -54,6 +54,7 @@
@RunWith(AndroidJUnit4.class)
public class FileProviderTest {
private static final String TEST_AUTHORITY = "moocow";
+ private static final String ADDITIONAL_AUTHORITY = "additional.authority";
private static final String TEST_FILE = "file.test";
private static final byte[] TEST_DATA = new byte[] { (byte) 0xf0, 0x00, 0x0d };
@@ -365,6 +366,14 @@
}
@Test
+ public void testAdditionalAuthority() throws Exception {
+ final File file = new File(mContext.getFilesDir(), TEST_FILE);
+ final Uri uri = stageFileAndGetUri(file, TEST_DATA, ADDITIONAL_AUTHORITY);
+ assertEquals("content://additional.authority/test_files/file.test", uri.toString());
+ assertContentsEquals(TEST_DATA, uri);
+ }
+
+ @Test
public void testNonExistentAuthority() {
File file = buildPath(mContext.getFilesDir(), "file.test");
try {
@@ -386,6 +395,10 @@
}
private Uri stageFileAndGetUri(File file, byte[] data) throws Exception {
+ return stageFileAndGetUri(file, data, TEST_AUTHORITY);
+ }
+
+ private Uri stageFileAndGetUri(File file, byte[] data, String authority) throws Exception {
if (data != null) {
final FileOutputStream out = new FileOutputStream(file);
try {
@@ -396,7 +409,7 @@
} else {
file.delete();
}
- return FileProvider.getUriForFile(mContext, TEST_AUTHORITY, file);
+ return FileProvider.getUriForFile(mContext, authority, file);
}
private static File buildPath(File base, String... segments) {
diff --git a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
new file mode 100644
index 0000000..576b9e9
--- /dev/null
+++ b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 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.core.view
+
+import android.os.Build
+import android.view.View
+import android.view.WindowInsetsController
+import android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+import android.widget.EditText
+import androidx.annotation.RequiresApi
+import androidx.core.graphics.Insets
+import androidx.core.test.R
+import androidx.test.core.app.ActivityScenario
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.action.ViewActions.click
+import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
+import androidx.test.espresso.matcher.ViewMatchers.assertThat
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.testutils.withActivity
+import org.hamcrest.Matchers.`is`
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.fail
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicReference
+import kotlin.concurrent.thread
+
+@Suppress("DEPRECATION")
+@SdkSuppress(minSdkVersion = 23)
+@RequiresApi(23) // ViewCompat.getRootWindowInsets()
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class WindowInsetsControllerCompatActivityTest {
+
+ private lateinit var container: View
+ private lateinit var windowInsetsController: WindowInsetsControllerCompat
+ private lateinit var scenario: ActivityScenario<WindowInsetsCompatActivity>
+
+ @Before
+ fun setup() {
+ scenario = ActivityScenario.launch(WindowInsetsCompatActivity::class.java)
+
+ container = scenario.withActivity { findViewById(R.id.container) }
+ windowInsetsController = ViewCompat.getWindowInsetsController(container)!!
+ scenario.withActivity {
+ WindowCompat.setDecorFitsSystemWindows(window, true)
+ }
+ // Close the IME if it's open, so we start from a known scenario
+ onView(withId(R.id.edittext)).perform(closeSoftKeyboard())
+ ViewCompat.getWindowInsetsController(container)!!.systemBarsBehavior =
+ WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+
+ // Needed on API 23 to report the nav bar insets
+ scenario.withActivity { this.window.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) }
+ }
+
+ /**
+ * IME visibility is only reliable on API 23+, where we have access to the root WindowInsets
+ */
+ @SdkSuppress(minSdkVersion = 23)
+ @Test
+ fun toggleIME() {
+ // Test do not currently work on Cuttlefish
+ assumeNotCuttlefish()
+ val container: View = scenario.withActivity { findViewById(R.id.container) }
+ scenario.withActivity { findViewById<View>(R.id.edittext).requestFocus() }
+
+ val windowInsetsController = ViewCompat.getWindowInsetsController(container)!!
+ scenario.onActivity { windowInsetsController.hide(WindowInsetsCompat.Type.ime()) }
+ container.assertInsetsVisibility(WindowInsetsCompat.Type.ime(), false)
+ testShow(WindowInsetsCompat.Type.ime())
+ testHide(WindowInsetsCompat.Type.ime())
+ }
+
+ /**
+ * IME visibility is only reliable on API 23+, where we have access to the root WindowInsets
+ */
+ @SdkSuppress(minSdkVersion = 23)
+ @Test
+ fun do_not_show_IME_if_TextView_not_focused() {
+ val editText = scenario.withActivity {
+ findViewById<EditText>(R.id.edittext)
+ }
+
+ // We hide the edit text to ensure it won't be automatically focused
+ scenario.onActivity {
+ editText.visibility = View.GONE
+ assertThat(editText.isFocused, `is`(false))
+ }
+
+ val type = WindowInsetsCompat.Type.ime()
+ scenario.onActivity { windowInsetsController.show(type) }
+ container.assertInsetsVisibility(type, false)
+ }
+
+ /**
+ * IME visibility is only reliable on API 23+, where we have access to the root WindowInsets
+ */
+ @SdkSuppress(minSdkVersion = 23)
+ @Test
+ fun show_IME_fromEditText() {
+ // Test do not currently work on Cuttlefish
+ assumeNotCuttlefish()
+ val type = WindowInsetsCompat.Type.ime()
+ val editText = scenario.withActivity { findViewById(R.id.edittext) }
+ val controller = scenario.withActivity { ViewCompat.getWindowInsetsController(editText)!! }
+
+ scenario.onActivity {
+ editText.requestFocus()
+ }
+ assertThat(editText.isFocused, `is`(true))
+ if (Build.VERSION.SDK_INT == 30) {
+ // Dirty hack until we figure out why the IME is not showing if we don't wait before
+ Thread.sleep(100)
+ }
+ controller.show(type)
+ container.assertInsetsVisibility(type, true)
+ }
+
+ /**
+ * IME visibility is only reliable on API 23+, where we have access to the root WindowInsets
+ */
+ @SdkSuppress(minSdkVersion = 23)
+ @Test
+ fun hide_IME() {
+ // Test do not currently work on Cuttlefish
+ assumeNotCuttlefish()
+ onView(withId(R.id.edittext)).perform(click())
+ container.assertInsetsVisibility(WindowInsetsCompat.Type.ime(), true)
+ testHide(WindowInsetsCompat.Type.ime())
+ }
+
+ @Test
+ fun toggle_StatusBar() {
+ container.assertInsetsVisibility(WindowInsetsCompat.Type.statusBars(), true)
+ testHide(WindowInsetsCompat.Type.statusBars())
+ testShow(WindowInsetsCompat.Type.statusBars())
+ }
+
+ @Test
+ fun toggle_NavBar() {
+ testHide(WindowInsetsCompat.Type.navigationBars())
+ testShow(WindowInsetsCompat.Type.navigationBars())
+ }
+
+ private fun testHide(type: Int) {
+ scenario.onActivity { windowInsetsController.hide(type) }
+ container.assertInsetsVisibility(type, false)
+ }
+
+ private fun testShow(type: Int) {
+ // Now open the IME using the InsetsController The IME should
+ // now be open
+ scenario.onActivity { windowInsetsController.show(type) }
+ container.assertInsetsVisibility(type, true)
+ }
+
+ /**
+ * IME visibility is only reliable on API 23+, where we have access to the root WindowInsets
+ */
+ @SdkSuppress(minSdkVersion = 23)
+ @Ignore("The listener isn't called when changing the visibility")
+ @Test
+ fun ime_toggle_check_with_listener() {
+ // Test do not currently work on Cuttlefish
+ assumeNotCuttlefish()
+ val type = WindowInsetsCompat.Type.ime()
+
+ val container: View = scenario.withActivity { findViewById(R.id.container) }
+
+ // Tell the window that our view will fit system windows
+ container.doAndAwaitNextInsets {
+ scenario.onActivity { activity ->
+ WindowCompat.setDecorFitsSystemWindows(activity.window, false)
+ }
+ }.let { insets ->
+ // Assert that the IME visibility is false and the insets are empty
+ assertThat(insets.isVisible(type), `is`(false))
+ assertEquals(Insets.NONE, insets.getInsets(type))
+ }
+
+ val windowInsetsController = ViewCompat.getWindowInsetsController(container)!!
+
+ // Now open the IME using the InsetsController The IME should
+ // now be open
+ // container.doAndAwaitNextInsets {
+ scenario.onActivity {
+ windowInsetsController.show(type)
+ }
+
+ // Finally dismiss the IME
+ container.doAndAwaitNextInsets {
+ scenario.onActivity {
+ windowInsetsController.hide(type)
+ }
+ }.let { insets ->
+ // Assert that the IME visibility is false and the insets are empty
+ assertThat(insets.isVisible(type), `is`(false))
+ assertEquals(Insets.NONE, insets.getInsets(type))
+ }
+ }
+
+ private fun assumeNotCuttlefish() {
+ // TODO: remove this if b/159103848 is resolved
+ assumeFalse(
+ "Unable to test: Cuttlefish devices default to the virtual keyboard being disabled.",
+ Build.MODEL.contains("Cuttlefish", ignoreCase = true)
+ )
+ }
+
+ @After
+ fun cleanup() {
+ scenario.close()
+ }
+
+ @RequiresApi(23) // ViewCompat.getRootWindowInsets()
+ private fun View.assertInsetsVisibility(
+ type: Int,
+ expectedVisibility: Boolean
+ ) {
+ val latch = CountDownLatch(1)
+ var loop = true
+ var lastVisibility: Boolean? = null
+ try {
+ thread {
+ while (loop) {
+ val rootWindowInsets = scenario.withActivity {
+ ViewCompat
+ .getRootWindowInsets(this@assertInsetsVisibility)!!
+ }
+ lastVisibility = rootWindowInsets.isVisible(type)
+ if (lastVisibility == expectedVisibility) {
+ latch.countDown()
+ }
+ Thread.sleep(300)
+ }
+ }
+
+ latch.await(5, TimeUnit.SECONDS)
+ } finally {
+ loop = false
+ assertThat(
+ "isVisible() should be <$expectedVisibility> but is <$lastVisibility>",
+ lastVisibility, `is`(expectedVisibility)
+ )
+ }
+ }
+}
+
+private fun View.doAndAwaitNextInsets(action: (View) -> Unit): WindowInsetsCompat {
+ val latch = CountDownLatch(1)
+ val received = AtomicReference<WindowInsetsCompat>()
+
+ // Set a listener to catch WindowInsets
+ ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets: WindowInsetsCompat ->
+ received.set(insets)
+ latch.countDown()
+
+ WindowInsetsCompat.CONSUMED
+ }
+
+ try {
+ // Perform the action
+ action(this)
+ // Await an inset pass
+ if (!latch.await(5, TimeUnit.SECONDS)) {
+ fail("OnApplyWindowInsetsListener was not called")
+ }
+ } finally {
+ this.post {
+ ViewCompat.setOnApplyWindowInsetsListener(this, null)
+ }
+ }
+ return received.get()
+}
\ No newline at end of file
diff --git a/core/core/src/main/java/androidx/core/content/FileProvider.java b/core/core/src/main/java/androidx/core/content/FileProvider.java
index b138130..753258c 100644
--- a/core/core/src/main/java/androidx/core/content/FileProvider.java
+++ b/core/core/src/main/java/androidx/core/content/FileProvider.java
@@ -397,6 +397,7 @@
* @param context A {@link Context} for the current component.
* @param info A {@link ProviderInfo} for the new provider.
*/
+ @SuppressWarnings("StringSplitter")
@Override
public void attachInfo(@NonNull Context context, @NonNull ProviderInfo info) {
super.attachInfo(context, info);
@@ -409,7 +410,7 @@
throw new SecurityException("Provider must grant uri permissions");
}
- mStrategy = getPathStrategy(context, info.authority);
+ mStrategy = getPathStrategy(context, info.authority.split(";")[0]);
}
/**
diff --git a/core/core/src/main/java/androidx/core/view/ViewCompat.java b/core/core/src/main/java/androidx/core/view/ViewCompat.java
index cc2ace9..c5c8c38 100644
--- a/core/core/src/main/java/androidx/core/view/ViewCompat.java
+++ b/core/core/src/main/java/androidx/core/view/ViewCompat.java
@@ -20,6 +20,7 @@
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
+import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -45,7 +46,9 @@
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
+import android.view.Window;
import android.view.WindowInsets;
+import android.view.WindowInsetsController;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -2644,6 +2647,27 @@
}
/**
+ * Retrieves a {@link WindowInsetsControllerCompat} of the window this view is attached to.
+ *
+ * @return A {@link WindowInsetsControllerCompat} or {@code null} if the view is neither
+ * attached to a window nor a view tree with a decor.
+ * @see WindowCompat#getInsetsController(Window, View)
+ */
+ @Nullable
+ public static WindowInsetsControllerCompat getWindowInsetsController(@NonNull View view) {
+ if (Build.VERSION.SDK_INT >= 30) {
+ return Api30Impl.getWindowInsetsController(view);
+ } else {
+ Context context = view.getContext();
+ if (context instanceof Activity) {
+ Window window = ((Activity) context).getWindow();
+ return window != null ? WindowCompat.getInsetsController(window, view) : null;
+ }
+ return null;
+ }
+ }
+
+ /**
* Controls whether the entire hierarchy under this view will save its
* state when a state saving traversal occurs from its parent.
*
@@ -4595,4 +4619,19 @@
context, styleable, attrs, t, defStyleAttr, defStyleRes);
}
}
+
+ @RequiresApi(30)
+ private static class Api30Impl {
+ private Api30Impl() {
+ // privatex
+ }
+
+ @Nullable
+ public static WindowInsetsControllerCompat getWindowInsetsController(@NonNull View view) {
+ WindowInsetsController windowInsetsController = view.getWindowInsetsController();
+ return windowInsetsController != null
+ ? WindowInsetsControllerCompat.toWindowInsetsControllerCompat(
+ windowInsetsController) : null;
+ }
+ }
}
diff --git a/core/core/src/main/java/androidx/core/view/WindowCompat.java b/core/core/src/main/java/androidx/core/view/WindowCompat.java
index 323f84d..48b45a9 100644
--- a/core/core/src/main/java/androidx/core/view/WindowCompat.java
+++ b/core/core/src/main/java/androidx/core/view/WindowCompat.java
@@ -19,9 +19,11 @@
import android.os.Build;
import android.view.View;
import android.view.Window;
+import android.view.WindowInsetsController;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
/**
@@ -119,6 +121,24 @@
}
}
+
+ /**
+ * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
+ *
+ * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to
+ * a window nor a view tree with a decor.
+ * @see Window#getInsetsController()
+ */
+ @Nullable
+ public static WindowInsetsControllerCompat getInsetsController(@NonNull Window window,
+ @NonNull View view) {
+ if (Build.VERSION.SDK_INT >= 30) {
+ return Impl30.getInsetsController(window);
+ } else {
+ return new WindowInsetsControllerCompat(window, view);
+ }
+ }
+
@RequiresApi(16)
private static class Impl16 {
static void setDecorFitsSystemWindows(@NonNull Window window,
@@ -141,5 +161,14 @@
final boolean decorFitsSystemWindows) {
window.setDecorFitsSystemWindows(decorFitsSystemWindows);
}
+
+ static WindowInsetsControllerCompat getInsetsController(@NonNull Window window) {
+ WindowInsetsController insetsController = window.getInsetsController();
+ if (insetsController != null) {
+ return WindowInsetsControllerCompat.toWindowInsetsControllerCompat(
+ insetsController);
+ }
+ return null;
+ }
}
}
diff --git a/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java b/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java
new file mode 100644
index 0000000..519abb7
--- /dev/null
+++ b/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java
@@ -0,0 +1,373 @@
+/*
+ * 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.core.view;
+
+import static android.os.Build.VERSION.SDK_INT;
+
+import android.content.Context;
+import android.graphics.Insets;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowInsetsAnimationController;
+import android.view.WindowInsetsController;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+import androidx.core.view.WindowInsetsCompat.Type;
+import androidx.core.view.WindowInsetsCompat.Type.InsetsType;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Provide simple controls of windows that generate insets.
+ *
+ * For SDKs >= 30, this class is a simple wrapper around {@link WindowInsetsController}. For
+ * lower SDKs, this class aims to behave as close as possible to the original implementation.
+ */
+public final class WindowInsetsControllerCompat {
+
+ /**
+ * The default option for {@link #setSystemBarsBehavior(int)}. System bars will be forcibly
+ * shown on any user interaction on the corresponding display if navigation bars are
+ * hidden by
+ * {@link #hide(int)} or
+ * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)}.
+ */
+ public static final int BEHAVIOR_SHOW_BARS_BY_TOUCH = 0;
+
+ /**
+ * Option for {@link #setSystemBarsBehavior(int)}: Window would like to remain
+ * interactive when
+ * hiding navigation bars by calling {@link #hide(int)} or
+ * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)}.
+ *
+ * <p>When system bars are hidden in this mode, they can be revealed with system
+ * gestures, such
+ * as swiping from the edge of the screen where the bar is hidden from.</p>
+ */
+ public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1;
+
+ /**
+ * Option for {@link #setSystemBarsBehavior(int)}: Window would like to remain
+ * interactive when
+ * hiding navigation bars by calling {@link #hide(int)} or
+ * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)}.
+ *
+ * <p>When system bars are hidden in this mode, they can be revealed temporarily with system
+ * gestures, such as swiping from the edge of the screen where the bar is hidden from. These
+ * transient system bars will overlay app’s content, may have some degree of
+ * transparency, and
+ * will automatically hide after a short timeout.</p>
+ */
+ public static final int BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 2;
+
+ private final Impl mImpl;
+
+ @RequiresApi(30)
+ private WindowInsetsControllerCompat(@NonNull WindowInsetsController insetsController) {
+ if (SDK_INT >= 30) {
+ mImpl = new Impl30(insetsController);
+ } else {
+ mImpl = new Impl();
+ }
+ }
+
+ public WindowInsetsControllerCompat(@NonNull Window window, @NonNull View view) {
+ if (SDK_INT >= 30) {
+ mImpl = new Impl30(window);
+ } else if (SDK_INT >= 20) {
+ mImpl = new Impl20(window, view);
+ } else {
+ mImpl = new Impl();
+ }
+ }
+
+ /**
+ * Wrap a {@link WindowInsetsController} into a {@link WindowInsetsControllerCompat} for
+ * compatibility purpose.
+ *
+ * @param insetsController The {@link WindowInsetsController} to wrap.
+ * @return The provided {@link WindowInsetsControllerCompat} wrapped into a
+ * {@link WindowInsetsControllerCompat}
+ */
+ @NonNull
+ @RequiresApi(30)
+ public static WindowInsetsControllerCompat toWindowInsetsControllerCompat(
+ @NonNull WindowInsetsController insetsController) {
+ return new WindowInsetsControllerCompat(insetsController);
+ }
+
+ /**
+ * Determines the behavior of system bars when hiding them by calling {@link #hide}.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {BEHAVIOR_SHOW_BARS_BY_TOUCH, BEHAVIOR_SHOW_BARS_BY_SWIPE,
+ BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE})
+ @interface Behavior {
+ }
+
+ /**
+ * Makes a set of windows that cause insets appear on screen.
+ * <p>
+ * Note that if the window currently doesn't have control over a certain type, it will apply the
+ * change as soon as the window gains control. The app can listen to the event by observing
+ * {@link View#onApplyWindowInsets} and checking visibility with {@link WindowInsets#isVisible}.
+ *
+ * @param types A bitmask of {@link WindowInsetsCompat.Type} specifying what windows the app
+ * would like to make appear on screen.
+ */
+ public void show(@InsetsType int types) {
+ mImpl.show(types);
+ }
+
+ /**
+ * Makes a set of windows causing insets disappear.
+ * <p>
+ * Note that if the window currently doesn't have control over a certain type, it will apply the
+ * change as soon as the window gains control. The app can listen to the event by observing
+ * {@link View#onApplyWindowInsets} and checking visibility with {@link WindowInsets#isVisible}.
+ *
+ * @param types A bitmask of {@link WindowInsetsCompat.Type} specifying what windows the app
+ * would like to make disappear.
+ */
+ public void hide(@InsetsType int types) {
+ mImpl.hide(types);
+ }
+
+ /**
+ * Controls the behavior of system bars.
+ *
+ * @param behavior Determines how the bars behave when being hidden by the application.
+ * @see #getSystemBarsBehavior
+ */
+ public void setSystemBarsBehavior(@Behavior int behavior) {
+ mImpl.setSystemBarsBehavior(behavior);
+ }
+
+ /**
+ * Retrieves the requested behavior of system bars.
+ *
+ * @return the system bar behavior controlled by this window.
+ * @see #setSystemBarsBehavior(int)
+ */
+ @Behavior
+ public int getSystemBarsBehavior() {
+ return mImpl.getSystemBarsBehavior();
+ }
+
+ private static class Impl {
+ Impl() {
+ }
+
+ void show(int types) {
+ }
+
+ void hide(int types) {
+ }
+
+ void setSystemBarsBehavior(int behavior) {
+ }
+
+ int getSystemBarsBehavior() {
+ return 0;
+ }
+ }
+
+ @RequiresApi(20)
+ private static class Impl20 extends Impl {
+
+ @NonNull
+ private final Window mWindow;
+
+ @Nullable
+ private final View mView;
+
+ Impl20(@NonNull Window window, @Nullable View view) {
+ mWindow = window;
+ mView = view;
+ }
+
+ @Override
+ void show(int typeMask) {
+ for (int i = Type.FIRST; i <= Type.LAST; i = i << 1) {
+ if ((typeMask & i) == 0) {
+ continue;
+ }
+ showForType(i);
+ }
+ }
+
+ private void showForType(int type) {
+ switch (type) {
+ case Type.STATUS_BARS:
+ unsetSystemUiFlag(View.SYSTEM_UI_FLAG_FULLSCREEN);
+ unsetWindowFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ return;
+ case Type.NAVIGATION_BARS:
+ unsetSystemUiFlag(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
+ return;
+ case Type.IME:
+ // We'll try to find an available textView to focus to show the IME
+ View view = mView;
+
+
+ if (view != null && (view.isInEditMode() || view.onCheckIsTextEditor())) {
+ // The IME needs a text view to be focused to be shown
+ // The view given to retrieve this controller is a textView so we can assume
+ // that we can focus it in order to show the IME
+ view.requestFocus();
+ } else {
+ view = mWindow.getCurrentFocus();
+ }
+
+ // Fallback on the container view
+ if (view == null) {
+ view = mWindow.findViewById(android.R.id.content);
+ }
+
+ if (view != null && view.hasWindowFocus()) {
+ final View finalView = view;
+ finalView.post(new Runnable() {
+ @Override
+ public void run() {
+ InputMethodManager imm =
+ (InputMethodManager) finalView.getContext()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(finalView, 0);
+
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ void hide(int typeMask) {
+ for (int i = Type.FIRST; i <= Type.LAST; i = i << 1) {
+ if ((typeMask & i) == 0) {
+ continue;
+ }
+ hideForType(i);
+ }
+ }
+
+ private void hideForType(int type) {
+ switch (type) {
+ case Type.STATUS_BARS:
+ setSystemUiFlag(View.SYSTEM_UI_FLAG_FULLSCREEN);
+ setWindowFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ return;
+ case Type.NAVIGATION_BARS:
+ setSystemUiFlag(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
+ return;
+ case Type.IME:
+ ((InputMethodManager) mWindow.getContext()
+ .getSystemService(Context.INPUT_METHOD_SERVICE))
+ .hideSoftInputFromWindow(mWindow.getDecorView().getWindowToken(),
+ 0);
+ }
+ }
+
+ protected void setSystemUiFlag(int systemUiFlag) {
+ View decorView = mWindow.getDecorView();
+ decorView.setSystemUiVisibility(
+ decorView.getSystemUiVisibility()
+ | systemUiFlag);
+ }
+
+ protected void unsetSystemUiFlag(int systemUiFlag) {
+ View decorView = mWindow.getDecorView();
+ decorView.setSystemUiVisibility(
+ decorView.getSystemUiVisibility()
+ & ~systemUiFlag);
+ }
+
+ private void setWindowFlag(int windowFlag) {
+ mWindow.addFlags(windowFlag);
+ }
+
+ private void unsetWindowFlag(int windowFlag) {
+ mWindow.clearFlags(windowFlag);
+ }
+
+ @Override
+ void setSystemBarsBehavior(int behavior) {
+ }
+
+ @Override
+ int getSystemBarsBehavior() {
+ return 0;
+ }
+ }
+
+ @RequiresApi(30)
+ private static class Impl30 extends Impl {
+
+ private final WindowInsetsController mInsetsController;
+
+ Impl30(Window window) {
+ mInsetsController = window.getInsetsController();
+ }
+
+ Impl30(WindowInsetsController insetsController) {
+ mInsetsController = insetsController;
+ }
+
+ @Override
+ void show(@InsetsType int types) {
+ mInsetsController.show(types);
+ }
+
+ @Override
+ void hide(@InsetsType int types) {
+ mInsetsController.hide(types);
+ }
+
+ /**
+ * Controls the behavior of system bars.
+ *
+ * @param behavior Determines how the bars behave when being hidden by the application.
+ * @see #getSystemBarsBehavior
+ */
+ @Override
+ void setSystemBarsBehavior(@Behavior int behavior) {
+ mInsetsController.setSystemBarsBehavior(behavior);
+ }
+
+ /**
+ * Retrieves the requested behavior of system bars.
+ *
+ * @return the system bar behavior controlled by this window.
+ * @see #setSystemBarsBehavior(int)
+ */
+ @Override
+ @Behavior
+ int getSystemBarsBehavior() {
+ return mInsetsController.getSystemBarsBehavior();
+ }
+ }
+}
diff --git a/datastore/datastore-core/src/main/java/androidx/datastore/SingleProcessDataStore.kt b/datastore/datastore-core/src/main/java/androidx/datastore/SingleProcessDataStore.kt
index 38672c4..f560b86 100644
--- a/datastore/datastore-core/src/main/java/androidx/datastore/SingleProcessDataStore.kt
+++ b/datastore/datastore-core/src/main/java/androidx/datastore/SingleProcessDataStore.kt
@@ -198,7 +198,7 @@
if (initializationComplete) {
throw IllegalStateException(
"InitializerApi.updateData should not be " +
- "called after initialization is complete."
+ "called after initialization is complete."
)
}
diff --git a/datastore/datastore-preferences/src/main/java/androidx/datastore/preferences/PreferenceDataStoreFactory.kt b/datastore/datastore-preferences/src/main/java/androidx/datastore/preferences/PreferenceDataStoreFactory.kt
index 7718ef1..2f17b79 100644
--- a/datastore/datastore-preferences/src/main/java/androidx/datastore/preferences/PreferenceDataStoreFactory.kt
+++ b/datastore/datastore-preferences/src/main/java/androidx/datastore/preferences/PreferenceDataStoreFactory.kt
@@ -58,7 +58,7 @@
val file = produceFile()
check(file.extension == PreferencesSerializer.fileExtension) {
"File extension for file: $file does not match required extension for" +
- " Preferences file: ${PreferencesSerializer.fileExtension}"
+ " Preferences file: ${PreferencesSerializer.fileExtension}"
}
file
},
@@ -103,15 +103,15 @@
internal class PreferenceDataStore(private val delegate: DataStore<Preferences>) :
DataStore<Preferences> by delegate {
override suspend fun updateData(transform: suspend (t: Preferences) -> Preferences):
- Preferences {
- return delegate.updateData {
- val transformed = transform(it)
- // Freeze the preferences since any future mutations will break DataStore. If a user
- // tunnels the value out of DataStore and mutates it, this could be problematic.
- // This is a safe cast, since MutablePreferences is the only implementation of
- // Preferences.
- (transformed as MutablePreferences).freeze()
- transformed
+ Preferences {
+ return delegate.updateData {
+ val transformed = transform(it)
+ // Freeze the preferences since any future mutations will break DataStore. If a user
+ // tunnels the value out of DataStore and mutates it, this could be problematic.
+ // This is a safe cast, since MutablePreferences is the only implementation of
+ // Preferences.
+ (transformed as MutablePreferences).freeze()
+ transformed
+ }
}
- }
}
diff --git a/datastore/datastore-sampleapp/build.gradle b/datastore/datastore-sampleapp/build.gradle
index cd88f49..8d60d35 100644
--- a/datastore/datastore-sampleapp/build.gradle
+++ b/datastore/datastore-sampleapp/build.gradle
@@ -33,13 +33,16 @@
// For DataStore with protos
implementation(project(":datastore:datastore-core"))
- api("androidx.preference:preference:1.1.0")
+
+ // For settings fragment
+ api("androidx.preference:preference:1.1.1")
implementation(PROTOBUF_LITE)
implementation(KOTLIN_STDLIB)
+ implementation("androidx.appcompat:appcompat:1.2.0")
implementation(CONSTRAINT_LAYOUT, { transitive = true })
- implementation(project(":fragment:fragment-ktx"))
+ implementation('androidx.navigation:navigation-fragment-ktx:2.3.0')
implementation project(":annotation:annotation-sampled")
}
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index eb5d47f..8fff328a 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -496,6 +496,7 @@
\[[0-9]+/[0-9]+\] Generating icing\-protobuf\-gen/icing/proto/document\.pb\.cc, icing\-protobuf\-gen/icing/proto/document\.pb\.h
\[[0-9]+/[0-9]+\] Generating icing\-protobuf\-gen/icing/proto/search\.pb\.cc, icing\-protobuf\-gen/icing/proto/search\.pb\.h
\[[0-9]+/[0-9]+\] Generating icing\-protobuf\-gen/icing/proto/schema\.pb\.cc, icing\-protobuf\-gen/icing/proto/schema\.pb\.h
+\[[0-9]+/[0-9]+\] Generating icing\-protobuf\-gen/icing/proto/usage\.pb\.cc, icing\-protobuf\-gen/icing/proto/usage\.pb\.h
\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/absl_ports/canonical_errors\.cc\.o
\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/legacy/core/icing\-timer\.cc\.o
\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/absl_ports/str_cat\.cc\.o
@@ -576,6 +577,16 @@
\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing\-protobuf\-gen/icing/proto/search\.pb\.cc\.o
\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/icing\-search\-engine\.cc\.o
\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/store/document\-store\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/util/character\-iterator\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/index/main/posting\-list\-identifier\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/index/main/posting\-list\-accessor\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/index/main/doc\-hit\-info\-iterator\-term\-main\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/index/lite/doc\-hit\-info\-iterator\-term\-lite\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/store/usage\-store\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/index/main/flash\-index\-storage\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/index/main/main\-index\-merger\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing\-protobuf\-gen/icing/proto/usage\.pb\.cc\.o
+\[[0-9]+/[0-9]+\] Building CXX object CMakeFiles/icing\.dir/icing/index/main/main\-index\.cc\.o
\[[0-9]+/[0-9]+\] Linking CXX shared library \$OUT_DIR/androidx/appsearch/appsearch\-local\-backend/build/intermediates/cmake/release/obj/armeabi\-v[0-9]+a/libicing\.so
Build icing_arm[0-9]+\-v[0-9]+a
ninja: Entering directory `\$SUPPORT/appsearch/local\-backend/\.cxx/cmake/release/arm[0-9]+\-v[0-9]+a'
diff --git a/dynamic-animation/dynamic-animation/src/main/java/androidx/dynamicanimation/animation/FlingAnimation.java b/dynamic-animation/dynamic-animation/src/main/java/androidx/dynamicanimation/animation/FlingAnimation.java
index 5be3b9b..e42d06a 100644
--- a/dynamic-animation/dynamic-animation/src/main/java/androidx/dynamicanimation/animation/FlingAnimation.java
+++ b/dynamic-animation/dynamic-animation/src/main/java/androidx/dynamicanimation/animation/FlingAnimation.java
@@ -215,8 +215,7 @@
MassState updateValueAndVelocity(float value, float velocity, long deltaT) {
mMassState.mVelocity = (float) (velocity * Math.exp((deltaT / 1000f) * mFriction));
- mMassState.mValue = (float) (value - velocity / mFriction
- + velocity / mFriction * Math.exp(mFriction * deltaT / 1000f));
+ mMassState.mValue = (float) (value + (mMassState.mVelocity - velocity) / mFriction);
if (isAtEquilibrium(mMassState.mValue, mMassState.mVelocity)) {
mMassState.mVelocity = 0f;
}
diff --git a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt
index 9dc4144..644f3d4 100644
--- a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt
+++ b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt
@@ -212,7 +212,7 @@
if (event == Lifecycle.Event.ON_START) {
tagSetBeforeOnStart =
fragment.requireView().getTag(view_tag_id) ==
- "fakeNavController"
+ "fakeNavController"
}
}
)
diff --git a/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/TestTypeSelectFragment.kt b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/TestTypeSelectFragment.kt
index 789291d..e7a7a5b 100644
--- a/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/TestTypeSelectFragment.kt
+++ b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/TestTypeSelectFragment.kt
@@ -33,18 +33,20 @@
}
private fun Fragment.addButton(text: String, fragment: Fragment) {
- (requireView() as LinearLayout).addView(Button(context).apply {
- this.text = text
+ (requireView() as LinearLayout).addView(
+ Button(context).apply {
+ this.text = text
- setOnClickListener {
- parentFragmentManager.commit {
- replace(R.id.fragment_container, fragment)
- addToBackStack(null)
+ setOnClickListener {
+ parentFragmentManager.commit {
+ replace(R.id.fragment_container, fragment)
+ addToBackStack(null)
+ }
+ }
+ layoutParams = LinearLayout.LayoutParams(-1, 0).apply {
+ weight = 1f
}
}
- layoutParams = LinearLayout.LayoutParams(-1, 0).apply {
- weight = 1f
- }
- })
+ )
}
}
diff --git a/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/TransitionTestsFragment.kt b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/TransitionTestsFragment.kt
index e2c8cbe..5c898b3 100644
--- a/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/TransitionTestsFragment.kt
+++ b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/TransitionTestsFragment.kt
@@ -35,14 +35,16 @@
}
fun <T : FragmentActivity> Fragment.addButton(text: String, clazz: Class<T>) {
- (requireView() as LinearLayout).addView(Button(context).apply {
- this.text = text
+ (requireView() as LinearLayout).addView(
+ Button(context).apply {
+ this.text = text
- setOnClickListener {
- startActivity(Intent(activity, clazz))
+ setOnClickListener {
+ startActivity(Intent(activity, clazz))
+ }
+ layoutParams = LinearLayout.LayoutParams(-1, 0).apply {
+ weight = 1f
+ }
}
- layoutParams = LinearLayout.LayoutParams(-1, 0).apply {
- weight = 1f
- }
- })
+ )
}
diff --git a/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/doubleTransitionBug/DoubleTransitionBugActivity.kt b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/doubleTransitionBug/DoubleTransitionBugActivity.kt
index ed841d1..969f8e7 100644
--- a/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/doubleTransitionBug/DoubleTransitionBugActivity.kt
+++ b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/doubleTransitionBug/DoubleTransitionBugActivity.kt
@@ -52,11 +52,11 @@
first.enterTransition = Fade().setDuration(5000)
supportFragmentManager.beginTransaction()
- .setReorderingAllowed(true)
- .add(R.id.content, first)
- .add(R.id.content, second)
- .hide(currentFragment)
- .addToBackStack(null)
- .commit()
+ .setReorderingAllowed(true)
+ .add(R.id.content, first)
+ .add(R.id.content, second)
+ .hide(currentFragment)
+ .addToBackStack(null)
+ .commit()
}
}
diff --git a/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/FragmentInjectionTest.kt b/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/FragmentInjectionTest.kt
index c15d78a..647f22c 100644
--- a/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/FragmentInjectionTest.kt
+++ b/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/FragmentInjectionTest.kt
@@ -100,7 +100,8 @@
fun addTestFragment() {
val fragment = supportFragmentManager.fragmentFactory.instantiate(
TestFragment::class.java.classLoader!!,
- TestFragment::class.java.name)
+ TestFragment::class.java.name
+ )
supportFragmentManager.beginTransaction()
.add(0, fragment, FRAGMENT_TAG)
.commitNow()
diff --git a/leanback/leanback/api/restricted_current.txt b/leanback/leanback/api/restricted_current.txt
index 83a1929..981b38c 100644
--- a/leanback/leanback/api/restricted_current.txt
+++ b/leanback/leanback/api/restricted_current.txt
@@ -1493,61 +1493,6 @@
ctor public SlideNoPropagation(android.content.Context!, android.util.AttributeSet!);
}
- @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class TransitionHelper {
- method public static void addSharedElement(android.app.FragmentTransaction!, android.view.View!, String!);
- method public static void addTarget(Object!, android.view.View!);
- method public static void addTransition(Object!, Object!);
- method public static void addTransitionListener(Object!, androidx.leanback.transition.TransitionListener!);
- method public static void beginDelayedTransition(android.view.ViewGroup!, Object!);
- method public static Object! createAutoTransition();
- method public static Object! createChangeBounds(boolean);
- method public static Object! createChangeTransform();
- method public static Object! createDefaultInterpolator(android.content.Context!);
- method public static Object! createFadeAndShortSlide(int);
- method public static Object! createFadeAndShortSlide(int, float);
- method public static Object! createFadeTransition(int);
- method public static Object! createScale();
- method public static Object! createScene(android.view.ViewGroup!, Runnable!);
- method public static Object! createSlide(int);
- method public static Object! createTransitionSet(boolean);
- method public static void exclude(Object!, int, boolean);
- method public static void exclude(Object!, android.view.View!, boolean);
- method public static void excludeChildren(Object!, int, boolean);
- method public static void excludeChildren(Object!, android.view.View!, boolean);
- method public static Object! getEnterTransition(android.view.Window!);
- method public static Object! getExitTransition(android.view.Window!);
- method public static Object! getReenterTransition(android.view.Window!);
- method public static Object! getReturnTransition(android.view.Window!);
- method public static Object! getSharedElementEnterTransition(android.view.Window!);
- method public static Object! getSharedElementExitTransition(android.view.Window!);
- method public static Object! getSharedElementReenterTransition(android.view.Window!);
- method public static Object! getSharedElementReturnTransition(android.view.Window!);
- method public static void include(Object!, int);
- method public static void include(Object!, android.view.View!);
- method public static Object! loadTransition(android.content.Context!, int);
- method public static void removeTransitionListener(Object!, androidx.leanback.transition.TransitionListener!);
- method public static void runTransition(Object!, Object!);
- method public static void setChangeBoundsDefaultStartDelay(Object!, int);
- method public static void setChangeBoundsStartDelay(Object!, android.view.View!, int);
- method public static void setChangeBoundsStartDelay(Object!, int, int);
- method public static void setChangeBoundsStartDelay(Object!, String!, int);
- method public static void setDuration(Object!, long);
- method public static void setEnterTransition(android.view.Window!, Object!);
- method public static void setEnterTransition(android.app.Fragment!, Object!);
- method public static void setEpicenterCallback(Object!, androidx.leanback.transition.TransitionEpicenterCallback!);
- method public static void setExitTransition(android.app.Fragment!, Object!);
- method public static void setInterpolator(Object!, Object!);
- method public static void setReturnTransition(android.view.Window!, Object!);
- method public static void setSharedElementEnterTransition(android.view.Window!, Object!);
- method public static void setSharedElementEnterTransition(android.app.Fragment!, Object!);
- method public static void setSharedElementReturnTransition(android.view.Window!, Object!);
- method public static void setStartDelay(Object!, long);
- method public static void setTransitionGroup(android.view.ViewGroup!, boolean);
- method public static boolean systemSupportsEntranceTransitions();
- field public static final int FADE_IN = 1; // 0x1
- field public static final int FADE_OUT = 2; // 0x2
- }
-
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class TransitionListener {
ctor public TransitionListener();
method public void onTransitionCancel(Object!);
diff --git a/leanback/leanback/src/main/java/androidx/leanback/transition/TransitionHelper.java b/leanback/leanback/src/main/java/androidx/leanback/transition/TransitionHelper.java
index a22577a..d75c269 100644
--- a/leanback/leanback/src/main/java/androidx/leanback/transition/TransitionHelper.java
+++ b/leanback/leanback/src/main/java/androidx/leanback/transition/TransitionHelper.java
@@ -13,7 +13,7 @@
*/
package androidx.leanback.transition;
-import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import android.animation.TimeInterpolator;
import android.annotation.SuppressLint;
@@ -41,7 +41,7 @@
* Helper for view transitions.
* @hide
*/
-@RestrictTo(LIBRARY_GROUP_PREFIX)
+@RestrictTo(LIBRARY)
public final class TransitionHelper {
public static final int FADE_IN = 0x1;
diff --git a/lifecycle/integration-tests/kotlintestapp/src/androidTest/java/androidx/lifecycle/LifecycleScopeIntegrationTest.kt b/lifecycle/integration-tests/kotlintestapp/src/androidTest/java/androidx/lifecycle/LifecycleScopeIntegrationTest.kt
index 3821ea9..48b2542 100644
--- a/lifecycle/integration-tests/kotlintestapp/src/androidTest/java/androidx/lifecycle/LifecycleScopeIntegrationTest.kt
+++ b/lifecycle/integration-tests/kotlintestapp/src/androidTest/java/androidx/lifecycle/LifecycleScopeIntegrationTest.kt
@@ -56,17 +56,21 @@
@Test
fun alreadyResumed() = runBlocking {
rule.scenario.moveToState(RESUMED)
- assertThat(owner().lifecycleScope.async {
- true
- }.await()).isTrue()
+ assertThat(
+ owner().lifecycleScope.async {
+ true
+ }.await()
+ ).isTrue()
}
@Test
fun createdState() = runBlocking {
rule.scenario.moveToState(CREATED)
- assertThat(owner().lifecycleScope.async {
- true
- }.await()).isTrue()
+ assertThat(
+ owner().lifecycleScope.async {
+ true
+ }.await()
+ ).isTrue()
}
@Test
diff --git a/lifecycle/integration-tests/kotlintestapp/src/test-common/java/androidx.lifecycle/LifecycleCoroutineScopeTestBase.kt b/lifecycle/integration-tests/kotlintestapp/src/test-common/java/androidx.lifecycle/LifecycleCoroutineScopeTestBase.kt
index 0951dee..02ee0a0 100644
--- a/lifecycle/integration-tests/kotlintestapp/src/test-common/java/androidx.lifecycle/LifecycleCoroutineScopeTestBase.kt
+++ b/lifecycle/integration-tests/kotlintestapp/src/test-common/java/androidx.lifecycle/LifecycleCoroutineScopeTestBase.kt
@@ -118,7 +118,8 @@
}
action.join()
assertThat(action.getCompletionExceptionOrNull()).hasMessageThat().isSameInstanceAs(
- "foo")
+ "foo"
+ )
}
}
@@ -135,7 +136,8 @@
}
action.join()
assertThat(action.getCompletionExceptionOrNull()).hasMessageThat().isSameInstanceAs(
- "foo")
+ "foo"
+ )
}
}
@@ -149,11 +151,13 @@
action.cancel()
action.join()
}
- assertThat(runBlocking {
- owner.lifecycleScope.async {
- true
- }.await()
- }).isTrue()
+ assertThat(
+ runBlocking {
+ owner.lifecycleScope.async {
+ true
+ }.await()
+ }
+ ).isTrue()
}
@Test
@@ -165,11 +169,13 @@
}
action.join()
}
- assertThat(runBlocking {
- owner.lifecycleScope.async {
- true
- }.await()
- }).isTrue()
+ assertThat(
+ runBlocking {
+ owner.lifecycleScope.async {
+ true
+ }.await()
+ }
+ ).isTrue()
}
@Test
@@ -180,7 +186,8 @@
throw IllegalArgumentException("why not ?")
}
val result = kotlin.runCatching {
- @Suppress("IMPLICIT_NOTHING_AS_TYPE_PARAMETER",
+ @Suppress(
+ "IMPLICIT_NOTHING_AS_TYPE_PARAMETER",
"IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION"
)
action.await()
@@ -188,10 +195,12 @@
assertThat(result.exceptionOrNull())
.isInstanceOf(IllegalArgumentException::class.java)
}
- assertThat(runBlocking {
- owner.lifecycleScope.async {
- true
- }.await()
- }).isTrue()
+ assertThat(
+ runBlocking {
+ owner.lifecycleScope.async {
+ true
+ }.await()
+ }
+ ).isTrue()
}
}
diff --git a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/AndroidFragment.kt b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/AndroidFragment.kt
index 3f7c8f1..41d82a2 100644
--- a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/AndroidFragment.kt
+++ b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/AndroidFragment.kt
@@ -55,22 +55,27 @@
putString("myarg", editArgs.text.toString())
}
val deeplink = findNavController().createDeepLink()
- .setDestination(R.id.android)
- .setArguments(args)
- .createPendingIntent()
+ .setDestination(R.id.android)
+ .setArguments(args)
+ .createPendingIntent()
val notificationManager = requireContext().getSystemService(
- Context.NOTIFICATION_SERVICE) as NotificationManager
+ Context.NOTIFICATION_SERVICE
+ ) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- notificationManager.createNotificationChannel(NotificationChannel(
- "deeplink", "Deep Links", NotificationManager.IMPORTANCE_HIGH))
+ notificationManager.createNotificationChannel(
+ NotificationChannel(
+ "deeplink", "Deep Links", NotificationManager.IMPORTANCE_HIGH
+ )
+ )
}
val builder = NotificationCompat.Builder(
- requireContext(), "deeplink")
- .setContentTitle("Navigation")
- .setContentText("Deep link to Android")
- .setSmallIcon(R.drawable.ic_android)
- .setContentIntent(deeplink)
- .setAutoCancel(true)
+ requireContext(), "deeplink"
+ )
+ .setContentTitle("Navigation")
+ .setContentText("Deep link to Android")
+ .setSmallIcon(R.drawable.ic_android)
+ .setContentIntent(deeplink)
+ .setAutoCancel(true)
notificationManager.notify(0, builder.build())
}
}
diff --git a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/DeepLinkAppWidgetProvider.kt b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/DeepLinkAppWidgetProvider.kt
index c3560be..118b869 100644
--- a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/DeepLinkAppWidgetProvider.kt
+++ b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/DeepLinkAppWidgetProvider.kt
@@ -32,17 +32,19 @@
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
- val remoteViews = RemoteViews(context.packageName,
- R.layout.deep_link_appwidget)
+ val remoteViews = RemoteViews(
+ context.packageName,
+ R.layout.deep_link_appwidget
+ )
val args = Bundle().apply {
putString("myarg", "From Widget")
}
val pendingIntent = NavDeepLinkBuilder(context)
- .setGraph(R.navigation.nav_main)
- .setDestination(R.id.android)
- .setArguments(args)
- .createPendingIntent()
+ .setGraph(R.navigation.nav_main)
+ .setDestination(R.id.android)
+ .setArguments(args)
+ .createPendingIntent()
remoteViews.setOnClickPendingIntent(R.id.deep_link, pendingIntent)
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews)
diff --git a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/HelpActivity.kt b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/HelpActivity.kt
index d867585..55f03b2 100644
--- a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/HelpActivity.kt
+++ b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/HelpActivity.kt
@@ -84,17 +84,19 @@
savedInstanceState: Bundle?
): View? {
val navigationView = requireActivity().layoutInflater
- .inflate(R.layout.bottom_bar_menu, container, false) as NavigationView
+ .inflate(R.layout.bottom_bar_menu, container, false) as NavigationView
// Add a fake Navigation Graph just to test out the behavior but not
// actually navigate anywhere
- navigationView.setupWithNavController(NavController(requireContext()).apply {
- navigatorProvider.addNavigator(TestNavigator())
- graph = createGraph(startDestination = R.id.launcher_home) {
- test(R.id.launcher_home)
- test(R.id.android)
+ navigationView.setupWithNavController(
+ NavController(requireContext()).apply {
+ navigatorProvider.addNavigator(TestNavigator())
+ graph = createGraph(startDestination = R.id.launcher_home) {
+ test(R.id.launcher_home)
+ test(R.id.android)
+ }
}
- })
+ )
return navigationView
}
}
diff --git a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/MainFragment.kt b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/MainFragment.kt
index 73e15ce..44ae1a2 100644
--- a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/MainFragment.kt
+++ b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/MainFragment.kt
@@ -52,13 +52,16 @@
Color.GREEN
} else {
Color.RED
- })
+ }
+ )
val b = view.findViewById<Button>(R.id.next_button)
ViewCompat.setTransitionName(b, "next")
b.setOnClickListener {
- findNavController().navigate(R.id.next, null, null,
- FragmentNavigatorExtras(b to "next"))
+ findNavController().navigate(
+ R.id.next, null, null,
+ FragmentNavigatorExtras(b to "next")
+ )
}
view.findViewById<Button>(R.id.learn_more).setOnClickListener {
val args = Bundle().apply {
diff --git a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/NavigationActivity.kt b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/NavigationActivity.kt
index e439818..a2d4835 100644
--- a/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/NavigationActivity.kt
+++ b/navigation/integration-tests/testapp/src/main/java/androidx/navigation/testapp/NavigationActivity.kt
@@ -41,18 +41,22 @@
super.onCreate(savedInstanceState)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.my_nav_host_fragment)
- as NavHostFragment
+ as NavHostFragment
val navController = navHostFragment.navController
val toolbar = findViewById<Toolbar>(R.id.toolbar)
val drawerLayout = findViewById<DrawerLayout>(R.id.drawer_layout)
- toolbar.setupWithNavController(navController,
+ toolbar.setupWithNavController(
+ navController,
AppBarConfiguration(
setOf(
R.id.main,
R.id.android_main
- ), drawerLayout,
- ::onSupportNavigateUp))
+ ),
+ drawerLayout,
+ ::onSupportNavigateUp
+ )
+ )
val navigationView = findViewById<NavigationView>(R.id.nav_view)
if (navigationView != null) {
@@ -64,11 +68,16 @@
toolbar.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.help_activity -> {
- navController.navigate(R.id.help_activity, null, null,
- ActivityNavigatorExtras(
- ActivityOptionsCompat
- .makeSceneTransitionAnimation(this,
- toolbar, "toolbar")))
+ navController.navigate(
+ R.id.help_activity, null, null,
+ ActivityNavigatorExtras(
+ ActivityOptionsCompat
+ .makeSceneTransitionAnimation(
+ this,
+ toolbar, "toolbar"
+ )
+ )
+ )
true
} else -> NavigationUI.onNavDestinationSelected(item, navController)
}
diff --git a/navigation/navigation-common-ktx/build.gradle b/navigation/navigation-common-ktx/build.gradle
index ad12d4d..69b4d3e 100644
--- a/navigation/navigation-common-ktx/build.gradle
+++ b/navigation/navigation-common-ktx/build.gradle
@@ -16,9 +16,8 @@
import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
-import androidx.build.AndroidXExtension
import androidx.build.Publish
+import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
plugins {
id("AndroidXPlugin")
@@ -32,6 +31,10 @@
}
}
+kotlin {
+ explicitApi = ExplicitApiMode.Strict
+}
+
dependencies {
api(project(":navigation:navigation-common"))
implementation("androidx.core:core-ktx:1.1.0")
diff --git a/navigation/navigation-common-ktx/src/androidTest/java/androidx/navigation/NavDestinationBuilderTest.kt b/navigation/navigation-common-ktx/src/androidTest/java/androidx/navigation/NavDestinationBuilderTest.kt
index 1616bbb..ff74348 100644
--- a/navigation/navigation-common-ktx/src/androidTest/java/androidx/navigation/NavDestinationBuilderTest.kt
+++ b/navigation/navigation-common-ktx/src/androidTest/java/androidx/navigation/NavDestinationBuilderTest.kt
@@ -64,8 +64,8 @@
.that(destination.arguments.get("testArg")?.defaultValue)
.isEqualTo("123")
assertWithMessage("NavArgument shouldn't have a default value")
- .that(destination.arguments.get("testArg2")?.isDefaultValuePresent)
- .isFalse()
+ .that(destination.arguments.get("testArg2")?.isDefaultValuePresent)
+ .isFalse()
}
@Test
diff --git a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavArgsLazy.kt b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavArgsLazy.kt
index cb4b4ad..35b21b1 100644
--- a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavArgsLazy.kt
+++ b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavArgsLazy.kt
@@ -31,7 +31,7 @@
* [argumentProducer] is a lambda that will be called during initialization to provide
* arguments to construct an [Args] instance via reflection.
*/
-class NavArgsLazy<Args : NavArgs>(
+public class NavArgsLazy<Args : NavArgs>(
private val navArgsClass: KClass<Args>,
private val argumentProducer: () -> Bundle
) : Lazy<Args> {
@@ -55,5 +55,5 @@
return args
}
- override fun isInitialized() = cached != null
+ override fun isInitialized(): Boolean = cached != null
}
diff --git a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavDeepLinkDslBuilder.kt b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavDeepLinkDslBuilder.kt
index 2b0ef14..9472414 100644
--- a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavDeepLinkDslBuilder.kt
+++ b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavDeepLinkDslBuilder.kt
@@ -17,32 +17,32 @@
package androidx.navigation
@DslMarker
-annotation class NavDeepLinkDsl
+public annotation class NavDeepLinkDsl
/**
* Construct a new [NavDeepLink]
*/
-fun navDeepLink(deepLinkBuilder: NavDeepLinkDslBuilder.() -> Unit): NavDeepLink =
- NavDeepLinkDslBuilder().apply(deepLinkBuilder).build()
+public fun navDeepLink(deepLinkBuilder: NavDeepLinkDslBuilder.() -> Unit): NavDeepLink =
+ NavDeepLinkDslBuilder().apply(deepLinkBuilder).build()
/**
* DSL for constructing a new [NavDeepLink]
*/
@NavDeepLinkDsl
-class NavDeepLinkDslBuilder {
+public class NavDeepLinkDslBuilder {
private val builder = NavDeepLink.Builder()
/**
* The uri pattern of the deep link
*/
- var uriPattern: String? = null
+ public var uriPattern: String? = null
/**
* Intent action for the deep link
*
* @throws IllegalArgumentException if attempting to set to empty.
*/
- var action: String? = null
+ public var action: String? = null
@Suppress("DocumentExceptions")
set(p) {
if (p != null && p.isEmpty()) {
@@ -54,7 +54,7 @@
/**
* MimeType for the deep link
*/
- var mimeType: String? = null
+ public var mimeType: String? = null
internal fun build() = builder.apply {
check(!(uriPattern == null && action == null && mimeType == null)) {
diff --git a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavDestinationBuilder.kt b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavDestinationBuilder.kt
index d762f21..faaed71 100644
--- a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavDestinationBuilder.kt
+++ b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavDestinationBuilder.kt
@@ -20,27 +20,27 @@
import androidx.core.os.bundleOf
@DslMarker
-annotation class NavDestinationDsl
+public annotation class NavDestinationDsl
/**
* DSL for constructing a new [NavDestination]
*/
@NavDestinationDsl
-open class NavDestinationBuilder<out D : NavDestination>(
+public open class NavDestinationBuilder<out D : NavDestination>(
protected val navigator: Navigator<out D>,
- @IdRes val id: Int
+ @IdRes public val id: Int
) {
/**
* The descriptive label of the destination
*/
- var label: CharSequence? = null
+ public var label: CharSequence? = null
private var arguments = mutableMapOf<String, NavArgument>()
/**
* Add a [NavArgument] to this destination.
*/
- fun argument(name: String, argumentBuilder: NavArgumentBuilder.() -> Unit) {
+ public fun argument(name: String, argumentBuilder: NavArgumentBuilder.() -> Unit) {
arguments[name] = NavArgumentBuilder().apply(argumentBuilder).build()
}
@@ -64,7 +64,7 @@
* @param uriPattern The uri pattern to add as a deep link
* @see deepLink
*/
- fun deepLink(uriPattern: String) {
+ public fun deepLink(uriPattern: String) {
deepLinks.add(NavDeepLink(uriPattern))
}
@@ -85,7 +85,7 @@
*
* @param navDeepLink the NavDeepLink to be added to this destination
*/
- fun deepLink(navDeepLink: NavDeepLinkDslBuilder.() -> Unit) {
+ public fun deepLink(navDeepLink: NavDeepLinkDslBuilder.() -> Unit) {
deepLinks.add(NavDeepLinkDslBuilder().apply(navDeepLink).build())
}
@@ -94,14 +94,14 @@
/**
* Adds a new [NavAction] to the destination
*/
- fun action(actionId: Int, actionBuilder: NavActionBuilder.() -> Unit) {
+ public fun action(actionId: Int, actionBuilder: NavActionBuilder.() -> Unit) {
actions[actionId] = NavActionBuilder().apply(actionBuilder).build()
}
/**
* Build the NavDestination by calling [Navigator.createDestination].
*/
- open fun build(): D {
+ public open fun build(): D {
return navigator.createDestination().also { destination ->
destination.id = id
destination.label = label
@@ -122,11 +122,11 @@
* DSL for building a [NavAction].
*/
@NavDestinationDsl
-class NavActionBuilder {
+public class NavActionBuilder {
/**
* The ID of the destination that should be navigated to when this action is used
*/
- var destinationId: Int = 0
+ public var destinationId: Int = 0
/**
* The set of default arguments that should be passed to the destination. The keys
@@ -137,29 +137,31 @@
*
* @see NavAction.getDefaultArguments
*/
- val defaultArguments = mutableMapOf<String, Any?>()
+ public val defaultArguments: MutableMap<String, Any?> = mutableMapOf()
private var navOptions: NavOptions? = null
/**
* Sets the [NavOptions] for this action that should be used by default
*/
- fun navOptions(optionsBuilder: NavOptionsBuilder.() -> Unit) {
+ public fun navOptions(optionsBuilder: NavOptionsBuilder.() -> Unit) {
navOptions = NavOptionsBuilder().apply(optionsBuilder).build()
}
- internal fun build() = NavAction(destinationId, navOptions,
+ internal fun build() = NavAction(
+ destinationId, navOptions,
if (defaultArguments.isEmpty())
null
else
- bundleOf(*defaultArguments.toList().toTypedArray()))
+ bundleOf(*defaultArguments.toList().toTypedArray())
+ )
}
/**
* DSL for constructing a new [NavArgument]
*/
@NavDestinationDsl
-class NavArgumentBuilder {
+public class NavArgumentBuilder {
private val builder = NavArgument.Builder()
private var _type: NavType<*>? = null
@@ -169,7 +171,7 @@
* If you don't set a type explicitly, it will be inferred
* from the default value of this argument.
*/
- var type: NavType<*>
+ public var type: NavType<*>
set(value) {
_type = value
builder.setType(value)
@@ -181,7 +183,7 @@
/**
* Controls if this argument allows null values.
*/
- var nullable: Boolean = false
+ public var nullable: Boolean = false
set(value) {
field = value
builder.setIsNullable(value)
@@ -192,7 +194,7 @@
*
* Any object that you set here must be compatible with [type], if it was specified.
*/
- var defaultValue: Any? = null
+ public var defaultValue: Any? = null
set(value) {
field = value
builder.setDefaultValue(value)
@@ -201,7 +203,7 @@
/**
* Builds the NavArgument by calling [NavArgument.Builder.build].
*/
- fun build(): NavArgument {
+ public fun build(): NavArgument {
return builder.build()
}
}
\ No newline at end of file
diff --git a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavGraph.kt b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavGraph.kt
index 26aaf72..b8c2bcc 100644
--- a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavGraph.kt
+++ b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavGraph.kt
@@ -25,11 +25,11 @@
*
* @throws IllegalArgumentException if no destination is found with that id.
*/
-inline operator fun NavGraph.get(@IdRes id: Int): NavDestination =
- findNode(id) ?: throw IllegalArgumentException("No destination for $id was found in $this")
+public inline operator fun NavGraph.get(@IdRes id: Int): NavDestination =
+ findNode(id) ?: throw IllegalArgumentException("No destination for $id was found in $this")
/** Returns `true` if a destination with `id` is found in this navigation graph. */
-operator fun NavGraph.contains(@IdRes id: Int): Boolean = findNode(id) != null
+public operator fun NavGraph.contains(@IdRes id: Int): Boolean = findNode(id) != null
/**
* Adds a destination to this NavGraph. The destination must have an
@@ -41,7 +41,7 @@
*
* @param node destination to add
*/
-inline operator fun NavGraph.plusAssign(node: NavDestination) {
+public inline operator fun NavGraph.plusAssign(node: NavDestination) {
addDestination(node)
}
@@ -52,11 +52,11 @@
* @param other collection of destinations to add. All destinations will be removed from the
* parameter graph after being added to this graph.
*/
-inline operator fun NavGraph.plusAssign(other: NavGraph) {
+public inline operator fun NavGraph.plusAssign(other: NavGraph) {
addAll(other)
}
/** Removes `node` from this navigation graph. */
-inline operator fun NavGraph.minusAssign(node: NavDestination) {
+public inline operator fun NavGraph.minusAssign(node: NavDestination) {
remove(node)
}
diff --git a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavGraphBuilder.kt b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavGraphBuilder.kt
index 0e7337a..e357290 100644
--- a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavGraphBuilder.kt
+++ b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavGraphBuilder.kt
@@ -21,27 +21,27 @@
/**
* Construct a new [NavGraph]
*/
-inline fun NavigatorProvider.navigation(
+public inline fun NavigatorProvider.navigation(
@IdRes id: Int = 0,
@IdRes startDestination: Int,
builder: NavGraphBuilder.() -> Unit
-) = NavGraphBuilder(this, id, startDestination).apply(builder).build()
+): NavGraph = NavGraphBuilder(this, id, startDestination).apply(builder).build()
/**
* Construct a nested [NavGraph]
*/
-inline fun NavGraphBuilder.navigation(
+public inline fun NavGraphBuilder.navigation(
@IdRes id: Int,
@IdRes startDestination: Int,
builder: NavGraphBuilder.() -> Unit
-) = destination(NavGraphBuilder(provider, id, startDestination).apply(builder))
+): Unit = destination(NavGraphBuilder(provider, id, startDestination).apply(builder))
/**
* DSL for constructing a new [NavGraph]
*/
@NavDestinationDsl
-open class NavGraphBuilder(
- val provider: NavigatorProvider,
+public open class NavGraphBuilder(
+ public val provider: NavigatorProvider,
@IdRes id: Int,
@IdRes private var startDestination: Int
) : NavDestinationBuilder<NavGraph>(provider[NavGraphNavigator::class], id) {
@@ -50,21 +50,21 @@
/**
* Build and add a new destination to the [NavGraphBuilder]
*/
- fun <D : NavDestination> destination(navDestination: NavDestinationBuilder<D>) {
+ public fun <D : NavDestination> destination(navDestination: NavDestinationBuilder<D>) {
destinations += navDestination.build()
}
/**
* Adds this destination to the [NavGraphBuilder]
*/
- operator fun NavDestination.unaryPlus() {
+ public operator fun NavDestination.unaryPlus() {
addDestination(this)
}
/**
* Add the destination to the [NavGraphBuilder]
*/
- fun addDestination(destination: NavDestination) {
+ public fun addDestination(destination: NavDestination) {
destinations += destination
}
diff --git a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavOptionsBuilder.kt b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavOptionsBuilder.kt
index ad9cf24..1e20b20 100644
--- a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavOptionsBuilder.kt
+++ b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavOptionsBuilder.kt
@@ -21,19 +21,19 @@
import androidx.annotation.IdRes
@DslMarker
-annotation class NavOptionsDsl
+public annotation class NavOptionsDsl
/**
* Construct a new [NavOptions]
*/
-fun navOptions(optionsBuilder: NavOptionsBuilder.() -> Unit): NavOptions =
- NavOptionsBuilder().apply(optionsBuilder).build()
+public fun navOptions(optionsBuilder: NavOptionsBuilder.() -> Unit): NavOptions =
+ NavOptionsBuilder().apply(optionsBuilder).build()
/**
* DSL for constructing a new [NavOptions]
*/
@NavOptionsDsl
-class NavOptionsBuilder {
+public class NavOptionsBuilder {
private val builder = NavOptions.Builder()
/**
@@ -43,14 +43,14 @@
* This functions similarly to how [android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP]
* works with activites.
*/
- var launchSingleTop = false
+ public var launchSingleTop: Boolean = false
/**
* Pop up to a given destination before navigating. This pops all non-matching destinations
* from the back stack until this destination is found.
*/
@IdRes
- var popUpTo: Int = -1
+ public var popUpTo: Int = -1
set(value) {
field = value
inclusive = false
@@ -61,7 +61,7 @@
* Pop up to a given destination before navigating. This pops all non-matching destinations
* from the back stack until this destination is found.
*/
- fun popUpTo(@IdRes id: Int, popUpToBuilder: PopUpToBuilder.() -> Unit) {
+ public fun popUpTo(@IdRes id: Int, popUpToBuilder: PopUpToBuilder.() -> Unit) {
popUpTo = id
inclusive = PopUpToBuilder().apply(popUpToBuilder).inclusive
}
@@ -71,12 +71,12 @@
*
* Note: Animator resources are not supported for navigating to a new Activity
*/
- fun anim(animBuilder: AnimBuilder.() -> Unit) {
+ public fun anim(animBuilder: AnimBuilder.() -> Unit) {
AnimBuilder().apply(animBuilder).run {
[email protected](enter)
- .setExitAnim(exit)
- .setPopEnterAnim(popEnter)
- .setPopExitAnim(popExit)
+ .setExitAnim(exit)
+ .setPopEnterAnim(popEnter)
+ .setPopExitAnim(popExit)
}
}
@@ -90,18 +90,18 @@
* DSL for customizing [NavOptionsBuilder.popUpTo] operations.
*/
@NavOptionsDsl
-class PopUpToBuilder {
+public class PopUpToBuilder {
/**
* Whether the `popUpTo` destination should be popped from the back stack.
*/
- var inclusive: Boolean = false
+ public var inclusive: Boolean = false
}
/**
* DSL for setting custom Animation or Animator resources on a [NavOptionsBuilder]
*/
@NavOptionsDsl
-class AnimBuilder {
+public class AnimBuilder {
/**
* The custom Animation or Animator resource for the enter animation.
*
@@ -109,7 +109,7 @@
*/
@AnimRes
@AnimatorRes
- var enter = -1
+ public var enter: Int = -1
/**
* The custom Animation or Animator resource for the exit animation.
@@ -118,7 +118,7 @@
*/
@AnimRes
@AnimatorRes
- var exit = -1
+ public var exit: Int = -1
/**
* The custom Animation or Animator resource for the enter animation
@@ -128,7 +128,7 @@
*/
@AnimRes
@AnimatorRes
- var popEnter = -1
+ public var popEnter: Int = -1
/**
* The custom Animation or Animator resource for the exit animation
@@ -138,5 +138,5 @@
*/
@AnimRes
@AnimatorRes
- var popExit = -1
+ public var popExit: Int = -1
}
diff --git a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavigatorProvider.kt b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavigatorProvider.kt
index 3535cdc..639ab83 100644
--- a/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavigatorProvider.kt
+++ b/navigation/navigation-common-ktx/src/main/java/androidx/navigation/NavigatorProvider.kt
@@ -25,8 +25,9 @@
*
* @throws IllegalStateException if the Navigator has not been added
*/
-inline operator fun <T : Navigator<out NavDestination>> NavigatorProvider.get(name: String): T =
- getNavigator(name)
+public inline operator fun <T : Navigator<out NavDestination>> NavigatorProvider.get(
+ name: String
+): T = getNavigator(name)
/**
* Retrieves a registered [Navigator] using the name provided by the
@@ -34,7 +35,7 @@
*
* @throws IllegalStateException if the Navigator has not been added
*/
-inline operator fun <T : Navigator<out NavDestination>> NavigatorProvider.get(
+public inline operator fun <T : Navigator<out NavDestination>> NavigatorProvider.get(
clazz: KClass<T>
): T = getNavigator(clazz.java)
@@ -44,15 +45,15 @@
*
* @return the previously added [Navigator] for the given name, if any
*/
-inline operator fun NavigatorProvider.set(
+public inline operator fun NavigatorProvider.set(
name: String,
navigator: Navigator<out NavDestination>
-) = addNavigator(name, navigator)
+): Navigator<out NavDestination>? = addNavigator(name, navigator)
/**
* Register a navigator using the name provided by the
* [Navigator.Name annotation][Navigator.Name].
*/
-inline operator fun NavigatorProvider.plusAssign(navigator: Navigator<out NavDestination>) {
+public inline operator fun NavigatorProvider.plusAssign(navigator: Navigator<out NavDestination>) {
addNavigator(navigator)
}
diff --git a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkActionTest.kt b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkActionTest.kt
index b11cdd1..539817a 100644
--- a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkActionTest.kt
+++ b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkActionTest.kt
@@ -35,8 +35,14 @@
val deepLink = NavDeepLink(DEEP_LINK_EXACT_HTTPS, DEEP_LINK_ACTION, null)
assertWithMessage("The actions should not have matched")
- .that(deepLink.matches(NavDeepLinkRequest(Uri.parse(DEEP_LINK_EXACT_HTTPS),
- null, null)))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ Uri.parse(DEEP_LINK_EXACT_HTTPS),
+ null, null
+ )
+ )
+ )
.isFalse()
}
@@ -45,8 +51,14 @@
val deepLink = NavDeepLink(DEEP_LINK_EXACT_HTTPS, DEEP_LINK_ACTION, null)
assertWithMessage("The actions should have matched")
- .that(deepLink.matches(NavDeepLinkRequest(Uri.parse(DEEP_LINK_EXACT_HTTPS),
- DEEP_LINK_ACTION, null)))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ Uri.parse(DEEP_LINK_EXACT_HTTPS),
+ DEEP_LINK_ACTION, null
+ )
+ )
+ )
.isTrue()
}
diff --git a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkMimeTypeTest.kt b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkMimeTypeTest.kt
index 44b5f87..959dc2c 100644
--- a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkMimeTypeTest.kt
+++ b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkMimeTypeTest.kt
@@ -39,7 +39,7 @@
assertThat(e)
.hasMessageThat().contains(
"The given mimeType $mimeType does not match to required \"type/subtype\" " +
- "format"
+ "format"
)
}
}
@@ -50,8 +50,13 @@
val deepLink = NavDeepLink(null, null, mimeType)
assertWithMessage("The mimeTypes should match")
- .that(deepLink.matches(NavDeepLinkRequest(
- null, null, mimeType)))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ null, null, mimeType
+ )
+ )
+ )
.isTrue()
}
@@ -61,8 +66,13 @@
val deepLink = NavDeepLink(DEEP_LINK_EXACT_HTTPS, null, mimeType)
assertWithMessage("The mimeTypes should match")
- .that(deepLink.matches(NavDeepLinkRequest(
- Uri.parse(DEEP_LINK_EXACT_HTTPS), null, mimeType)))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ Uri.parse(DEEP_LINK_EXACT_HTTPS), null, mimeType
+ )
+ )
+ )
.isTrue()
}
@@ -72,8 +82,13 @@
val deepLink = NavDeepLink(null, null, mimeType)
assertWithMessage("The mimeTypes should match")
- .that(deepLink.matches(NavDeepLinkRequest(
- null, null, "type/subtype")))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ null, null, "type/subtype"
+ )
+ )
+ )
.isTrue()
}
@@ -83,8 +98,13 @@
val deepLink = NavDeepLink(null, null, mimeType)
assertWithMessage("The mimeTypes should match")
- .that(deepLink.matches(NavDeepLinkRequest(
- null, null, "type/subtype")))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ null, null, "type/subtype"
+ )
+ )
+ )
.isTrue()
}
@@ -94,8 +114,13 @@
val deepLink = NavDeepLink(null, null, mimeType)
assertWithMessage("The mimeTypes should match")
- .that(deepLink.matches(NavDeepLinkRequest(
- null, null, "type/subtype")))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ null, null, "type/subtype"
+ )
+ )
+ )
.isTrue()
}
@@ -105,8 +130,13 @@
val deepLink = NavDeepLink(null, null, mimeType)
assertWithMessage("The mimeTypes should match")
- .that(deepLink.matches(NavDeepLinkRequest(
- null, null, "*/*")))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ null, null, "*/*"
+ )
+ )
+ )
.isTrue()
}
@@ -116,8 +146,13 @@
val deepLink = NavDeepLink(null, null, mimeType)
assertWithMessage("The mimeTypes should match")
- .that(deepLink.matches(NavDeepLinkRequest(
- null, null, "type/*")))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ null, null, "type/*"
+ )
+ )
+ )
.isTrue()
}
@@ -127,8 +162,13 @@
val deepLink = NavDeepLink(null, null, mimeType)
assertWithMessage("The mimeTypes should match")
- .that(deepLink.matches(NavDeepLinkRequest(
- null, null, "*/subtype")))
+ .that(
+ deepLink.matches(
+ NavDeepLinkRequest(
+ null, null, "*/subtype"
+ )
+ )
+ )
.isTrue()
}
}
\ No newline at end of file
diff --git a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkTest.kt b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkTest.kt
index 34b4dc6..50dbe6c 100644
--- a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkTest.kt
+++ b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkTest.kt
@@ -146,8 +146,10 @@
val myArg = "test"
val matchArgs = deepLink.getMatchingArguments(
Uri.parse(deepLinkArgument.replace("{id}", id.toString()).replace("{myarg}", myArg)),
- mapOf("id" to intArgument(),
- "myarg" to stringArgument())
+ mapOf(
+ "id" to intArgument(),
+ "myarg" to stringArgument()
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -170,8 +172,10 @@
val myArg = "test"
val matchArgs = deepLink.getMatchingArguments(
Uri.parse(deepLinkArgument.replace("{id}", id.toString()).replace("{myarg}", myArg)),
- mapOf("id" to intArgument(),
- "myarg" to stringArgument())
+ mapOf(
+ "id" to intArgument(),
+ "myarg" to stringArgument()
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -194,8 +198,10 @@
val id = 211
val matchArgs = deepLink.getMatchingArguments(
Uri.parse(deepLinkArgument.replace("{id}", id.toString())),
- mapOf("id" to intArgument(),
- "myarg" to stringArgument())
+ mapOf(
+ "id" to intArgument(),
+ "myarg" to stringArgument()
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -269,10 +275,14 @@
val id = 2
val myarg = "test"
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse(deepLinkArgument
- .replace("{id}", id.toString()).replace("{myarg}", myarg)),
- mapOf("id" to intArgument(),
- "myarg" to stringArgument())
+ Uri.parse(
+ deepLinkArgument
+ .replace("{id}", id.toString()).replace("{myarg}", myarg)
+ ),
+ mapOf(
+ "id" to intArgument(),
+ "myarg" to stringArgument()
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -366,8 +376,10 @@
val optional = "test"
val matchArgs = deepLink.getMatchingArguments(
Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?id={id}".replace("{id}", id.toString())),
- mapOf("id" to intArgument(),
- "optional" to stringArgument(optional))
+ mapOf(
+ "id" to intArgument(),
+ "optional" to stringArgument(optional)
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -388,10 +400,14 @@
val id = 2
val optional = "test"
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?optional={optional}&id={id}"
- .replace("{id}", id.toString())),
- mapOf("id" to intArgument(),
- "optional" to stringArgument(optional))
+ Uri.parse(
+ "$DEEP_LINK_EXACT_HTTPS/users?optional={optional}&id={id}"
+ .replace("{id}", id.toString())
+ ),
+ mapOf(
+ "id" to intArgument(),
+ "optional" to stringArgument(optional)
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -412,8 +428,10 @@
val id = 2
val matchArgs = deepLink.getMatchingArguments(
Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?id={id}".replace("{id}", id.toString())),
- mapOf("id" to intArgument(),
- "optional" to nullableStringArgument())
+ mapOf(
+ "id" to intArgument(),
+ "optional" to nullableStringArgument()
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -432,8 +450,11 @@
val deepLinkArgument = "$DEEP_LINK_EXACT_HTTPS/users"
val deepLink = NavDeepLink(deepLinkArgument)
- assertThat(deepLink.matches(
- Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?extraParam={extraParam}"))).isTrue()
+ assertThat(
+ deepLink.matches(
+ Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?extraParam={extraParam}")
+ )
+ ).isTrue()
}
@Test
@@ -463,9 +484,12 @@
val id = 2
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?id={id}&extraParam={extraParam}"
- .replace("{id}", id.toString())),
- mapOf("id" to intArgument()))
+ Uri.parse(
+ "$DEEP_LINK_EXACT_HTTPS/users?id={id}&extraParam={extraParam}"
+ .replace("{id}", id.toString())
+ ),
+ mapOf("id" to intArgument())
+ )
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -517,8 +541,10 @@
val id = 2
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?string={id}"
- .replace("{id}", id.toString())),
+ Uri.parse(
+ "$DEEP_LINK_EXACT_HTTPS/users?string={id}"
+ .replace("{id}", id.toString())
+ ),
mapOf("id" to intArgument())
)
assertWithMessage("Args should not be null")
@@ -626,8 +652,10 @@
val last = "Doe"
val matchArgs = deepLink.getMatchingArguments(
Uri.parse(deepLinkArgument.replace("{first}", first).replace("{last}", last)),
- mapOf("first" to stringArgument(),
- "last" to stringArgument())
+ mapOf(
+ "first" to stringArgument(),
+ "last" to stringArgument()
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -649,8 +677,10 @@
val last = "Doe"
val matchArgs = deepLink.getMatchingArguments(
Uri.parse("$DEEP_LINK_EXACT_HTTPS/users"),
- mapOf("first" to stringArgument(first),
- "last" to stringArgument(last))
+ mapOf(
+ "first" to stringArgument(first),
+ "last" to stringArgument(last)
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -672,8 +702,10 @@
val last = "Doe"
val matchArgs = deepLink.getMatchingArguments(
Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?name=Jane_"),
- mapOf("first" to stringArgument(),
- "last" to stringArgument(last))
+ mapOf(
+ "first" to stringArgument(),
+ "last" to stringArgument(last)
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -693,8 +725,10 @@
val matchArgs = deepLink.getMatchingArguments(
Uri.parse("$DEEP_LINK_EXACT_HTTPS/users"),
- mapOf("first" to nullableStringArgument(),
- "last" to nullableStringArgument())
+ mapOf(
+ "first" to nullableStringArgument(),
+ "last" to nullableStringArgument()
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -714,8 +748,10 @@
val id = 2
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?productId=wildCardMatch-{id}"
- .replace("{id}", id.toString())),
+ Uri.parse(
+ "$DEEP_LINK_EXACT_HTTPS/users?productId=wildCardMatch-{id}"
+ .replace("{id}", id.toString())
+ ),
mapOf("id" to intArgument())
)
assertWithMessage("Args should not be null")
@@ -787,8 +823,10 @@
val id = 2
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?productId=A*B{id}"
- .replace("{id}", id.toString())),
+ Uri.parse(
+ "$DEEP_LINK_EXACT_HTTPS/users?productId=A*B{id}"
+ .replace("{id}", id.toString())
+ ),
mapOf("id" to intArgument())
)
assertWithMessage("Args should not be null")
@@ -806,8 +844,10 @@
val id = 2
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?productId={id}A*B"
- .replace("{id}", id.toString())),
+ Uri.parse(
+ "$DEEP_LINK_EXACT_HTTPS/users?productId={id}A*B"
+ .replace("{id}", id.toString())
+ ),
mapOf("id" to intArgument())
)
assertWithMessage("Args should not be null")
@@ -918,11 +958,15 @@
val id = 2
val postId = 42
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse(deepLinkArgument
- .replace("{id}", id.toString())
- .replace("{postId}", postId.toString())),
- mapOf("id" to intArgument(),
- "postId" to intArgument())
+ Uri.parse(
+ deepLinkArgument
+ .replace("{id}", id.toString())
+ .replace("{postId}", postId.toString())
+ ),
+ mapOf(
+ "id" to intArgument(),
+ "postId" to intArgument()
+ )
)
assertWithMessage("Args should not be null")
.that(matchArgs)
@@ -969,9 +1013,11 @@
val postId = 2
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse(deepLinkMultiple
- .replace(".*", "test")
- .replace("{postId}", postId.toString())),
+ Uri.parse(
+ deepLinkMultiple
+ .replace(".*", "test")
+ .replace("{postId}", postId.toString())
+ ),
mapOf("postId" to intArgument())
)
assertWithMessage("Args should not be null")
@@ -989,9 +1035,11 @@
val id = 2
val matchArgs = deepLink.getMatchingArguments(
- Uri.parse(deepLinkMultiple
- .replace("{id}", id.toString())
- .replace(".*", "test")),
+ Uri.parse(
+ deepLinkMultiple
+ .replace("{id}", id.toString())
+ .replace(".*", "test")
+ ),
mapOf("id" to intArgument())
)
assertWithMessage("Args should not be null")
diff --git a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDestinationAndroidTest.kt b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDestinationAndroidTest.kt
index 404931b..f609a5c 100644
--- a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDestinationAndroidTest.kt
+++ b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDestinationAndroidTest.kt
@@ -34,7 +34,8 @@
destination.addDeepLink("www.example.com/users/{id}")
val match = destination.matchDeepLink(
- Uri.parse("https://www.example.com/users/43"))
+ Uri.parse("https://www.example.com/users/43")
+ )
assertWithMessage("Deep link should match")
.that(match)
@@ -55,7 +56,8 @@
destination.addDeepLink("www.example.com/users/{name}")
val match = destination.matchDeepLink(
- Uri.parse("https://www.example.com/users/index.html"))
+ Uri.parse("https://www.example.com/users/index.html")
+ )
assertWithMessage("Deep link should match")
.that(match)
@@ -92,7 +94,8 @@
destination.addDeepLink("www.example.com/users/{id}/posts/{postId}")
val match = destination.matchDeepLink(
- Uri.parse("https://www.example.com/users/43/posts/99"))
+ Uri.parse("https://www.example.com/users/43/posts/99")
+ )
assertWithMessage("Deep link should match")
.that(match)
@@ -113,16 +116,27 @@
val destination = NoOpNavigator().createDestination()
destination.addArgument("deeplink1", stringArgument())
- destination.addDeepLink(NavDeepLink("www.example.com/users/{deeplink1}",
- null, "*/*"))
+ destination.addDeepLink(
+ NavDeepLink(
+ "www.example.com/users/{deeplink1}",
+ null, "*/*"
+ )
+ )
destination.addArgument("deeplink2", stringArgument())
- destination.addDeepLink(NavDeepLink("www.example.com/users/{deeplink2}",
- null, "image/*"))
+ destination.addDeepLink(
+ NavDeepLink(
+ "www.example.com/users/{deeplink2}",
+ null, "image/*"
+ )
+ )
val match = destination.matchDeepLink(
- NavDeepLinkRequest(Uri.parse("https://www.example.com/users/result"), null,
- "image/jpg"))
+ NavDeepLinkRequest(
+ Uri.parse("https://www.example.com/users/result"), null,
+ "image/jpg"
+ )
+ )
assertWithMessage("Deep link should match")
.that(match)
@@ -170,9 +184,11 @@
destination.addArgument("stringArg", stringArgument("aaa"))
destination.addArgument("intArg", intArgument(123))
- val bundle = destination.addInDefaultArgs(Bundle().apply {
- putString("stringArg", "bbb")
- })
+ val bundle = destination.addInDefaultArgs(
+ Bundle().apply {
+ putString("stringArg", "bbb")
+ }
+ )
assertThat(bundle?.getString("stringArg")).isEqualTo("bbb")
assertThat(bundle?.getInt("intArg")).isEqualTo(123)
}
@@ -183,8 +199,10 @@
destination.addArgument("stringArg", stringArgument("aaa"))
destination.addArgument("intArg", intArgument(123))
- destination.addInDefaultArgs(Bundle().apply {
- putInt("stringArg", 123)
- })
+ destination.addInDefaultArgs(
+ Bundle().apply {
+ putInt("stringArg", 123)
+ }
+ )
}
}
diff --git a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavGraphAndroidTest.kt b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavGraphAndroidTest.kt
index 9e046f6..3825d87 100644
--- a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavGraphAndroidTest.kt
+++ b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavGraphAndroidTest.kt
@@ -46,7 +46,8 @@
graph.addDeepLink("www.example.com/users/{id}")
val match = graph.matchDeepLink(
- Uri.parse("https://www.example.com/users/43"))
+ Uri.parse("https://www.example.com/users/43")
+ )
assertWithMessage("Deep link should match")
.that(match)
@@ -74,7 +75,8 @@
graph.addDeepLink("www.example.com/users/{name}")
val match = graph.matchDeepLink(
- Uri.parse("https://www.example.com/users/index.html"))
+ Uri.parse("https://www.example.com/users/index.html")
+ )
assertWithMessage("Deep link should match")
.that(match)
@@ -125,7 +127,8 @@
graph.addDeepLink("www.example.com/users/{id}/posts/{postId}")
val match = graph.matchDeepLink(
- Uri.parse("https://www.example.com/users/43/posts/99"))
+ Uri.parse("https://www.example.com/users/43/posts/99")
+ )
assertWithMessage("Deep link should match")
.that(match)
@@ -173,7 +176,8 @@
graph.addDestination(postDestination)
val match = graph.matchDeepLink(
- Uri.parse("https://www.example.com/users/43/posts/99"))
+ Uri.parse("https://www.example.com/users/43/posts/99")
+ )
assertWithMessage("Deep link should match")
.that(match)
@@ -203,7 +207,7 @@
startDestination = DESTINATION_ID
}
val expected = "NavGraph(0x${GRAPH_ID.toString(16)}) label=$GRAPH_LABEL " +
- "startDestination=0x${DESTINATION_ID.toString(16)}"
+ "startDestination=0x${DESTINATION_ID.toString(16)}"
assertThat(graph.toString()).isEqualTo(expected)
}
@@ -226,8 +230,8 @@
addDestination(destination)
}
val expected = "NavGraph(0x${GRAPH_ID.toString(16)}) label=$GRAPH_LABEL " +
- "startDestination={NavDestination(0x${DESTINATION_ID.toString(16)}) " +
- "label=$DESTINATION_LABEL}"
+ "startDestination={NavDestination(0x${DESTINATION_ID.toString(16)}) " +
+ "label=$DESTINATION_LABEL}"
assertThat(graph.toString()).isEqualTo(expected)
}
}
diff --git a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavTypeTest.kt b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavTypeTest.kt
index 7243c4f..3b590be 100644
--- a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavTypeTest.kt
+++ b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavTypeTest.kt
@@ -49,11 +49,11 @@
private val serializables = arrayOf(Bitmap.Config.ALPHA_8)
private val parcelableNavType = NavType.ParcelableType(ActivityInfo::class.java)
private val parcelableArrayNavType =
- NavType.ParcelableArrayType(ActivityInfo::class.java)
+ NavType.ParcelableArrayType(ActivityInfo::class.java)
private val serializableNavType = NavType.SerializableType(Person::class.java)
private val enumNavType = NavType.EnumType(Bitmap.Config::class.java)
private val serializableArrayNavType =
- NavType.SerializableArrayType(Bitmap.Config::class.java)
+ NavType.SerializableArrayType(Bitmap.Config::class.java)
}
@Test
@@ -83,7 +83,7 @@
assertThat(NavType.fromArgType("android.content.pm.ActivityInfo[]", null))
.isEqualTo(parcelableArrayNavType)
assertThat(NavType.fromArgType("androidx.navigation.NavTypeTest\$Person", null))
- .isEqualTo(serializableNavType)
+ .isEqualTo(serializableNavType)
assertThat(NavType.fromArgType("android.graphics.Bitmap\$Config", null))
.isEqualTo(enumNavType)
assertThat(NavType.fromArgType("android.graphics.Bitmap\$Config[]", null))
@@ -135,7 +135,7 @@
assertThat(NavType.inferFromValueType(en))
.isEqualTo(enumNavType)
assertThat(NavType.inferFromValueType(serializable))
- .isEqualTo(serializableNavType)
+ .isEqualTo(serializableNavType)
assertThat(NavType.inferFromValueType(serializables))
.isEqualTo(serializableArrayNavType)
assertThat(NavType.inferFromValueType(null))
@@ -213,7 +213,7 @@
serializableNavType.put(bundle, key, serializable)
assertThat(serializableNavType.get(bundle, key))
- .isEqualTo(serializable)
+ .isEqualTo(serializable)
bundle.clear()
serializableArrayNavType.put(bundle, key, serializables)
diff --git a/navigation/navigation-common/src/test/java/androidx/navigation/NavDestinationTest.kt b/navigation/navigation-common/src/test/java/androidx/navigation/NavDestinationTest.kt
index d4baa29..c878890 100644
--- a/navigation/navigation-common/src/test/java/androidx/navigation/NavDestinationTest.kt
+++ b/navigation/navigation-common/src/test/java/androidx/navigation/NavDestinationTest.kt
@@ -41,8 +41,10 @@
@Test
fun parseClassFromNameAbsolute() {
val context = mock(Context::class.java)
- val clazz = NavDestination.parseClassFromName(context,
- "java.lang.String", Any::class.java)
+ val clazz = NavDestination.parseClassFromName(
+ context,
+ "java.lang.String", Any::class.java
+ )
assertThat(clazz).isNotNull()
assertThat(clazz.name).isEqualTo(String::class.java.name)
}
@@ -51,8 +53,10 @@
fun parseClassFromNameAbsoluteInvalid() {
val context = mock(Context::class.java)
try {
- NavDestination.parseClassFromName(context,
- "definitely.not.found", Any::class.java)
+ NavDestination.parseClassFromName(
+ context,
+ "definitely.not.found", Any::class.java
+ )
fail("Invalid type should cause an IllegalArgumentException")
} catch (e: IllegalArgumentException) {
// Expected
@@ -62,8 +66,10 @@
@Test
fun parseClassFromNameAbsoluteWithType() {
val context = mock(Context::class.java)
- val clazz = NavDestination.parseClassFromName(context,
- "java.lang.String", String::class.java)
+ val clazz = NavDestination.parseClassFromName(
+ context,
+ "java.lang.String", String::class.java
+ )
assertThat(clazz).isNotNull()
assertThat(clazz.name).isEqualTo(String::class.java.name)
}
@@ -72,8 +78,10 @@
fun parseClassFromNameAbsoluteWithIncorrectType() {
val context = mock(Context::class.java)
try {
- NavDestination.parseClassFromName(context,
- "java.lang.String", List::class.java)
+ NavDestination.parseClassFromName(
+ context,
+ "java.lang.String", List::class.java
+ )
fail("Incorrect type should cause an IllegalArgumentException")
} catch (e: IllegalArgumentException) {
// Expected
@@ -84,8 +92,10 @@
fun parseClassFromNameRelative() {
val context = mock(Context::class.java)
`when`(context.packageName).thenReturn("java.lang")
- val clazz = NavDestination.parseClassFromName(context,
- ".String", Any::class.java)
+ val clazz = NavDestination.parseClassFromName(
+ context,
+ ".String", Any::class.java
+ )
assertThat(clazz).isNotNull()
assertThat(clazz.name).isEqualTo(String::class.java.name)
}
@@ -95,8 +105,10 @@
val context = mock(Context::class.java)
`when`(context.packageName).thenReturn("java.lang")
try {
- NavDestination.parseClassFromName(context,
- ".definitely.not.found", Any::class.java)
+ NavDestination.parseClassFromName(
+ context,
+ ".definitely.not.found", Any::class.java
+ )
fail("Invalid type should cause an IllegalArgumentException")
} catch (e: IllegalArgumentException) {
// Expected
@@ -107,8 +119,10 @@
fun parseClassFromNameRelativeWithType() {
val context = mock(Context::class.java)
`when`(context.packageName).thenReturn("java.lang")
- val clazz = NavDestination.parseClassFromName(context,
- ".String", String::class.java)
+ val clazz = NavDestination.parseClassFromName(
+ context,
+ ".String", String::class.java
+ )
assertThat(clazz).isNotNull()
assertThat(clazz.name).isEqualTo(String::class.java.name)
}
@@ -118,8 +132,10 @@
val context = mock(Context::class.java)
`when`(context.packageName).thenReturn("java.lang")
try {
- NavDestination.parseClassFromName(context,
- ".String", List::class.java)
+ NavDestination.parseClassFromName(
+ context,
+ ".String", List::class.java
+ )
fail("Incorrect type should cause an IllegalArgumentException")
} catch (e: IllegalArgumentException) {
// Expected
diff --git a/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphNavigatorTest.kt b/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphNavigatorTest.kt
index 5009c64..cd5e75f 100644
--- a/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphNavigatorTest.kt
+++ b/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphNavigatorTest.kt
@@ -42,9 +42,11 @@
fun setup() {
provider = NavigatorProvider().apply {
addNavigator(NoOpNavigator().also { noOpNavigator = it })
- addNavigator(NavGraphNavigator(this).also {
- navGraphNavigator = it
- })
+ addNavigator(
+ NavGraphNavigator(this).also {
+ navGraphNavigator = it
+ }
+ )
}
}
@@ -100,8 +102,12 @@
val destination = createFirstDestination()
val graph = createGraphWithDestination(destination)
// singleTop should still show as added on an empty stack
- assertThat(navGraphNavigator.navigate(graph, null,
- NavOptions.Builder().setLaunchSingleTop(true).build(), null))
+ assertThat(
+ navGraphNavigator.navigate(
+ graph, null,
+ NavOptions.Builder().setLaunchSingleTop(true).build(), null
+ )
+ )
.isEqualTo(destination)
}
@@ -111,8 +117,12 @@
val graph = createGraphWithDestination(destination)
assertThat(navGraphNavigator.navigate(graph, null, null, null))
.isEqualTo(destination)
- assertThat(navGraphNavigator.navigate(graph, null,
- NavOptions.Builder().setLaunchSingleTop(true).build(), null))
+ assertThat(
+ navGraphNavigator.navigate(
+ graph, null,
+ NavOptions.Builder().setLaunchSingleTop(true).build(), null
+ )
+ )
.isEqualTo(destination)
}
@@ -126,8 +136,12 @@
}
assertThat(navGraphNavigator.navigate(graph, null, null, null))
.isEqualTo(destination)
- assertThat(navGraphNavigator.navigate(secondGraph, null,
- NavOptions.Builder().setLaunchSingleTop(true).build(), null))
+ assertThat(
+ navGraphNavigator.navigate(
+ secondGraph, null,
+ NavOptions.Builder().setLaunchSingleTop(true).build(), null
+ )
+ )
.isEqualTo(secondDestination)
}
@@ -140,8 +154,12 @@
val graph = createGraphWithDestination(nestedGraph)
assertThat(navGraphNavigator.navigate(graph, null, null, null))
.isEqualTo(destination)
- assertThat(navGraphNavigator.navigate(graph, null,
- NavOptions.Builder().setLaunchSingleTop(true).build(), null))
+ assertThat(
+ navGraphNavigator.navigate(
+ graph, null,
+ NavOptions.Builder().setLaunchSingleTop(true).build(), null
+ )
+ )
.isEqualTo(destination)
}
}
diff --git a/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphTest.kt b/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphTest.kt
index 9e44438..8408a8e 100644
--- a/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphTest.kt
+++ b/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphTest.kt
@@ -44,9 +44,11 @@
fun setup() {
provider = NavigatorProvider().apply {
addNavigator(NoOpNavigator().also { noOpNavigator = it })
- addNavigator(NavGraphNavigator(this).also {
- navGraphNavigator = it
- })
+ addNavigator(
+ NavGraphNavigator(this).also {
+ navGraphNavigator = it
+ }
+ )
}
}
@@ -59,14 +61,14 @@
}
private fun createGraphWithDestination(destination: NavDestination) =
- navGraphNavigator.createDestination().apply {
- addDestination(destination)
- }
+ navGraphNavigator.createDestination().apply {
+ addDestination(destination)
+ }
private fun createGraphWithDestinations(vararg destinations: NavDestination) =
- navGraphNavigator.createDestination().apply {
- addDestinations(*destinations)
- }
+ navGraphNavigator.createDestination().apply {
+ addDestinations(*destinations)
+ }
@Test(expected = IllegalArgumentException::class)
fun addDestinationWithoutId() {
@@ -96,7 +98,7 @@
assertWithMessage("Adding destination with same id as its parent should fail")
.that(e).hasMessageThat().contains(
"Destination $destination cannot have the same id as graph $graph"
- )
+ )
}
}
@@ -110,7 +112,8 @@
graph.startDestination = destination.id
} catch (e: IllegalArgumentException) {
assertWithMessage("Setting a start destination with same id as its parent should fail")
- .that(e).hasMessageThat().contains("Start destination " + destination.id +
+ .that(e).hasMessageThat().contains(
+ "Start destination " + destination.id +
" cannot use the same id as the graph $graph"
)
}
diff --git a/navigation/navigation-common/src/test/java/androidx/navigation/NavigatorProviderTest.kt b/navigation/navigation-common/src/test/java/androidx/navigation/NavigatorProviderTest.kt
index 0ac72e9..878a6da 100644
--- a/navigation/navigation-common/src/test/java/androidx/navigation/NavigatorProviderTest.kt
+++ b/navigation/navigation-common/src/test/java/androidx/navigation/NavigatorProviderTest.kt
@@ -31,8 +31,10 @@
val navigator = NoNameNavigator()
try {
provider.addNavigator(navigator)
- fail("Adding a provider with no @Navigator.Name should cause an " +
- "IllegalArgumentException")
+ fail(
+ "Adding a provider with no @Navigator.Name should cause an " +
+ "IllegalArgumentException"
+ )
} catch (e: IllegalArgumentException) {
// Expected
}
@@ -70,8 +72,10 @@
provider.addNavigator("name", navigator)
try {
provider.getNavigator(NoNameNavigator::class.java)
- fail("getNavigator(Class) with no @Navigator.Name should cause an " +
- "IllegalArgumentException")
+ fail(
+ "getNavigator(Class) with no @Navigator.Name should cause an " +
+ "IllegalArgumentException"
+ )
} catch (e: IllegalArgumentException) {
// Expected
}
diff --git a/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilderTest.kt b/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilderTest.kt
index 1246dfba..7c33183 100644
--- a/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilderTest.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/androidTest/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilderTest.kt
@@ -55,8 +55,8 @@
@Test fun moduleName() {
val navHostFragment = DynamicNavHostFragment()
fragmentManager.beginTransaction()
- .add(android.R.id.content, navHostFragment)
- .commitNow()
+ .add(android.R.id.content, navHostFragment)
+ .commitNow()
val graph = navHostFragment.createGraph(startDestination = DESTINATION_ID) {
fragment(DESTINATION_ID, FRAGMENT_CLASS_NAME) {
moduleName = MODULE_NAME
@@ -75,8 +75,8 @@
@Test fun no_moduleName() {
val navHostFragment = DynamicNavHostFragment()
fragmentManager.beginTransaction()
- .add(android.R.id.content, navHostFragment)
- .commitNow()
+ .add(android.R.id.content, navHostFragment)
+ .commitNow()
val graph = navHostFragment.createGraph(startDestination = DESTINATION_ID) {
fragment(DESTINATION_ID, FRAGMENT_CLASS_NAME) {}
}
diff --git a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilder.kt b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilder.kt
index e02af61..62d5768 100644
--- a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilder.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilder.kt
@@ -51,11 +51,13 @@
@IdRes id: Int,
fragmentClassName: String,
builder: DynamicFragmentNavigatorDestinationBuilder.() -> Unit
-) = destination(DynamicFragmentNavigatorDestinationBuilder(
+) = destination(
+ DynamicFragmentNavigatorDestinationBuilder(
provider[DynamicFragmentNavigator::class],
id,
fragmentClassName
-).apply(builder))
+ ).apply(builder)
+)
/**
* DSL for constructing a new [DynamicFragmentNavigator.Destination]
@@ -71,7 +73,7 @@
override fun build() =
(super.build() as DynamicFragmentNavigator.Destination).also { destination ->
- destination.className = fragmentClassName
- destination.moduleName = moduleName
- }
+ destination.className = fragmentClassName
+ destination.moduleName = moduleName
+ }
}
diff --git a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragment.kt b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragment.kt
index c28b373..03e6b91 100644
--- a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragment.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragment.kt
@@ -40,8 +40,10 @@
navigatorProvider += DynamicActivityNavigator(requireActivity(), installManager)
- val fragmentNavigator = DynamicFragmentNavigator(requireContext(),
- childFragmentManager, id, installManager)
+ val fragmentNavigator = DynamicFragmentNavigator(
+ requireContext(),
+ childFragmentManager, id, installManager
+ )
navigatorProvider += fragmentNavigator
val graphNavigator = DynamicGraphNavigator(
@@ -56,8 +58,10 @@
}
navigatorProvider += graphNavigator
- navigatorProvider += DynamicIncludeGraphNavigator(requireContext(),
- navigatorProvider, navController.navInflater, installManager)
+ navigatorProvider += DynamicIncludeGraphNavigator(
+ requireContext(),
+ navigatorProvider, navController.navInflater, installManager
+ )
}
/**
diff --git a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
index aee34b8..a1cf5fa 100644
--- a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
@@ -128,35 +128,37 @@
onInstalled()
navigate()
}
- SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> try {
- val splitInstallManager = monitor.splitInstallManager
- if (splitInstallManager == null) {
- onFailed(SplitInstallErrorCode.INTERNAL_ERROR)
- return
- }
- splitInstallManager.startConfirmationDialogForResult(
- sessionState,
- IntentSenderForResultStarter { intent,
- requestCode,
- fillInIntent,
- flagsMask,
- flagsValues,
- extraFlags,
- options ->
- startIntentSenderForResult(
- intent,
+ SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION ->
+ try {
+ val splitInstallManager = monitor.splitInstallManager
+ if (splitInstallManager == null) {
+ onFailed(SplitInstallErrorCode.INTERNAL_ERROR)
+ return
+ }
+ splitInstallManager.startConfirmationDialogForResult(
+ sessionState,
+ IntentSenderForResultStarter { intent,
requestCode,
fillInIntent,
flagsMask,
flagsValues,
extraFlags,
- options
- )
- }, INSTALL_REQUEST_CODE
- )
- } catch (e: IntentSender.SendIntentException) {
- onFailed(SplitInstallErrorCode.INTERNAL_ERROR)
- }
+ options ->
+ startIntentSenderForResult(
+ intent,
+ requestCode,
+ fillInIntent,
+ flagsMask,
+ flagsValues,
+ extraFlags,
+ options
+ )
+ },
+ INSTALL_REQUEST_CODE
+ )
+ } catch (e: IntentSender.SendIntentException) {
+ onFailed(SplitInstallErrorCode.INTERNAL_ERROR)
+ }
SplitInstallSessionStatus.CANCELED -> onCancelled()
SplitInstallSessionStatus.FAILED -> onFailed(sessionState.errorCode())
SplitInstallSessionStatus.UNKNOWN ->
diff --git a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorTest.kt b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorTest.kt
index f252355..25b16d62 100644
--- a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorTest.kt
@@ -29,7 +29,9 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.mock
+/* ktlint-disable no-unused-imports */ // https://github.com/pinterest/ktlint/issues/937
import org.mockito.Mockito.`when` as mockWhen
+/* ktlint-enable unused-imports */
@SmallTest
@RunWith(AndroidJUnit4::class)
diff --git a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigatorTest.kt b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigatorTest.kt
index 680c3b0..ab2697a 100644
--- a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigatorTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigatorTest.kt
@@ -63,7 +63,8 @@
)
with(navController) {
navigatorProvider.addNavigator(
- DynamicGraphNavigator(navigatorProvider, installManager))
+ DynamicGraphNavigator(navigatorProvider, installManager)
+ )
navigatorProvider.addNavigator(navigator)
navigatorProvider.addNavigator(NoOpNavigator())
setGraph(navGraphId)
@@ -83,13 +84,19 @@
moduleName = FEATURE_NAME
}
assertThat(
- dynamicNavGraph.getPackageOrDefault(context, "\${applicationId}.something" +
- ".$FEATURE_NAME")
+ dynamicNavGraph.getPackageOrDefault(
+ context,
+ "\${applicationId}.something" +
+ ".$FEATURE_NAME"
+ )
).isEqualTo("$packageName.something.$FEATURE_NAME")
assertThat(
- dynamicNavGraph.getPackageOrDefault(context, "something.\${applicationId}" +
- ".$FEATURE_NAME")
+ dynamicNavGraph.getPackageOrDefault(
+ context,
+ "something.\${applicationId}" +
+ ".$FEATURE_NAME"
+ )
).isEqualTo("something.$packageName.$FEATURE_NAME")
assertThat(
@@ -103,10 +110,12 @@
setupInternal(R.navigation.nav_invalid_id)
fail("Inflating nav_invalid_id should fail with an IllegalStateException")
} catch (e: IllegalStateException) {
- assertThat(e).hasMessageThat().containsMatch(".*" +
+ assertThat(e).hasMessageThat().containsMatch(
+ ".*" +
"androidx.navigation.dynamicfeatures.test:id/featureFragmentNested" +
".*" +
- "androidx.navigation.dynamicfeatures.test:id/dynamic_graph")
+ "androidx.navigation.dynamicfeatures.test:id/dynamic_graph"
+ )
}
}
diff --git a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeNavGraphBuilderTest.kt b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeNavGraphBuilderTest.kt
index 024c82a..dfa5c5b 100644
--- a/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeNavGraphBuilderTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/androidTest/java/androidx/navigation/dynamicfeatures/DynamicIncludeNavGraphBuilderTest.kt
@@ -37,8 +37,10 @@
private val context: Context = ApplicationProvider.getApplicationContext()
private val navController = NavController(context).apply {
- navigatorProvider += DynamicIncludeGraphNavigator(context, navigatorProvider, navInflater,
- AndroidTestDynamicInstallManager(context))
+ navigatorProvider += DynamicIncludeGraphNavigator(
+ context, navigatorProvider, navInflater,
+ AndroidTestDynamicInstallManager(context)
+ )
navigatorProvider += NoOpNavigator()
}
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorDestinationBuilder.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorDestinationBuilder.kt
index dbbaf2a..f0f04b5 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorDestinationBuilder.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorDestinationBuilder.kt
@@ -70,7 +70,8 @@
targetPackage!!
} else {
activityNavigator.packageName
- }, it
+ },
+ it
)
)
}
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigator.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigator.kt
index 866fa55..b72b9d3 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigator.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigator.kt
@@ -117,8 +117,10 @@
}
val progressDestination = dynamicNavGraph.findNode(progressDestinationId)
- ?: throw IllegalStateException("The progress destination id must be set and " +
- "accessible to the module of this navigator.")
+ ?: throw IllegalStateException(
+ "The progress destination id must be set and " +
+ "accessible to the module of this navigator."
+ )
val navigator = navigatorProvider.getNavigator<Navigator<NavDestination>>(
progressDestination.navigatorName
)
@@ -134,11 +136,11 @@
val progressDestinationSupplier = defaultProgressDestinationSupplier
checkNotNull(progressDestinationSupplier) {
"You must set a default progress destination " +
- "using DynamicNavGraphNavigator.installDefaultProgressDestination or " +
- "pass in an DynamicInstallMonitor in the DynamicExtras.\n" +
- "Alternatively, when using NavHostFragment make sure to swap it with " +
- "DynamicNavHostFragment. This will take care of setting the default " +
- "progress destination for you."
+ "using DynamicNavGraphNavigator.installDefaultProgressDestination or " +
+ "pass in an DynamicInstallMonitor in the DynamicExtras.\n" +
+ "Alternatively, when using NavHostFragment make sure to swap it with " +
+ "DynamicNavHostFragment. This will take care of setting the default " +
+ "progress destination for you."
}
val progressDestination = progressDestinationSupplier.invoke()
dynamicNavGraph.addDestination(progressDestination)
@@ -187,10 +189,10 @@
return destination.parent as? DynamicNavGraph
?: throw IllegalStateException(
"Dynamic destinations must be part of a DynamicNavGraph.\n" +
- "You can use DynamicNavHostFragment, which will take care of " +
- "setting up the NavController for Dynamic destinations.\n" +
- "If you're not using Fragments, you must set up the " +
- "NavigatorProvider manually."
+ "You can use DynamicNavHostFragment, which will take care of " +
+ "setting up the NavController for Dynamic destinations.\n" +
+ "If you're not using Fragments, you must set up the " +
+ "NavigatorProvider manually."
)
}
}
@@ -211,7 +213,8 @@
context.withStyledAttributes(attrs, R.styleable.DynamicGraphNavigator) {
moduleName = getString(R.styleable.DynamicGraphNavigator_moduleName)
progressDestination = getResourceId(
- R.styleable.DynamicGraphNavigator_progressDestination, 0)
+ R.styleable.DynamicGraphNavigator_progressDestination, 0
+ )
if (progressDestination == 0) {
navGraphNavigator.destinationsWithoutDefaultProgressDestination
.add(this@DynamicNavGraph)
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigator.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigator.kt
index 980068f..e2a6826 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigator.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicIncludeGraphNavigator.kt
@@ -90,22 +90,24 @@
private fun replaceWithIncludedNav(destination: DynamicIncludeNavGraph): NavGraph {
val graphId = context.resources.getIdentifier(
destination.graphResourceName, "navigation",
- destination.graphPackage)
+ destination.graphPackage
+ )
if (graphId == 0) {
throw Resources.NotFoundException(
- "${destination.graphPackage}:navigation/${destination.graphResourceName}")
+ "${destination.graphPackage}:navigation/${destination.graphResourceName}"
+ )
}
val includedNav = navInflater.inflate(graphId)
check(!(includedNav.id != 0 && includedNav.id != destination.id)) {
"The included <navigation>'s id ${includedNav.displayName} is different from " +
- "the destination id ${destination.displayName}. Either remove the " +
- "<navigation> id or make them match."
+ "the destination id ${destination.displayName}. Either remove the " +
+ "<navigation> id or make them match."
}
includedNav.id = destination.id
val outerNav = destination.parent
?: throw IllegalStateException(
"The include-dynamic destination with id ${destination.displayName} " +
- "does not have a parent. Make sure it is attached to a NavGraph."
+ "does not have a parent. Make sure it is attached to a NavGraph."
)
outerNav.addDestination(includedNav)
// Avoid calling replaceWithIncludedNav() on the same destination more than once
@@ -180,8 +182,8 @@
if (it != null) {
require(it.isNotEmpty()) {
"`graphPackage` cannot be empty for <include-dynamic>. You can " +
- "omit the `graphPackage` attribute entirely to use the " +
- "default of ${context.packageName}.$moduleName."
+ "omit the `graphPackage` attribute entirely to use the " +
+ "default of ${context.packageName}.$moduleName."
}
}
getPackageOrDefault(context, it)
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicIncludeNavGraphBuilder.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicIncludeNavGraphBuilder.kt
index d64718c..aea2813 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicIncludeNavGraphBuilder.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicIncludeNavGraphBuilder.kt
@@ -54,12 +54,14 @@
moduleName: String,
graphResourceName: String,
builder: DynamicIncludeNavGraphBuilder.() -> Unit
-) = destination(DynamicIncludeNavGraphBuilder(
- provider[DynamicIncludeGraphNavigator::class],
- id,
- moduleName,
- graphResourceName
-).apply(builder))
+) = destination(
+ DynamicIncludeNavGraphBuilder(
+ provider[DynamicIncludeGraphNavigator::class],
+ id,
+ moduleName,
+ graphResourceName
+ ).apply(builder)
+)
/**
* DSL for constructing a new [DynamicIncludeGraphNavigator.DynamicIncludeNavGraph]
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicInstallManager.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicInstallManager.kt
index afee9f4..42c9bcd 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicInstallManager.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicInstallManager.kt
@@ -52,8 +52,8 @@
// Best effort leak prevention, will only work for active observers
check(!status.hasActiveObservers()) {
"This DynamicInstallMonitor will not " +
- "emit any more status updates. You should remove all " +
- "Observers after null has been emitted."
+ "emit any more status updates. You should remove all " +
+ "Observers after null has been emitted."
}
}
}
@@ -83,7 +83,8 @@
navigator.navigateToProgressDestination(dynamicNavGraph, progressArgs)
} else {
throw IllegalStateException(
- "You must use a DynamicNavGraph to perform a module installation.")
+ "You must use a DynamicNavGraph to perform a module installation."
+ )
}
}
}
@@ -105,7 +106,7 @@
check(!installMonitor.isUsed) {
// We don't want an installMonitor in an undefined state or used by another install
"You must pass in a fresh DynamicInstallMonitor " +
- "in DynamicExtras every time you call navigate()."
+ "in DynamicExtras every time you call navigate()."
}
val status = installMonitor.status as MutableLiveData<SplitInstallSessionState>
@@ -142,8 +143,10 @@
}
}
.addOnFailureListener { exception ->
- Log.i("DynamicInstallManager",
- "Error requesting install of $module: ${exception.message}")
+ Log.i(
+ "DynamicInstallManager",
+ "Error requesting install of $module: ${exception.message}"
+ )
installMonitor.exception = exception
status.value = SplitInstallSessionState.create(
/* sessionId */ 0,
diff --git a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigatorTest.kt b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigatorTest.kt
index bd170db..281684c 100644
--- a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigatorTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigatorTest.kt
@@ -32,7 +32,8 @@
class DynamicGraphNavigatorTest {
private val navigator =
- DynamicGraphNavigator(mock(NavigatorProvider::class.java),
+ DynamicGraphNavigator(
+ mock(NavigatorProvider::class.java),
TestDynamicInstallManager()
)
diff --git a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicInstallManagerTest.kt b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicInstallManagerTest.kt
index 4661dfa..9f407c5 100644
--- a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicInstallManagerTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicInstallManagerTest.kt
@@ -24,7 +24,9 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+/* ktlint-disable no-unused-imports */ // https://github.com/pinterest/ktlint/issues/937
import org.mockito.Mockito.`when` as mockWhen
+/* ktlint-enable unused-imports */
import org.mockito.Mockito.mock
import org.mockito.Mockito.spy
@@ -46,7 +48,7 @@
@Test
fun testNeedsInstall_NoInstallNeeded() {
- mockWhen(splitInstallManager.installedModules).thenReturn(setOf("module"))
+ mockWhen(splitInstallManager.installedModules).thenReturn(setOf("module"))
assertFalse(manager.needsInstall("module"))
}
}
diff --git a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicNavGraphTest.kt b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicNavGraphTest.kt
index 49c09c3..4fc7aae 100644
--- a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicNavGraphTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicNavGraphTest.kt
@@ -43,7 +43,8 @@
fun setup() {
provider = NavigatorProvider()
noOpNavigator = NoOpNavigator()
- navigator = DynamicGraphNavigator(provider,
+ navigator = DynamicGraphNavigator(
+ provider,
TestDynamicInstallManager()
)
provider.addNavigator(noOpNavigator)
@@ -57,9 +58,11 @@
@Test
fun testGetOrThrow_CorrectParent() {
- setupProgressDestination(noOpNavigator.createDestination().apply {
- id = progressId
- })
+ setupProgressDestination(
+ noOpNavigator.createDestination().apply {
+ id = progressId
+ }
+ )
val progressDestination = navigator.navigateToProgressDestination(dynamicNavGraph, null)
assertNotNull(progressDestination)
progressDestination?.let {
@@ -76,9 +79,11 @@
@Test
fun testNavigateToProgressDestination_withProviderAndDestination() {
- setupProgressDestination(noOpNavigator.createDestination().apply {
- id = progressId
- })
+ setupProgressDestination(
+ noOpNavigator.createDestination().apply {
+ id = progressId
+ }
+ )
val destination = navigator.navigateToProgressDestination(dynamicNavGraph, null)
assertTrue(destination?.parent is DynamicNavGraph)
}
diff --git a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilderTest.kt b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilderTest.kt
index 121ad32..fed4875 100644
--- a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilderTest.kt
+++ b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilderTest.kt
@@ -40,8 +40,8 @@
@Test fun fragment() {
val navHostFragment = NavHostFragment()
fragmentManager.beginTransaction()
- .add(android.R.id.content, navHostFragment)
- .commitNow()
+ .add(android.R.id.content, navHostFragment)
+ .commitNow()
val graph = navHostFragment.createGraph(startDestination = DESTINATION_ID) {
dialog<BuilderTestDialogFragment>(DESTINATION_ID)
}
@@ -57,8 +57,8 @@
@Test fun fragmentWithBody() {
val navHostFragment = NavHostFragment()
fragmentManager.beginTransaction()
- .add(android.R.id.content, navHostFragment)
- .commitNow()
+ .add(android.R.id.content, navHostFragment)
+ .commitNow()
val graph = navHostFragment.createGraph(startDestination = DESTINATION_ID) {
dialog<BuilderTestDialogFragment>(DESTINATION_ID) {
label = LABEL
diff --git a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilderTest.kt b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilderTest.kt
index b05d626..028a90c 100644
--- a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilderTest.kt
+++ b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilderTest.kt
@@ -41,36 +41,46 @@
@Test fun fragment() {
val navHostFragment = NavHostFragment()
fragmentManager.beginTransaction()
- .add(android.R.id.content, navHostFragment)
- .commitNow()
+ .add(android.R.id.content, navHostFragment)
+ .commitNow()
val graph = navHostFragment.createGraph(startDestination = DESTINATION_ID) {
fragment<BuilderTestFragment>(DESTINATION_ID)
}
- assertTrue("Destination should be added to the graph",
- DESTINATION_ID in graph)
- assertEquals("Fragment class should be set to BuilderTestFragment",
- BuilderTestFragment::class.java.name,
- (graph[DESTINATION_ID] as FragmentNavigator.Destination).className)
+ assertTrue(
+ "Destination should be added to the graph",
+ DESTINATION_ID in graph
+ )
+ assertEquals(
+ "Fragment class should be set to BuilderTestFragment",
+ BuilderTestFragment::class.java.name,
+ (graph[DESTINATION_ID] as FragmentNavigator.Destination).className
+ )
}
@UiThreadTest
@Test fun fragmentWithBody() {
val navHostFragment = NavHostFragment()
fragmentManager.beginTransaction()
- .add(android.R.id.content, navHostFragment)
- .commitNow()
+ .add(android.R.id.content, navHostFragment)
+ .commitNow()
val graph = navHostFragment.createGraph(startDestination = DESTINATION_ID) {
fragment<BuilderTestFragment>(DESTINATION_ID) {
label = LABEL
}
}
- assertTrue("Destination should be added to the graph",
- DESTINATION_ID in graph)
- assertEquals("Fragment class should be set to BuilderTestFragment",
- BuilderTestFragment::class.java.name,
- (graph[DESTINATION_ID] as FragmentNavigator.Destination).className)
- assertEquals("Fragment should have label set",
- LABEL, graph[DESTINATION_ID].label)
+ assertTrue(
+ "Destination should be added to the graph",
+ DESTINATION_ID in graph
+ )
+ assertEquals(
+ "Fragment class should be set to BuilderTestFragment",
+ BuilderTestFragment::class.java.name,
+ (graph[DESTINATION_ID] as FragmentNavigator.Destination).className
+ )
+ assertEquals(
+ "Fragment should have label set",
+ LABEL, graph[DESTINATION_ID].label
+ )
}
}
diff --git a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentTest.kt b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentTest.kt
index 4c7e1d7..4f93a8a 100644
--- a/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentTest.kt
+++ b/navigation/navigation-fragment-ktx/src/androidTest/java/androidx/navigation/fragment/FragmentTest.kt
@@ -41,23 +41,27 @@
@Test fun findNavController() {
val navHostFragment = NavHostFragment.create(R.navigation.test_graph)
fragmentManager.beginTransaction()
- .add(android.R.id.content, navHostFragment)
- .commitNow()
+ .add(android.R.id.content, navHostFragment)
+ .commitNow()
val foundNavController = contentFragment.findNavController()
- assertTrue("Fragment should have NavController set",
- foundNavController == navHostFragment.navController)
+ assertTrue(
+ "Fragment should have NavController set",
+ foundNavController == navHostFragment.navController
+ )
}
@UiThreadTest
@Test fun findNavControllerNull() {
fragmentManager.beginTransaction()
- .add(android.R.id.content, TestFragment())
- .commitNow()
+ .add(android.R.id.content, TestFragment())
+ .commitNow()
try {
contentFragment.findNavController()
- fail("findNavController should throw IllegalStateException if a NavController " +
- "was not set")
+ fail(
+ "findNavController should throw IllegalStateException if a NavController " +
+ "was not set"
+ )
} catch (e: IllegalStateException) {
// Expected
}
@@ -72,7 +76,7 @@
// TODO Create a real API to get the current Fragment b/119800853
val testFragment = navHostFragment.childFragmentManager.primaryNavigationFragment
- as TestFragment
+ as TestFragment
assertThat(testFragment.args)
.isNotNull()
assertThat(testFragment.args.bundle["test"])
diff --git a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/NavGraphViewModelLazy.kt b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/NavGraphViewModelLazy.kt
index 51c7a2a..ca8c723b 100644
--- a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/NavGraphViewModelLazy.kt
+++ b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/NavGraphViewModelLazy.kt
@@ -58,7 +58,10 @@
val storeProducer: () -> ViewModelStore = {
backStackEntry.viewModelStore
}
- return createViewModelLazy(VM::class, storeProducer, {
- factoryProducer?.invoke() ?: backStackEntry.defaultViewModelProviderFactory
- })
+ return createViewModelLazy(
+ VM::class, storeProducer,
+ {
+ factoryProducer?.invoke() ?: backStackEntry.defaultViewModelProviderFactory
+ }
+ )
}
\ No newline at end of file
diff --git a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilder.kt b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilder.kt
index 6f090bc..402cdf5 100644
--- a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilder.kt
+++ b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/DialogFragmentNavigatorDestinationBuilder.kt
@@ -35,11 +35,13 @@
inline fun <reified F : DialogFragment> NavGraphBuilder.dialog(
@IdRes id: Int,
builder: DialogFragmentNavigatorDestinationBuilder.() -> Unit
-) = destination(DialogFragmentNavigatorDestinationBuilder(
+) = destination(
+ DialogFragmentNavigatorDestinationBuilder(
provider[DialogFragmentNavigator::class],
id,
F::class
-).apply(builder))
+ ).apply(builder)
+)
/**
* DSL for constructing a new [DialogFragmentNavigator.Destination]
@@ -52,7 +54,7 @@
) : NavDestinationBuilder<DialogFragmentNavigator.Destination>(navigator, id) {
override fun build(): DialogFragmentNavigator.Destination =
- super.build().also { destination ->
- destination.className = fragmentClass.java.name
- }
+ super.build().also { destination ->
+ destination.className = fragmentClass.java.name
+ }
}
diff --git a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/Fragment.kt b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/Fragment.kt
index 56a51a7..4646f75 100644
--- a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/Fragment.kt
+++ b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/Fragment.kt
@@ -26,4 +26,4 @@
* will result in an [IllegalStateException]
*/
fun Fragment.findNavController(): NavController =
- NavHostFragment.findNavController(this)
+ NavHostFragment.findNavController(this)
diff --git a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilder.kt b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilder.kt
index f59a3ae..5bb7aaf 100644
--- a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilder.kt
+++ b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/FragmentNavigatorDestinationBuilder.kt
@@ -35,11 +35,13 @@
inline fun <reified F : Fragment> NavGraphBuilder.fragment(
@IdRes id: Int,
builder: FragmentNavigatorDestinationBuilder.() -> Unit
-) = destination(FragmentNavigatorDestinationBuilder(
+) = destination(
+ FragmentNavigatorDestinationBuilder(
provider[FragmentNavigator::class],
id,
F::class
-).apply(builder))
+ ).apply(builder)
+)
/**
* DSL for constructing a new [FragmentNavigator.Destination]
@@ -52,7 +54,7 @@
) : NavDestinationBuilder<FragmentNavigator.Destination>(navigator, id) {
override fun build(): FragmentNavigator.Destination =
- super.build().also { destination ->
- destination.className = fragmentClass.java.name
- }
+ super.build().also { destination ->
+ destination.className = fragmentClass.java.name
+ }
}
diff --git a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/FragmentNavigatorExtras.kt b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/FragmentNavigatorExtras.kt
index dd7441e..2292eb0 100644
--- a/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/FragmentNavigatorExtras.kt
+++ b/navigation/navigation-fragment-ktx/src/main/java/androidx/navigation/fragment/FragmentNavigatorExtras.kt
@@ -26,8 +26,8 @@
*/
@Suppress("FunctionName")
fun FragmentNavigatorExtras(vararg sharedElements: Pair<View, String>) =
- FragmentNavigator.Extras.Builder().apply {
- sharedElements.forEach { (view, name) ->
- addSharedElement(view, name)
- }
- }.build()
+ FragmentNavigator.Extras.Builder().apply {
+ sharedElements.forEach { (view, name) ->
+ addSharedElement(view, name)
+ }
+ }.build()
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/BaseNavControllerTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/BaseNavControllerTest.kt
index a373dd1..8f9ffe9 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/BaseNavControllerTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/BaseNavControllerTest.kt
@@ -96,8 +96,10 @@
}
private fun assertDeeplink(@IdRes destId: Int, expectedStackSize: Int) {
- val activity = launchDeepLink(R.navigation.nav_deep_link,
- destId, null)
+ val activity = launchDeepLink(
+ R.navigation.nav_deep_link,
+ destId, null
+ )
val navController = activity.navController
assertEquals(destId, navController.currentDestination?.id ?: 0)
@@ -107,7 +109,8 @@
// Test that the deep link Intent was passed through even though we don't pass in any args
val deepLinkIntent = navigator.current.second?.getParcelable<Intent>(
- NavController.KEY_DEEP_LINK_INTENT)
+ NavController.KEY_DEEP_LINK_INTENT
+ )
assertNotNull(deepLinkIntent)
assertEquals(TEST_DEEP_LINK_ACTION, deepLinkIntent?.action)
}
@@ -146,8 +149,10 @@
val args = Bundle().apply {
putString(TEST_ARG, TEST_ARG_VALUE)
}
- val activity = launchDeepLink(R.navigation.nav_deep_link,
- destId, args)
+ val activity = launchDeepLink(
+ R.navigation.nav_deep_link,
+ destId, args
+ )
val navController = activity.navController
assertEquals(destId, navController.currentDestination?.id ?: 0)
@@ -158,7 +163,8 @@
// Test that the deep link Intent was passed in alongside our args
val deepLinkIntent = navigator.current.second?.getParcelable<Intent>(
- NavController.KEY_DEEP_LINK_INTENT)
+ NavController.KEY_DEEP_LINK_INTENT
+ )
assertNotNull(deepLinkIntent)
assertEquals(TEST_DEEP_LINK_ACTION, deepLinkIntent?.action)
}
@@ -185,8 +191,10 @@
@Test
fun testNestedUriDeepLinkWithSlash() {
- assertUriDeepLink("nested_deep_link/$TEST_ARG_VALUE/", TEST_ARG_VALUE,
- R.id.nested_deep_link_test, 3)
+ assertUriDeepLink(
+ "nested_deep_link/$TEST_ARG_VALUE/", TEST_ARG_VALUE,
+ R.id.nested_deep_link_test, 3
+ )
}
@Test
@@ -214,9 +222,13 @@
) {
val deepLinkUri = Uri.parse("http://www.example.com/$fullPath")
val intent = Intent(Intent.ACTION_VIEW, deepLinkUri)
- .setComponent(ComponentName(instrumentation.context,
- activityClass))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ .setComponent(
+ ComponentName(
+ instrumentation.context,
+ activityClass
+ )
+ )
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
val activity = launchActivity(intent)
val navController = activity.navController
navController.setGraph(R.navigation.nav_deep_link)
@@ -228,7 +240,8 @@
// Test that the deep link Intent was passed in alongside our args
val deepLinkIntent = navigator.current.second?.getParcelable<Intent>(
- NavController.KEY_DEEP_LINK_INTENT)
+ NavController.KEY_DEEP_LINK_INTENT
+ )
assertNotNull(deepLinkIntent)
assertEquals(deepLinkUri, deepLinkIntent?.data)
}
@@ -248,10 +261,10 @@
args: Bundle?
): BaseNavigationActivity {
val intents = NavDeepLinkBuilder(instrumentation.targetContext)
- .setGraph(graphId)
- .setDestination(destId)
- .setArguments(args)
- .createTaskStackBuilder()
+ .setGraph(graphId)
+ .setDestination(destId)
+ .setArguments(args)
+ .createTaskStackBuilder()
val intent = intents.editIntentAt(0)!!
intent.action = TEST_DEEP_LINK_ACTION
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/DynamicNavControllerTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/DynamicNavControllerTest.kt
index 01c531c..e638d70 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/DynamicNavControllerTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/DynamicNavControllerTest.kt
@@ -26,7 +26,8 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class DynamicNavControllerTest : BaseNavControllerTest<DynamicNavigationActivity>(
- DynamicNavigationActivity::class.java)
+ DynamicNavigationActivity::class.java
+)
/**
* Test Navigation Activity that dynamically adds the [NavHostFragment].
@@ -42,9 +43,9 @@
if (savedInstanceState == null) {
val finalHost = NavHostFragment()
supportFragmentManager.beginTransaction()
- .replace(R.id.nav_host, finalHost)
- .setPrimaryNavigationFragment(finalHost)
- .commit()
+ .replace(R.id.nav_host, finalHost)
+ .setPrimaryNavigationFragment(finalHost)
+ .commit()
}
}
}
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/EmbeddedXmlTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/EmbeddedXmlTest.kt
index ab19723..ac1cb9b 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/EmbeddedXmlTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/EmbeddedXmlTest.kt
@@ -48,8 +48,10 @@
@Throws(Throwable::class)
fun testRecreate() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
- val intent = Intent(instrumentation.context,
- EmbeddedXmlActivity::class.java)
+ val intent = Intent(
+ instrumentation.context,
+ EmbeddedXmlActivity::class.java
+ )
val activity = activityRule.launchActivity(intent)
instrumentation.waitForIdleSync()
@@ -73,9 +75,9 @@
if (savedInstanceState == null) {
val embeddedFragment = EmbeddedXmlFragment()
supportFragmentManager.beginTransaction()
- .replace(R.id.container, embeddedFragment)
- .setPrimaryNavigationFragment(embeddedFragment)
- .commit()
+ .replace(R.id.container, embeddedFragment)
+ .setPrimaryNavigationFragment(embeddedFragment)
+ .commit()
}
}
}
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorExtrasTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorExtrasTest.kt
index bdc0079..115858e 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorExtrasTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorExtrasTest.kt
@@ -33,8 +33,8 @@
fun testAddSharedElement() {
val view = View(InstrumentationRegistry.getInstrumentation().targetContext)
val extras = FragmentNavigator.Extras.Builder()
- .addSharedElement(view, "test")
- .build()
+ .addSharedElement(view, "test")
+ .build()
val sharedElements = extras.sharedElements
assertEquals("Should be one shared element", 1, sharedElements.size)
val name = sharedElements[view]
@@ -46,10 +46,11 @@
fun testAddSharedElements() {
val map = mapOf(
View(InstrumentationRegistry.getInstrumentation().targetContext) to "test1",
- View(InstrumentationRegistry.getInstrumentation().targetContext) to "test2")
+ View(InstrumentationRegistry.getInstrumentation().targetContext) to "test2"
+ )
val extras = FragmentNavigator.Extras.Builder()
- .addSharedElements(map)
- .build()
+ .addSharedElements(map)
+ .build()
val sharedElements = extras.sharedElements
assertEquals("Should be ${map.size} shared elements", map.size, sharedElements.size)
map.forEach { (view, expected) ->
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
index 8a0e324..70421db 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
@@ -78,10 +78,14 @@
fragmentManager.executePendingTransactions()
val fragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Fragment should be added", fragment)
- assertEquals("Fragment should be the correct type",
- EmptyFragment::class.java, fragment!!::class.java)
- assertEquals("Fragment should be the primary navigation Fragment",
- fragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Fragment should be the correct type",
+ EmptyFragment::class.java, fragment!!::class.java
+ )
+ assertEquals(
+ "Fragment should be the primary navigation Fragment",
+ fragment, fragmentManager.primaryNavigationFragment
+ )
}
@UiThreadTest
@@ -123,10 +127,14 @@
fragmentManager.executePendingTransactions()
val fragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Fragment should be added", fragment)
- assertEquals("Fragment should be the correct type",
- EmptyFragment::class.java, fragment!!::class.java)
- assertEquals("Fragment should be the primary navigation Fragment",
- fragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Fragment should be the correct type",
+ EmptyFragment::class.java, fragment!!::class.java
+ )
+ assertEquals(
+ "Fragment should be the primary navigation Fragment",
+ fragment, fragmentManager.primaryNavigationFragment
+ )
// Now push a second fragment
destination.id = SECOND_FRAGMENT
@@ -135,10 +143,14 @@
fragmentManager.executePendingTransactions()
val replacementFragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Replacement Fragment should be added", replacementFragment)
- assertEquals("Replacement Fragment should be the correct type",
- EmptyFragment::class.java, replacementFragment!!::class.java)
- assertEquals("Replacement Fragment should be the primary navigation Fragment",
- replacementFragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Replacement Fragment should be the correct type",
+ EmptyFragment::class.java, replacementFragment!!::class.java
+ )
+ assertEquals(
+ "Replacement Fragment should be the primary navigation Fragment",
+ replacementFragment, fragmentManager.primaryNavigationFragment
+ )
}
@UiThreadTest
@@ -164,8 +176,12 @@
val success = fragmentNavigator.popBackStack()
assertTrue("FragmentNavigator should return true when popping the third fragment", success)
destination.id = THIRD_FRAGMENT
- assertThat(fragmentNavigator.navigate(destination, null,
- NavOptions.Builder().setPopUpTo(INITIAL_FRAGMENT, false).build(), null))
+ assertThat(
+ fragmentNavigator.navigate(
+ destination, null,
+ NavOptions.Builder().setPopUpTo(INITIAL_FRAGMENT, false).build(), null
+ )
+ )
.isEqualTo(destination)
fragmentManager.executePendingTransactions()
@@ -187,20 +203,32 @@
assertNotNull("Fragment should be added", fragment)
val lifecycle = fragment!!.lifecycle
- assertThat(fragmentNavigator.navigate(destination, null,
- NavOptions.Builder().setLaunchSingleTop(true).build(), null))
+ assertThat(
+ fragmentNavigator.navigate(
+ destination, null,
+ NavOptions.Builder().setLaunchSingleTop(true).build(), null
+ )
+ )
.isNull()
fragmentManager.executePendingTransactions()
val replacementFragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Replacement Fragment should be added", replacementFragment)
- assertTrue("Replacement Fragment should be the correct type",
- replacementFragment is EmptyFragment)
- assertEquals("Replacement Fragment should be the primary navigation Fragment",
- replacementFragment, fragmentManager.primaryNavigationFragment)
- assertNotEquals("Replacement should be a new instance", fragment,
- replacementFragment)
- assertEquals("Old instance should be destroyed", Lifecycle.State.DESTROYED,
- lifecycle.currentState)
+ assertTrue(
+ "Replacement Fragment should be the correct type",
+ replacementFragment is EmptyFragment
+ )
+ assertEquals(
+ "Replacement Fragment should be the primary navigation Fragment",
+ replacementFragment, fragmentManager.primaryNavigationFragment
+ )
+ assertNotEquals(
+ "Replacement should be a new instance", fragment,
+ replacementFragment
+ )
+ assertEquals(
+ "Old instance should be destroyed", Lifecycle.State.DESTROYED,
+ lifecycle.currentState
+ )
}
@UiThreadTest
@@ -230,8 +258,12 @@
.isNotNull()
val lifecycle = fragment!!.lifecycle
- assertThat(fragmentNavigator.navigate(destination, null,
- NavOptions.Builder().setLaunchSingleTop(true).build(), null))
+ assertThat(
+ fragmentNavigator.navigate(
+ destination, null,
+ NavOptions.Builder().setLaunchSingleTop(true).build(), null
+ )
+ )
.isNull()
fragmentManager.executePendingTransactions()
val replacementFragment = fragmentManager.findFragmentById(R.id.container)
@@ -265,8 +297,10 @@
@UiThreadTest
@Test
fun testPopInitial() {
- val fragmentNavigator = FragmentNavigator(emptyActivity,
- fragmentManager, R.id.container)
+ val fragmentNavigator = FragmentNavigator(
+ emptyActivity,
+ fragmentManager, R.id.container
+ )
val destination = fragmentNavigator.createDestination()
destination.id = INITIAL_FRAGMENT
destination.className = EmptyFragment::class.java.name
@@ -277,8 +311,10 @@
// Now pop the initial Fragment
val popped = fragmentNavigator.popBackStack()
- assertWithMessage("FragmentNavigator should return false when popping " +
- "the initial Fragment")
+ assertWithMessage(
+ "FragmentNavigator should return false when popping " +
+ "the initial Fragment"
+ )
.that(popped)
.isTrue()
}
@@ -305,17 +341,23 @@
fragmentManager.executePendingTransactions()
val replacementFragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Replacement Fragment should be added", replacementFragment)
- assertTrue("Replacement Fragment should be the correct type",
- replacementFragment is EmptyFragment)
- assertEquals("Replacement Fragment should be the primary navigation Fragment",
- replacementFragment, fragmentManager.primaryNavigationFragment)
+ assertTrue(
+ "Replacement Fragment should be the correct type",
+ replacementFragment is EmptyFragment
+ )
+ assertEquals(
+ "Replacement Fragment should be the primary navigation Fragment",
+ replacementFragment, fragmentManager.primaryNavigationFragment
+ )
// Now pop the Fragment
val popped = fragmentNavigator.popBackStack()
fragmentManager.executePendingTransactions()
assertTrue("FragmentNavigator should return true when popping a Fragment", popped)
- assertEquals("Fragment should be the primary navigation Fragment after pop",
- fragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Fragment should be the primary navigation Fragment after pop",
+ fragment, fragmentManager.primaryNavigationFragment
+ )
}
@UiThreadTest
@@ -367,8 +409,10 @@
assertWithMessage("FragmentNavigator should return true when popping a Fragment")
.that(popped)
.isTrue()
- assertWithMessage("Replacement Fragment should be the primary navigation Fragment " +
- "after pop")
+ assertWithMessage(
+ "Replacement Fragment should be the primary navigation Fragment " +
+ "after pop"
+ )
.that(fragmentManager.primaryNavigationFragment)
.isSameInstanceAs(replacementFragment)
}
@@ -395,10 +439,14 @@
fragmentManager.executePendingTransactions()
val replacementFragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Replacement Fragment should be added", replacementFragment)
- assertTrue("Replacement Fragment should be the correct type",
- replacementFragment is EmptyFragment)
- assertEquals("Replacement Fragment should be the primary navigation Fragment",
- replacementFragment, fragmentManager.primaryNavigationFragment)
+ assertTrue(
+ "Replacement Fragment should be the correct type",
+ replacementFragment is EmptyFragment
+ )
+ assertEquals(
+ "Replacement Fragment should be the primary navigation Fragment",
+ replacementFragment, fragmentManager.primaryNavigationFragment
+ )
// Add a Fragment to the replacementFragment's childFragmentManager back stack
replacementFragment?.childFragmentManager?.run {
@@ -413,8 +461,10 @@
val popped = fragmentNavigator.popBackStack()
fragmentManager.executePendingTransactions()
assertTrue("FragmentNavigator should return true when popping a Fragment", popped)
- assertEquals("Fragment should be the primary navigation Fragment after pop",
- fragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Fragment should be the primary navigation Fragment after pop",
+ fragment, fragmentManager.primaryNavigationFragment
+ )
}
@UiThreadTest
@@ -439,24 +489,32 @@
fragmentManager.executePendingTransactions()
val replacementFragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Replacement Fragment should be added", replacementFragment)
- assertTrue("Replacement Fragment should be the correct type",
- replacementFragment is EmptyFragment)
- assertEquals("Replacement Fragment should be the primary navigation Fragment",
- replacementFragment, fragmentManager.primaryNavigationFragment)
+ assertTrue(
+ "Replacement Fragment should be the correct type",
+ replacementFragment is EmptyFragment
+ )
+ assertEquals(
+ "Replacement Fragment should be the primary navigation Fragment",
+ replacementFragment, fragmentManager.primaryNavigationFragment
+ )
// Now pop the Fragment
fragmentNavigator.popBackStack()
fragmentManager.executePendingTransactions()
val fragment = fragmentManager.findFragmentById(R.id.container)
- assertEquals("Fragment should be the primary navigation Fragment after pop",
- fragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Fragment should be the primary navigation Fragment after pop",
+ fragment, fragmentManager.primaryNavigationFragment
+ )
}
@UiThreadTest
@Test
fun testDeepLinkPopWithSaveState() {
- var fragmentNavigator = FragmentNavigator(emptyActivity,
- fragmentManager, R.id.container)
+ var fragmentNavigator = FragmentNavigator(
+ emptyActivity,
+ fragmentManager, R.id.container
+ )
val destination = fragmentNavigator.createDestination()
destination.id = INITIAL_FRAGMENT
destination.className = EmptyFragment::class.java.name
@@ -475,30 +533,40 @@
fragmentManager.executePendingTransactions()
val replacementFragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Replacement Fragment should be added", replacementFragment)
- assertTrue("Replacement Fragment should be the correct type",
- replacementFragment is EmptyFragment)
- assertEquals("Replacement Fragment should be the primary navigation Fragment",
- replacementFragment, fragmentManager.primaryNavigationFragment)
+ assertTrue(
+ "Replacement Fragment should be the correct type",
+ replacementFragment is EmptyFragment
+ )
+ assertEquals(
+ "Replacement Fragment should be the primary navigation Fragment",
+ replacementFragment, fragmentManager.primaryNavigationFragment
+ )
// Create a new FragmentNavigator, replacing the previous one
val savedState = fragmentNavigator.onSaveState()
- fragmentNavigator = FragmentNavigator(emptyActivity,
- fragmentManager, R.id.container)
+ fragmentNavigator = FragmentNavigator(
+ emptyActivity,
+ fragmentManager, R.id.container
+ )
fragmentNavigator.onRestoreState(savedState)
// Now pop the Fragment
fragmentNavigator.popBackStack()
fragmentManager.executePendingTransactions()
val fragment = fragmentManager.findFragmentById(R.id.container)
- assertEquals("Fragment should be the primary navigation Fragment after pop",
- fragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Fragment should be the primary navigation Fragment after pop",
+ fragment, fragmentManager.primaryNavigationFragment
+ )
}
@UiThreadTest
@Test
fun testNavigateThenPopAfterSaveState() {
- var fragmentNavigator = FragmentNavigator(emptyActivity,
- fragmentManager, R.id.container)
+ var fragmentNavigator = FragmentNavigator(
+ emptyActivity,
+ fragmentManager, R.id.container
+ )
val destination = fragmentNavigator.createDestination()
destination.id = INITIAL_FRAGMENT
destination.className = EmptyFragment::class.java.name
@@ -508,10 +576,14 @@
fragmentManager.executePendingTransactions()
var fragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Fragment should be added", fragment)
- assertEquals("Fragment should be the correct type",
- EmptyFragment::class.java, fragment!!::class.java)
- assertEquals("Fragment should be the primary navigation Fragment",
- fragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Fragment should be the correct type",
+ EmptyFragment::class.java, fragment!!::class.java
+ )
+ assertEquals(
+ "Fragment should be the primary navigation Fragment",
+ fragment, fragmentManager.primaryNavigationFragment
+ )
// Now push a second fragment
destination.id = SECOND_FRAGMENT
@@ -520,15 +592,21 @@
fragmentManager.executePendingTransactions()
var replacementFragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Replacement Fragment should be added", replacementFragment)
- assertEquals("Replacement Fragment should be the correct type",
- EmptyFragment::class.java, replacementFragment!!::class.java)
- assertEquals("Replacement Fragment should be the primary navigation Fragment",
- replacementFragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Replacement Fragment should be the correct type",
+ EmptyFragment::class.java, replacementFragment!!::class.java
+ )
+ assertEquals(
+ "Replacement Fragment should be the primary navigation Fragment",
+ replacementFragment, fragmentManager.primaryNavigationFragment
+ )
// Create a new FragmentNavigator, replacing the previous one
val savedState = fragmentNavigator.onSaveState()
- fragmentNavigator = FragmentNavigator(emptyActivity,
- fragmentManager, R.id.container)
+ fragmentNavigator = FragmentNavigator(
+ emptyActivity,
+ fragmentManager, R.id.container
+ )
fragmentNavigator.onRestoreState(savedState)
// Now push a third fragment after the state save
@@ -538,24 +616,32 @@
fragmentManager.executePendingTransactions()
replacementFragment = fragmentManager.findFragmentById(R.id.container)
assertNotNull("Replacement Fragment should be added", replacementFragment)
- assertTrue("Replacement Fragment should be the correct type",
- replacementFragment is EmptyFragment)
- assertEquals("Replacement Fragment should be the primary navigation Fragment",
- replacementFragment, fragmentManager.primaryNavigationFragment)
+ assertTrue(
+ "Replacement Fragment should be the correct type",
+ replacementFragment is EmptyFragment
+ )
+ assertEquals(
+ "Replacement Fragment should be the primary navigation Fragment",
+ replacementFragment, fragmentManager.primaryNavigationFragment
+ )
// Now pop the Fragment
fragmentNavigator.popBackStack()
fragmentManager.executePendingTransactions()
fragment = fragmentManager.findFragmentById(R.id.container)
- assertEquals("Fragment should be the primary navigation Fragment after pop",
- fragment, fragmentManager.primaryNavigationFragment)
+ assertEquals(
+ "Fragment should be the primary navigation Fragment after pop",
+ fragment, fragmentManager.primaryNavigationFragment
+ )
}
@UiThreadTest
@Test
fun testMultipleNavigateFragmentTransactionsThenPop() {
- val fragmentNavigator = FragmentNavigator(emptyActivity,
- fragmentManager, R.id.container)
+ val fragmentNavigator = FragmentNavigator(
+ emptyActivity,
+ fragmentManager, R.id.container
+ )
val destination = fragmentNavigator.createDestination()
destination.className = EmptyFragment::class.java.name
val destination2 = fragmentNavigator.createDestination()
@@ -586,8 +672,10 @@
@UiThreadTest
@Test
fun testMultiplePopFragmentTransactionsThenPop() {
- val fragmentNavigator = FragmentNavigator(emptyActivity,
- fragmentManager, R.id.container)
+ val fragmentNavigator = FragmentNavigator(
+ emptyActivity,
+ fragmentManager, R.id.container
+ )
val destination = fragmentNavigator.createDestination()
destination.className = EmptyFragment::class.java.name
@@ -620,7 +708,7 @@
label = TEST_LABEL
}
val expected = "Destination(0x${INITIAL_FRAGMENT.toString(16)}) label=test_label " +
- "class=${EmptyFragment::class.java.name}"
+ "class=${EmptyFragment::class.java.name}"
assertThat(destination.toString()).isEqualTo(expected)
}
@@ -632,7 +720,7 @@
label = TEST_LABEL
}
val expected = "Destination(0x${INITIAL_FRAGMENT.toString(16)}) label=test_label " +
- "class=null"
+ "class=null"
assertThat(destination.toString()).isEqualTo(expected)
}
}
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/MultiNavHostFragmentTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/MultiNavHostFragmentTest.kt
index c895377..cbe0723 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/MultiNavHostFragmentTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/MultiNavHostFragmentTest.kt
@@ -69,7 +69,7 @@
val childFragment = withActivity {
supportFragmentManager.findFragmentById(R.id.nav_host_fragment)
?.childFragmentManager?.findFragmentById(R.id.nav_host_fragment) as
- BasicNavHostFragment
+ BasicNavHostFragment
}
navController.popBackStack()
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/OnBackPressedTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/OnBackPressedTest.kt
index e6f0cd9..fb3d8d2 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/OnBackPressedTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/OnBackPressedTest.kt
@@ -89,8 +89,10 @@
onBackPressed()
finishCountDownLatch
}
- assertWithMessage("onBackPressed() should finish the activity when not the " +
- "primary nav")
+ assertWithMessage(
+ "onBackPressed() should finish the activity when not the " +
+ "primary nav"
+ )
.that(countDownLatch.await(1, TimeUnit.SECONDS))
.isTrue()
}
@@ -101,7 +103,7 @@
with(ActivityScenario.launch(activityClass)) {
withActivity {
val navHostFragment = supportFragmentManager.primaryNavigationFragment
- as NavHostFragment
+ as NavHostFragment
val navHostFragmentManager = navHostFragment.childFragmentManager
val navController = navHostFragment.navController
navController.setGraph(R.navigation.nav_simple)
@@ -109,14 +111,16 @@
navHostFragmentManager.executePendingTransactions()
val currentFragment = navHostFragmentManager.primaryNavigationFragment
- as ChildBackStackFragment
+ as ChildBackStackFragment
assertWithMessage("Current Fragment should have a child Fragment by default")
.that(currentFragment.childFragment)
.isNotNull()
onBackPressed()
- assertWithMessage("onBackPressed() should not trigger NavController when there " +
- "is a child back stack")
+ assertWithMessage(
+ "onBackPressed() should not trigger NavController when there " +
+ "is a child back stack"
+ )
.that(navController.currentDestination?.id)
.isEqualTo(R.id.child_back_stack_fragment)
assertWithMessage("Child Fragment should be popped")
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/StartDestinationArgsTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/StartDestinationArgsTest.kt
index 20410c2..f9605a6 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/StartDestinationArgsTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/StartDestinationArgsTest.kt
@@ -64,12 +64,14 @@
val args = Bundle().apply {
putString(TEST_ARG, TEST_ARG_VALUE)
}
- val navHostFragment = NavHostFragment.create(R.navigation.nav_fragment_start_args,
- args)
+ val navHostFragment = NavHostFragment.create(
+ R.navigation.nav_fragment_start_args,
+ args
+ )
supportFragmentManager.beginTransaction()
- .replace(R.id.nav_host, navHostFragment)
- .setPrimaryNavigationFragment(navHostFragment)
- .commit()
+ .replace(R.id.nav_host, navHostFragment)
+ .setPrimaryNavigationFragment(navHostFragment)
+ .commit()
}
}
}
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/XmlNavControllerTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/XmlNavControllerTest.kt
index 803d6e4..375c7c0 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/XmlNavControllerTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/XmlNavControllerTest.kt
@@ -26,7 +26,8 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
class XmlNavControllerTest : BaseNavControllerTest<XmlNavigationActivity>(
- XmlNavigationActivity::class.java)
+ XmlNavigationActivity::class.java
+)
/**
* Test Navigation Activity that adds the [NavHostFragment] in XML.
diff --git a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityNavigatorDestinationBuilderTest.kt b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityNavigatorDestinationBuilderTest.kt
index 506771e..41b28c1 100644
--- a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityNavigatorDestinationBuilderTest.kt
+++ b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityNavigatorDestinationBuilderTest.kt
@@ -39,11 +39,15 @@
label = LABEL
}
}
- assertTrue("Destination should be added to the graph",
- DESTINATION_ID in graph)
- assertEquals("Destination should have label set",
- LABEL,
- graph[DESTINATION_ID].label)
+ assertTrue(
+ "Destination should be added to the graph",
+ DESTINATION_ID in graph
+ )
+ assertEquals(
+ "Destination should have label set",
+ LABEL,
+ graph[DESTINATION_ID].label
+ )
}
@Test
@@ -68,11 +72,15 @@
activityClass = TestActivity::class
}
}
- assertTrue("Destination should be added to the graph",
- DESTINATION_ID in graph)
- assertEquals("Destination should have ComponentName set",
- TestActivity::class.java.name,
- (graph[DESTINATION_ID] as ActivityNavigator.Destination).component?.className)
+ assertTrue(
+ "Destination should be added to the graph",
+ DESTINATION_ID in graph
+ )
+ assertEquals(
+ "Destination should have ComponentName set",
+ TestActivity::class.java.name,
+ (graph[DESTINATION_ID] as ActivityNavigator.Destination).component?.className
+ )
}
@Test
@@ -82,11 +90,15 @@
action = ACTION
}
}
- assertTrue("Destination should be added to the graph",
- DESTINATION_ID in graph)
- assertEquals("Destination should have action set",
- ACTION,
- (graph[DESTINATION_ID] as ActivityNavigator.Destination).action)
+ assertTrue(
+ "Destination should be added to the graph",
+ DESTINATION_ID in graph
+ )
+ assertEquals(
+ "Destination should have action set",
+ ACTION,
+ (graph[DESTINATION_ID] as ActivityNavigator.Destination).action
+ )
}
@Test
@@ -96,11 +108,15 @@
data = DATA
}
}
- assertTrue("Destination should be added to the graph",
- DESTINATION_ID in graph)
- assertEquals("Destination should have data set",
- DATA,
- (graph[DESTINATION_ID] as ActivityNavigator.Destination).data)
+ assertTrue(
+ "Destination should be added to the graph",
+ DESTINATION_ID in graph
+ )
+ assertEquals(
+ "Destination should have data set",
+ DATA,
+ (graph[DESTINATION_ID] as ActivityNavigator.Destination).data
+ )
}
@Test
@@ -110,11 +126,15 @@
dataPattern = DATA_PATTERN
}
}
- assertTrue("Destination should be added to the graph",
- DESTINATION_ID in graph)
- assertEquals("Destination should have data pattern set",
- DATA_PATTERN,
- (graph[DESTINATION_ID] as ActivityNavigator.Destination).dataPattern)
+ assertTrue(
+ "Destination should be added to the graph",
+ DESTINATION_ID in graph
+ )
+ assertEquals(
+ "Destination should have data pattern set",
+ DATA_PATTERN,
+ (graph[DESTINATION_ID] as ActivityNavigator.Destination).dataPattern
+ )
}
}
diff --git a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityTest.kt b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityTest.kt
index 337e5850..38986ca 100644
--- a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityTest.kt
+++ b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ActivityTest.kt
@@ -40,15 +40,19 @@
Navigation.setViewNavController(view, navController)
val foundNavController = activityRule.activity.findNavController(VIEW_ID)
- assertTrue("View should have NavController set",
- foundNavController == navController)
+ assertTrue(
+ "View should have NavController set",
+ foundNavController == navController
+ )
}
@Test fun findNavControllerNull() {
try {
activityRule.activity.findNavController(VIEW_ID)
- fail("findNavController should throw IllegalStateException if a NavController" +
- " was not set")
+ fail(
+ "findNavController should throw IllegalStateException if a NavController" +
+ " was not set"
+ )
} catch (e: IllegalStateException) {
// Expected
}
@@ -57,8 +61,10 @@
@Test fun findNavControllerInvalidViewId() {
try {
activityRule.activity.findNavController(INVALID_VIEW_ID)
- fail("findNavController should throw IllegalArgumentException if the view" +
- " does not exist")
+ fail(
+ "findNavController should throw IllegalArgumentException if the view" +
+ " does not exist"
+ )
} catch (e: IllegalArgumentException) {
// Expected
}
@@ -90,7 +96,8 @@
} catch (e: IllegalStateException) {
assertThat(e).hasMessageThat().isEqualTo(
"Activity ${activityRule.activity} has null extras in " +
- activityRule.activity.intent)
+ activityRule.activity.intent
+ )
}
}
}
@@ -114,8 +121,10 @@
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(View(this).apply {
- id = VIEW_ID
- })
+ setContentView(
+ View(this).apply {
+ id = VIEW_ID
+ }
+ )
}
}
diff --git a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/NavControllerTest.kt b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/NavControllerTest.kt
index 70cfa2e..7dfafcb 100644
--- a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/NavControllerTest.kt
+++ b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/NavControllerTest.kt
@@ -36,8 +36,10 @@
val graph = navController.createGraph(startDestination = DESTINATION_ID) {
test(DESTINATION_ID)
}
- assertTrue("Destination should be added to the graph",
- DESTINATION_ID in graph)
+ assertTrue(
+ "Destination should be added to the graph",
+ DESTINATION_ID in graph
+ )
}
}
diff --git a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/NavHostTest.kt b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/NavHostTest.kt
index d744cce..87c2045 100644
--- a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/NavHostTest.kt
+++ b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/NavHostTest.kt
@@ -28,8 +28,8 @@
class NavHostTest {
private val navController =
NavController(ApplicationProvider.getApplicationContext() as Context).apply {
- navigatorProvider += TestNavigator()
- }
+ navigatorProvider += TestNavigator()
+ }
private val navHost = NavHost { [email protected] }
@Test
@@ -37,8 +37,10 @@
val graph = navHost.createGraph(startDestination = DESTINATION_ID) {
test(DESTINATION_ID)
}
- assertTrue("Destination should be added to the graph",
- DESTINATION_ID in graph)
+ assertTrue(
+ "Destination should be added to the graph",
+ DESTINATION_ID in graph
+ )
}
}
diff --git a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ViewTest.kt b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ViewTest.kt
index 81ff144..e0ce2ed 100644
--- a/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ViewTest.kt
+++ b/navigation/navigation-runtime-ktx/src/androidTest/java/androidx/navigation/ViewTest.kt
@@ -36,16 +36,20 @@
Navigation.setViewNavController(view, navController)
val foundNavController = view.findNavController()
- assertTrue("View should have NavController set",
- foundNavController == navController)
+ assertTrue(
+ "View should have NavController set",
+ foundNavController == navController
+ )
}
@Test fun findNavControllerNull() {
val view = View(ApplicationProvider.getApplicationContext() as android.content.Context)
try {
view.findNavController()
- fail("findNavController should throw IllegalStateException if a NavController" +
- " was not set")
+ fail(
+ "findNavController should throw IllegalStateException if a NavController" +
+ " was not set"
+ )
} catch (e: IllegalStateException) {
// Expected
}
diff --git a/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/Activity.kt b/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/Activity.kt
index a646663..d365762 100644
--- a/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/Activity.kt
+++ b/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/Activity.kt
@@ -27,4 +27,4 @@
* will result in an [IllegalStateException]
*/
fun Activity.findNavController(@IdRes viewId: Int): NavController =
- Navigation.findNavController(this, viewId)
+ Navigation.findNavController(this, viewId)
diff --git a/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/ActivityNavigatorDestinationBuilder.kt b/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/ActivityNavigatorDestinationBuilder.kt
index dd3b631..63caeeb 100644
--- a/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/ActivityNavigatorDestinationBuilder.kt
+++ b/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/ActivityNavigatorDestinationBuilder.kt
@@ -30,10 +30,12 @@
inline fun NavGraphBuilder.activity(
@IdRes id: Int,
builder: ActivityNavigatorDestinationBuilder.() -> Unit
-) = destination(ActivityNavigatorDestinationBuilder(
+) = destination(
+ ActivityNavigatorDestinationBuilder(
provider[ActivityNavigator::class],
id
-).apply(builder))
+ ).apply(builder)
+)
/**
* DSL for constructing a new [ActivityNavigator.Destination]
@@ -56,13 +58,13 @@
var dataPattern: String? = null
override fun build(): ActivityNavigator.Destination =
- super.build().also { destination ->
- destination.targetPackage = targetPackage
- activityClass?.let { clazz ->
- destination.setComponentName(ComponentName(context, clazz.java))
- }
- destination.action = action
- destination.data = data
- destination.dataPattern = dataPattern
+ super.build().also { destination ->
+ destination.targetPackage = targetPackage
+ activityClass?.let { clazz ->
+ destination.setComponentName(ComponentName(context, clazz.java))
}
+ destination.action = action
+ destination.data = data
+ destination.dataPattern = dataPattern
+ }
}
diff --git a/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/ActivityNavigatorExtras.kt b/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/ActivityNavigatorExtras.kt
index 8d25d97..3956894 100644
--- a/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/ActivityNavigatorExtras.kt
+++ b/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/ActivityNavigatorExtras.kt
@@ -28,9 +28,9 @@
*/
@Suppress("FunctionName")
fun ActivityNavigatorExtras(activityOptions: ActivityOptionsCompat? = null, flags: Int = 0) =
- ActivityNavigator.Extras.Builder().apply {
- if (activityOptions != null) {
- setActivityOptions(activityOptions)
- }
- addFlags(flags)
- }.build()
+ ActivityNavigator.Extras.Builder().apply {
+ if (activityOptions != null) {
+ setActivityOptions(activityOptions)
+ }
+ addFlags(flags)
+ }.build()
diff --git a/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/View.kt b/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/View.kt
index 1356f69..c7cfe68 100644
--- a/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/View.kt
+++ b/navigation/navigation-runtime-ktx/src/main/java/androidx/navigation/View.kt
@@ -25,4 +25,4 @@
* [IllegalStateException]
*/
fun View.findNavController(): NavController =
- Navigation.findNavController(this)
+ Navigation.findNavController(this)
diff --git a/navigation/navigation-runtime-truth/src/androidTest/java/androidx/navigation/truth/NavControllerSubjectTest.kt b/navigation/navigation-runtime-truth/src/androidTest/java/androidx/navigation/truth/NavControllerSubjectTest.kt
index b52c7bc..d634a80 100644
--- a/navigation/navigation-runtime-truth/src/androidTest/java/androidx/navigation/truth/NavControllerSubjectTest.kt
+++ b/navigation/navigation-runtime-truth/src/androidTest/java/androidx/navigation/truth/NavControllerSubjectTest.kt
@@ -46,9 +46,11 @@
@Test
fun testIsCurrentDestinationFailure() {
- with(assertThrows {
- assertThat(navController).isCurrentDestination(R.id.second_test)
- }) {
+ with(
+ assertThrows {
+ assertThat(navController).isCurrentDestination(R.id.second_test)
+ }
+ ) {
factValue("expected id")
.isEqualTo("0x${R.id.second_test.toString(16)}")
factValue("but was")
@@ -65,9 +67,11 @@
@Test
fun testIsGraphFailure() {
- with(assertThrows {
- assertThat(navController).isGraph(R.id.second_test_graph)
- }) {
+ with(
+ assertThrows {
+ assertThat(navController).isGraph(R.id.second_test_graph)
+ }
+ ) {
factValue("expected id")
.isEqualTo("0x${R.id.second_test_graph.toString(16)}")
factValue("but was")
diff --git a/navigation/navigation-runtime-truth/src/main/java/androidx/navigation/truth/NavControllerSubject.kt b/navigation/navigation-runtime-truth/src/main/java/androidx/navigation/truth/NavControllerSubject.kt
index a57eede..bbbb6c0 100644
--- a/navigation/navigation-runtime-truth/src/main/java/androidx/navigation/truth/NavControllerSubject.kt
+++ b/navigation/navigation-runtime-truth/src/main/java/androidx/navigation/truth/NavControllerSubject.kt
@@ -69,7 +69,9 @@
companion object {
@SuppressLint("MemberVisibilityCanBePrivate")
val factory = Factory<NavControllerSubject, NavController> {
- metadata, actual -> NavControllerSubject(metadata, actual) }
+ metadata, actual ->
+ NavControllerSubject(metadata, actual)
+ }
@JvmStatic
fun assertThat(actual: NavController): NavControllerSubject {
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
index 7beeb5e..66ff509 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
@@ -98,8 +98,10 @@
val targetActivity = waitForActivity()
val intent = targetActivity.intent
assertNotNull(intent)
- assertEquals("Intent should not include FLAG_ACTIVITY_NEW_TASK",
- 0, intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK)
+ assertEquals(
+ "Intent should not include FLAG_ACTIVITY_NEW_TASK",
+ 0, intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK
+ )
}
@Test
@@ -116,8 +118,10 @@
val targetActivity = waitForActivity()
val intent = targetActivity.intent
assertNotNull(intent)
- assertEquals("Intent should include FLAG_ACTIVITY_NEW_TASK",
- Intent.FLAG_ACTIVITY_NEW_TASK, intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK)
+ assertEquals(
+ "Intent should include FLAG_ACTIVITY_NEW_TASK",
+ Intent.FLAG_ACTIVITY_NEW_TASK, intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK
+ )
}
@Test
@@ -126,15 +130,21 @@
id = TARGET_ID
setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
}
- activityNavigator.navigate(targetDestination, null, navOptions {
- launchSingleTop = true
- }, null)
+ activityNavigator.navigate(
+ targetDestination, null,
+ navOptions {
+ launchSingleTop = true
+ },
+ null
+ )
val targetActivity = waitForActivity()
val intent = targetActivity.intent
assertNotNull(intent)
- assertEquals("Intent should include FLAG_ACTIVITY_SINGLE_TOP",
- Intent.FLAG_ACTIVITY_SINGLE_TOP, intent.flags and Intent.FLAG_ACTIVITY_SINGLE_TOP)
+ assertEquals(
+ "Intent should include FLAG_ACTIVITY_SINGLE_TOP",
+ Intent.FLAG_ACTIVITY_SINGLE_TOP, intent.flags and Intent.FLAG_ACTIVITY_SINGLE_TOP
+ )
}
@Test
@@ -152,8 +162,10 @@
val targetActivity = waitForActivity()
val intent = targetActivity.intent
assertNotNull(intent)
- assertEquals("Intent should have its arguments in its extras",
- TARGET_ARGUMENT_VALUE, intent.getStringExtra(TARGET_ARGUMENT_NAME))
+ assertEquals(
+ "Intent should have its arguments in its extras",
+ TARGET_ARGUMENT_VALUE, intent.getStringExtra(TARGET_ARGUMENT_NAME)
+ )
}
@Test
@@ -168,8 +180,10 @@
val targetActivity = waitForActivity()
val intent = targetActivity.intent
assertNotNull(intent)
- assertEquals("Intent should have action set",
- TARGET_ACTION, intent.action)
+ assertEquals(
+ "Intent should have action set",
+ TARGET_ACTION, intent.action
+ )
}
@Test
@@ -184,8 +198,10 @@
val targetActivity = waitForActivity()
val intent = targetActivity.intent
assertNotNull(intent)
- assertEquals("Intent should have data set",
- TARGET_DATA, intent.data)
+ assertEquals(
+ "Intent should have data set",
+ TARGET_DATA, intent.data
+ )
}
@Test
@@ -203,11 +219,15 @@
val targetActivity = waitForActivity()
val intent = targetActivity.intent
assertNotNull(intent)
- assertEquals("Intent should have data set with argument filled in",
- TARGET_DATA_PATTERN.replace("{$TARGET_ARGUMENT_NAME}", TARGET_ARGUMENT_VALUE),
- intent.data?.toString())
- assertEquals("Intent should have its arguments in its extras",
- TARGET_ARGUMENT_VALUE, intent.getStringExtra(TARGET_ARGUMENT_NAME))
+ assertEquals(
+ "Intent should have data set with argument filled in",
+ TARGET_DATA_PATTERN.replace("{$TARGET_ARGUMENT_NAME}", TARGET_ARGUMENT_VALUE),
+ intent.data?.toString()
+ )
+ assertEquals(
+ "Intent should have its arguments in its extras",
+ TARGET_ARGUMENT_VALUE, intent.getStringExtra(TARGET_ARGUMENT_NAME)
+ )
}
@Test
@@ -225,12 +245,18 @@
val targetActivity = waitForActivity()
val intent = targetActivity.intent
assertNotNull(intent)
- assertEquals("Intent should have data set with argument filled in",
- TARGET_DATA_PATTERN.replace("{$TARGET_ARGUMENT_NAME}",
- TARGET_ARGUMENT_INT_VALUE.toString()),
- intent.data?.toString())
- assertEquals("Intent should have its arguments in its extras",
- TARGET_ARGUMENT_INT_VALUE, intent.getIntExtra(TARGET_ARGUMENT_NAME, -1))
+ assertEquals(
+ "Intent should have data set with argument filled in",
+ TARGET_DATA_PATTERN.replace(
+ "{$TARGET_ARGUMENT_NAME}",
+ TARGET_ARGUMENT_INT_VALUE.toString()
+ ),
+ intent.data?.toString()
+ )
+ assertEquals(
+ "Intent should have its arguments in its extras",
+ TARGET_ARGUMENT_INT_VALUE, intent.getIntExtra(TARGET_ARGUMENT_NAME, -1)
+ )
}
@Test
@@ -257,9 +283,10 @@
val view = mock(View::class.java)
val activityNavigator = ActivityNavigator(context)
val activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
- activityRule.activity,
- view,
- "test")
+ activityRule.activity,
+ view,
+ "test"
+ )
val flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
val extras = ActivityNavigator.Extras.Builder()
.setActivityOptions(activityOptions)
@@ -273,9 +300,12 @@
activityNavigator.navigate(targetDestination, null, null, extras)
// Just verify that the ActivityOptions got passed through, there's
// CTS tests to ensure that the ActivityOptions do the right thing
- verify(context).startActivity(argThat { intent ->
- intent.flags and flags != 0
- }, refEq(activityOptions.toBundle()))
+ verify(context).startActivity(
+ argThat { intent ->
+ intent.flags and flags != 0
+ },
+ refEq(activityOptions.toBundle())
+ )
}
@Test
@@ -286,7 +316,7 @@
setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
}
val expected = "Destination(0x${TARGET_ID.toString(16)}) label=$TARGET_LABEL " +
- "class=${TargetActivity::class.java.name}"
+ "class=${TargetActivity::class.java.name}"
assertThat(targetDestination.toString()).isEqualTo(expected)
}
@@ -298,7 +328,7 @@
action = TARGET_ACTION
}
val expected = "Destination(0x${TARGET_ID.toString(16)}) label=$TARGET_LABEL " +
- "action=$TARGET_ACTION"
+ "action=$TARGET_ACTION"
assertThat(targetDestination.toString()).isEqualTo(expected)
}
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/FloatingWindowTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/FloatingWindowTest.kt
index ccbf1c1..c324e80 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/FloatingWindowTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/FloatingWindowTest.kt
@@ -37,7 +37,8 @@
val navController = createNavController()
navController.setGraph(R.navigation.nav_floating)
val floatingNavigator = navController.navigatorProvider.getNavigator(
- FloatingTestNavigator::class.java)
+ FloatingTestNavigator::class.java
+ )
val navigator = navController.navigatorProvider.getNavigator(TestNavigator::class.java)
assertThat(navController.currentDestination?.id)
.isEqualTo(R.id.start_test)
@@ -61,7 +62,8 @@
val navController = createNavController()
navController.setGraph(R.navigation.nav_floating)
val floatingNavigator = navController.navigatorProvider.getNavigator(
- FloatingTestNavigator::class.java)
+ FloatingTestNavigator::class.java
+ )
assertThat(navController.currentDestination?.id)
.isEqualTo(R.id.start_test)
assertThat(floatingNavigator.backStack.size)
@@ -82,7 +84,8 @@
val navController = createNavController()
navController.setGraph(R.navigation.nav_floating)
val floatingNavigator = navController.navigatorProvider.getNavigator(
- FloatingTestNavigator::class.java)
+ FloatingTestNavigator::class.java
+ )
val navigator = navController.navigatorProvider.getNavigator(TestNavigator::class.java)
assertThat(navController.currentDestination?.id)
.isEqualTo(R.id.start_test)
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt
index 40ef402..eebd3a7 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt
@@ -268,8 +268,10 @@
assertWithMessage("The nested graph should be started when its children are started")
.that(nestedGraphBackStackEntry.lifecycle.currentState)
.isEqualTo(Lifecycle.State.STARTED)
- assertWithMessage("The nested start destination should be started when a " +
- "FloatingWindow is open")
+ assertWithMessage(
+ "The nested start destination should be started when a " +
+ "FloatingWindow is open"
+ )
.that(nestedBackStackEntry.lifecycle.currentState)
.isEqualTo(Lifecycle.State.STARTED)
val secondBackStackEntry = navController.getBackStackEntry(R.id.second_test)
@@ -323,49 +325,66 @@
nestedBackStackEntry.lifecycle.addObserver(nestedObserver)
val inOrder = inOrder(graphObserver, nestedGraphObserver, nestedObserver)
inOrder.verify(graphObserver).onStateChanged(
- graphBackStackEntry, Lifecycle.Event.ON_CREATE)
+ graphBackStackEntry, Lifecycle.Event.ON_CREATE
+ )
inOrder.verify(graphObserver).onStateChanged(
- graphBackStackEntry, Lifecycle.Event.ON_START)
+ graphBackStackEntry, Lifecycle.Event.ON_START
+ )
inOrder.verify(graphObserver).onStateChanged(
- graphBackStackEntry, Lifecycle.Event.ON_RESUME)
+ graphBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_CREATE)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_CREATE
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_START)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_START
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_RESUME)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_CREATE)
+ nestedBackStackEntry, Lifecycle.Event.ON_CREATE
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_START)
+ nestedBackStackEntry, Lifecycle.Event.ON_START
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_RESUME)
+ nestedBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
navController.navigate(R.id.second_test)
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_PAUSE)
+ nestedBackStackEntry, Lifecycle.Event.ON_PAUSE
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_STOP)
+ nestedBackStackEntry, Lifecycle.Event.ON_STOP
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_PAUSE)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_PAUSE
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_STOP)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_STOP
+ )
navController.popBackStack()
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_START)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_START
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_RESUME)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_START)
+ nestedBackStackEntry, Lifecycle.Event.ON_START
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_RESUME)
+ nestedBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
inOrder.verifyNoMoreInteractions()
}
@@ -401,41 +420,54 @@
nestedBackStackEntry.lifecycle.addObserver(nestedObserver)
val inOrder = inOrder(graphObserver, nestedGraphObserver, nestedObserver)
inOrder.verify(graphObserver).onStateChanged(
- graphBackStackEntry, Lifecycle.Event.ON_CREATE)
+ graphBackStackEntry, Lifecycle.Event.ON_CREATE
+ )
inOrder.verify(graphObserver).onStateChanged(
- graphBackStackEntry, Lifecycle.Event.ON_START)
+ graphBackStackEntry, Lifecycle.Event.ON_START
+ )
inOrder.verify(graphObserver).onStateChanged(
- graphBackStackEntry, Lifecycle.Event.ON_RESUME)
+ graphBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_CREATE)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_CREATE
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_START)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_START
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_RESUME)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_CREATE)
+ nestedBackStackEntry, Lifecycle.Event.ON_CREATE
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_START)
+ nestedBackStackEntry, Lifecycle.Event.ON_START
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_RESUME)
+ nestedBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
navController.navigate(R.id.second_test)
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_PAUSE)
+ nestedBackStackEntry, Lifecycle.Event.ON_PAUSE
+ )
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_PAUSE)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_PAUSE
+ )
navController.popBackStack()
inOrder.verify(nestedGraphObserver).onStateChanged(
- nestedGraphBackStackEntry, Lifecycle.Event.ON_RESUME)
+ nestedGraphBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
inOrder.verify(nestedObserver).onStateChanged(
- nestedBackStackEntry, Lifecycle.Event.ON_RESUME)
+ nestedBackStackEntry, Lifecycle.Event.ON_RESUME
+ )
inOrder.verifyNoMoreInteractions()
}
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt
index 2e45f6f3..33716e8 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt
@@ -107,7 +107,8 @@
val restoredOwner = navController.getViewModelStoreOwner(navGraph.id)
val restoredViewModel = ViewModelProvider(
- restoredOwner)[TestSavedStateViewModel::class.java]
+ restoredOwner
+ )[TestSavedStateViewModel::class.java]
val restoredState: String? = restoredViewModel.savedStateHandle.get("test")
assertThat(restoredState).isEqualTo("test")
}
@@ -151,7 +152,7 @@
navController.getViewModelStoreOwner(navGraphId)
fail(
"Attempting to get ViewModelStoreOwner for navGraph not on back stack should " +
- "throw IllegalArgumentException"
+ "throw IllegalArgumentException"
)
} catch (e: IllegalArgumentException) {
assertThat(e)
@@ -217,8 +218,10 @@
@UiThreadTest
@Test
fun testGetSavedStateHandle() {
- val entry = NavBackStackEntry(ApplicationProvider.getApplicationContext(),
- NavDestination(TestNavigator()), null, null, NavControllerViewModel())
+ val entry = NavBackStackEntry(
+ ApplicationProvider.getApplicationContext(),
+ NavDestination(TestNavigator()), null, null, NavControllerViewModel()
+ )
assertThat(entry.savedStateHandle).isNotNull()
}
@@ -226,20 +229,22 @@
@UiThreadTest
@Test
fun testGetSavedStateHandleNoViewModelSet() {
- val entry = NavBackStackEntry(ApplicationProvider.getApplicationContext(),
- NavDestination(TestNavigator()), null, null, null)
+ val entry = NavBackStackEntry(
+ ApplicationProvider.getApplicationContext(),
+ NavDestination(TestNavigator()), null, null, null
+ )
try {
entry.savedStateHandle
fail(
"Attempting to get SavedStateHandle for back stack entry without " +
- "navControllerViewModel set should throw IllegalStateException"
+ "navControllerViewModel set should throw IllegalStateException"
)
} catch (e: IllegalStateException) {
assertThat(e)
.hasMessageThat().contains(
"You must call setViewModelStore() on your NavHostController before " +
- "accessing the ViewModelStore of a navigation graph."
+ "accessing the ViewModelStore of a navigation graph."
)
}
}
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt
index 85529e3..efcee15 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt
@@ -73,9 +73,11 @@
fun testNavigateUp() {
val activity = activityRule.activity
navController.setGraph(R.navigation.nav_simple)
- navController.handleDeepLink(Intent().apply {
- data = Uri.parse("android-app://androidx.navigation.test/test")
- })
+ navController.handleDeepLink(
+ Intent().apply {
+ data = Uri.parse("android-app://androidx.navigation.test/test")
+ }
+ )
assertThat(navController.currentDestination?.id)
.isEqualTo(R.id.second_test)
assertThat(navigator.backStack.size)
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
index 309e049..6fe9305 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
@@ -173,7 +173,7 @@
}
val navGraph = navController.navigatorProvider.navigation(
- startDestination = R.id.start_test
+ startDestination = R.id.start_test
) {
test(R.id.start_test)
}
@@ -249,7 +249,8 @@
val navController = createNavController()
navController.setGraph(R.navigation.nav_simple)
val deepLinkRequest = NavDeepLinkRequest.Builder.fromUri(
- Uri.parse("android-app://androidx.navigation.test/invalid")).build()
+ Uri.parse("android-app://androidx.navigation.test/invalid")
+ ).build()
try {
navController.navigate(deepLinkRequest)
@@ -258,7 +259,7 @@
assertThat(e)
.hasMessageThat().contains(
"Navigation destination that matches request $deepLinkRequest cannot be " +
- "found in the navigation graph ${navController.graph}"
+ "found in the navigation graph ${navController.graph}"
)
}
}
@@ -375,9 +376,12 @@
val navigator = navController.navigatorProvider.getNavigator(TestNavigator::class.java)
val deepLink = Uri.parse("android-app://androidx.navigation.test/test")
- navController.navigate(deepLink, navOptions {
- popUpTo(R.id.nav_root) { inclusive = true }
- })
+ navController.navigate(
+ deepLink,
+ navOptions {
+ popUpTo(R.id.nav_root) { inclusive = true }
+ }
+ )
assertThat(navController.currentDestination?.id ?: 0).isEqualTo(R.id.second_test)
assertThat(navigator.backStack.size).isEqualTo(1)
}
@@ -788,8 +792,10 @@
val returnedArgs = navigateWithArgs(args)
// Test that default values can be overridden by programmatic values
- assertEquals(TEST_OVERRIDDEN_VALUE_ARG_VALUE,
- returnedArgs.getString(TEST_OVERRIDDEN_VALUE_ARG))
+ assertEquals(
+ TEST_OVERRIDDEN_VALUE_ARG_VALUE,
+ returnedArgs.getString(TEST_OVERRIDDEN_VALUE_ARG)
+ )
}
private fun navigateWithArgs(args: Bundle?): Bundle {
@@ -816,8 +822,8 @@
val success = navController.popBackStack()
assertWithMessage("NavController should return false when popping the root")
- .that(success)
- .isFalse()
+ .that(success)
+ .isFalse()
assertNull(navController.currentDestination)
assertEquals(0, navigator.backStack.size)
}
@@ -833,14 +839,16 @@
val success = navController.popBackStack()
assertWithMessage("NavController should return false when popping the root")
- .that(success)
- .isFalse()
+ .that(success)
+ .isFalse()
assertNull(navController.currentDestination)
assertEquals(0, navigator.backStack.size)
val popped = navController.popBackStack()
- assertWithMessage("popBackStack should return false when there's nothing on the " +
- "back stack")
+ assertWithMessage(
+ "popBackStack should return false when there's nothing on the " +
+ "back stack"
+ )
.that(popped)
.isFalse()
}
@@ -896,9 +904,12 @@
assertEquals(R.id.start_test, navController.currentDestination?.id ?: 0)
assertEquals(1, navigator.backStack.size)
- navController.navigate(R.id.second_test, null, navOptions {
- popUpTo(R.id.start_test) { inclusive = true }
- })
+ navController.navigate(
+ R.id.second_test, null,
+ navOptions {
+ popUpTo(R.id.start_test) { inclusive = true }
+ }
+ )
assertEquals(R.id.second_test, navController.currentDestination?.id ?: 0)
assertEquals(1, navigator.backStack.size)
}
@@ -912,9 +923,12 @@
assertEquals(R.id.start_test, navController.currentDestination?.id ?: 0)
assertEquals(1, navigator.backStack.size)
- navController.navigate(R.id.second_test, null, navOptions {
- popUpTo(R.id.nav_root) { inclusive = true }
- })
+ navController.navigate(
+ R.id.second_test, null,
+ navOptions {
+ popUpTo(R.id.nav_root) { inclusive = true }
+ }
+ )
assertEquals(R.id.second_test, navController.currentDestination?.id ?: 0)
assertEquals(1, navigator.backStack.size)
}
@@ -1019,9 +1033,12 @@
var destinationListenerExecuted = false
- navController.navigate(R.id.start_test, args, navOptions {
- launchSingleTop = true
- })
+ navController.navigate(
+ R.id.start_test, args,
+ navOptions {
+ launchSingleTop = true
+ }
+ )
navController.addOnDestinationChangedListener { _, destination, arguments ->
destinationListenerExecuted = true
@@ -1156,12 +1173,15 @@
// Test that programmatically constructed arguments are passed through
assertEquals(TEST_ARG_VALUE, returnedArgs.getString(TEST_ARG))
// Test that default values can be overridden by programmatic values
- assertEquals(TEST_OVERRIDDEN_VALUE_ARG_VALUE,
- returnedArgs.getString(TEST_OVERRIDDEN_VALUE_ARG))
+ assertEquals(
+ TEST_OVERRIDDEN_VALUE_ARG_VALUE,
+ returnedArgs.getString(TEST_OVERRIDDEN_VALUE_ARG)
+ )
// Test that default values can be overridden by action default values
assertEquals(
TEST_OVERRIDDEN_VALUE_ARG_VALUE,
- returnedArgs.getString(TEST_ACTION_OVERRIDDEN_VALUE_ARG))
+ returnedArgs.getString(TEST_ACTION_OVERRIDDEN_VALUE_ARG)
+ )
}
@UiThreadTest
@@ -1171,8 +1191,8 @@
navController.setGraph(R.navigation.nav_simple)
val taskStackBuilder = navController.createDeepLink()
- .setDestination(R.id.second_test)
- .createTaskStackBuilder()
+ .setDestination(R.id.second_test)
+ .createTaskStackBuilder()
assertNotNull(taskStackBuilder)
assertEquals(1, taskStackBuilder.intentCount)
}
@@ -1186,9 +1206,9 @@
val args = Bundle()
args.putString("test", "test")
val taskStackBuilder = navController.createDeepLink()
- .setDestination(R.id.second_test)
- .setArguments(args)
- .createTaskStackBuilder()
+ .setDestination(R.id.second_test)
+ .setArguments(args)
+ .createTaskStackBuilder()
val intent = taskStackBuilder.editIntentAt(0)
assertNotNull(intent)
@@ -1210,7 +1230,8 @@
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.start_test)),
- any())
+ any()
+ )
val taskStackBuilder = navController.createDeepLink()
.setDestination(R.id.second_test)
@@ -1226,11 +1247,13 @@
verify(onDestinationChangedListener, times(2)).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.start_test)),
- any())
+ any()
+ )
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.second_test)),
- any())
+ any()
+ )
verifyNoMoreInteractions(onDestinationChangedListener)
}
@@ -1246,7 +1269,8 @@
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(startDestination),
- any())
+ any()
+ )
val taskStackBuilder = navController.createDeepLink()
.setDestination(R.id.second_test)
@@ -1262,11 +1286,13 @@
verify(onDestinationChangedListener, times(2)).onDestinationChanged(
eq(navController),
eq(startDestination),
- any())
+ any()
+ )
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.second_test)),
- any())
+ any()
+ )
verifyNoMoreInteractions(onDestinationChangedListener)
}
@@ -1282,7 +1308,8 @@
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(startDestination),
- any())
+ any()
+ )
val childDestination = navController.findDestination(R.id.simple_child_second_test)
val taskStackBuilder = navController.createDeepLink()
@@ -1301,20 +1328,24 @@
verify(onDestinationChangedListener, times(2)).onDestinationChanged(
eq(navController),
eq(startDestination),
- any())
+ any()
+ )
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(childDestination),
- any())
+ any()
+ )
// Then to the second destination added via addDestination()
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.deep_link_child_start_test)),
- any())
+ any()
+ )
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.deep_link_child_second_test)),
- any())
+ any()
+ )
verifyNoMoreInteractions(onDestinationChangedListener)
}
@@ -1330,7 +1361,8 @@
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(startDestination),
- any())
+ any()
+ )
val childDestination = navController.findDestination(R.id.simple_child_second_test)
val globalBundle = Bundle().apply {
@@ -1362,30 +1394,34 @@
eq(startDestination),
argThat { args ->
args?.getString("global").equals("global") &&
- args?.getString("test").equals("first")
- })
+ args?.getString("test").equals("first")
+ }
+ )
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(childDestination),
argThat { args ->
args?.getString("global").equals("global") &&
- args?.getString("test").equals("first")
- })
+ args?.getString("test").equals("first")
+ }
+ )
// Then to the second destination added via addDestination()
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.deep_link_child_start_test)),
argThat { args ->
args?.getString("global").equals("overridden") &&
- args?.getString("test").equals("second")
- })
+ args?.getString("test").equals("second")
+ }
+ )
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.deep_link_child_second_test)),
argThat { args ->
args?.getString("global").equals("overridden") &&
- args?.getString("test").equals("second")
- })
+ args?.getString("test").equals("second")
+ }
+ )
verifyNoMoreInteractions(onDestinationChangedListener)
}
@@ -1400,7 +1436,8 @@
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.start_test)),
- any())
+ any()
+ )
val taskStackBuilder = navController.createDeepLink()
.setGraph(R.navigation.nav_nested_start_destination)
@@ -1427,7 +1464,8 @@
verify(onDestinationChangedListener).onDestinationChanged(
eq(navController),
eq(navController.findDestination(R.id.start_test)),
- any())
+ any()
+ )
val taskStackBuilder = navController.createDeepLink()
.setGraph(R.navigation.nav_nested_start_destination)
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerViewModelTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerViewModelTest.kt
index 92aac96..ca5ed11 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerViewModelTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerViewModelTest.kt
@@ -67,6 +67,7 @@
baseViewModelStore.clear()
assertThat(viewModel.getViewModelStore(navGraphId)).isNotSameInstanceAs(
- navGraphViewModelStore)
+ navGraphViewModelStore
+ )
}
}
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavDeepLinkBuilderTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavDeepLinkBuilderTest.kt
index 190604c..afdccd1 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavDeepLinkBuilderTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavDeepLinkBuilderTest.kt
@@ -167,7 +167,8 @@
args.putString("test", "test2")
val secondPendingIntent = deepLinkBuilder.createPendingIntent()
assertWithMessage(
- "PendingIntents with different destination arguments should be different")
+ "PendingIntents with different destination arguments should be different"
+ )
.that(firstPendingIntent)
.isNotEqualTo(secondPendingIntent)
}
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt
index a441aaa..8123559 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt
@@ -84,8 +84,10 @@
val graph = navInflater.inflate(R.navigation.nav_simple)
assertThat(graph).isNotNull()
- val expectedUri = Uri.parse("android-app://" +
- instrumentation.targetContext.packageName + "/test")
+ val expectedUri = Uri.parse(
+ "android-app://" +
+ instrumentation.targetContext.packageName + "/test"
+ )
val expectedDeepLinkRequest = NavDeepLinkRequest.Builder.fromUri(expectedUri).build()
val result = graph.matchDeepLink(expectedDeepLinkRequest)
assertThat(result)
@@ -119,8 +121,12 @@
assertThat(graph).isNotNull()
val expectedDeepLinkRequest = NavDeepLinkRequest.Builder
- .fromUri(Uri.parse("android-app://" +
- instrumentation.targetContext.packageName + "/test/param1/param2")).build()
+ .fromUri(
+ Uri.parse(
+ "android-app://" +
+ instrumentation.targetContext.packageName + "/test/param1/param2"
+ )
+ ).build()
val result = graph.matchDeepLink(expectedDeepLinkRequest)
assertThat(result)
.isNotNull()
@@ -171,9 +177,11 @@
.isEqualTo(NavType.BoolType to false)
assertThat(defaultArguments["test_boolean_with_argType"]?.run { type to defaultValue })
.isEqualTo(NavType.BoolType to true)
- assertThat(defaultArguments["test_boolean_with_argType_false"]?.run {
- type to defaultValue
- }).isEqualTo(NavType.BoolType to false)
+ assertThat(
+ defaultArguments["test_boolean_with_argType_false"]?.run {
+ type to defaultValue
+ }
+ ).isEqualTo(NavType.BoolType to false)
}
@Test
@@ -209,9 +217,11 @@
assertThat(defaultArguments["test_string_integer"]?.run { type to defaultValue })
.isEqualTo(NavType.StringType to "123")
- assertThat(defaultArguments["test_string_no_default"]?.run {
- type to isDefaultValuePresent
- }).isEqualTo(NavType.StringType to false)
+ assertThat(
+ defaultArguments["test_string_no_default"]?.run {
+ type to isDefaultValuePresent
+ }
+ ).isEqualTo(NavType.StringType to false)
}
@Test
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/FloatingTestNavigator.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/FloatingTestNavigator.kt
index 0de74a5..689f7c6 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/FloatingTestNavigator.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/FloatingTestNavigator.kt
@@ -33,7 +33,8 @@
return FloatingDestination(this)
}
- class FloatingDestination(navigator: TestNavigator) : Destination(navigator),
+ class FloatingDestination(navigator: TestNavigator) :
+ Destination(navigator),
FloatingWindow
}
@@ -48,10 +49,12 @@
inline fun NavGraphBuilder.dialog(
@IdRes id: Int,
builder: FloatingTestNavigatorDestinationBuilder.() -> Unit
-) = destination(FloatingTestNavigatorDestinationBuilder(
- provider[FloatingTestNavigator::class],
- id
-).apply(builder))
+) = destination(
+ FloatingTestNavigatorDestinationBuilder(
+ provider[FloatingTestNavigator::class],
+ id
+ ).apply(builder)
+)
/**
* DSL for constructing a new [TestNavigator.Destination] from a [FloatingTestNavigator].
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/Context.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/Context.kt
index 04c2673..2fe9aed 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/Context.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/Context.kt
@@ -27,8 +27,10 @@
fun createStubId() = ResReference("error", "id", "errorId${next()}")
fun createStubArg() = Argument("errorArg${next()}", StringType)
- fun createStubDestination() = Destination(createStubId(), null, "stub",
- emptyList(), emptyList())
+ fun createStubDestination() = Destination(
+ createStubId(), null, "stub",
+ emptyList(), emptyList()
+ )
fun createStubIncludedDestination() = IncludedDestination(createStubId())
private fun next() = nextId++
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavArgumentResolver.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavArgumentResolver.kt
index 4f804a5..f47b7f7 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavArgumentResolver.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavArgumentResolver.kt
@@ -43,16 +43,18 @@
}
private fun mergeArguments(args1: List<Argument>, args2: List<Argument>) =
- args2.fold(args1) { result, arg ->
- val duplicate = result.find { it.name == arg.name }
- if (duplicate != null) {
- if (duplicate.type != arg.type) {
- // TODO: needs context to print better exception
- throw IllegalArgumentException("Incompatible types ${duplicate.type} and " +
- "${arg.type} of argument ${arg.name}")
- }
- result
- } else {
- result + arg
+ args2.fold(args1) { result, arg ->
+ val duplicate = result.find { it.name == arg.name }
+ if (duplicate != null) {
+ if (duplicate.type != arg.type) {
+ // TODO: needs context to print better exception
+ throw IllegalArgumentException(
+ "Incompatible types ${duplicate.type} and " +
+ "${arg.type} of argument ${arg.name}"
+ )
}
+ result
+ } else {
+ result + arg
}
+ }
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavParser.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavParser.kt
index 30be3b6..a866ae8 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavParser.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavParser.kt
@@ -166,8 +166,10 @@
ReferenceType -> {
when (defaultValue) {
VALUE_NULL -> {
- context.logger.error(NavParserErrors.nullDefaultValueReference(name),
- xmlPosition)
+ context.logger.error(
+ NavParserErrors.nullDefaultValueReference(name),
+ xmlPosition
+ )
return context.createStubArg()
}
"0" -> IntValue("0")
@@ -189,8 +191,8 @@
NullValue
} else {
context.logger.error(
- NavParserErrors.defaultValueObjectType(typeString),
- xmlPosition
+ NavParserErrors.defaultValueObjectType(typeString),
+ xmlPosition
)
return context.createStubArg()
}
@@ -339,7 +341,7 @@
}
private fun parseFloatValue(value: String): FloatValue? =
- value.toFloatOrNull()?.let { FloatValue(value) }
+ value.toFloatOrNull()?.let { FloatValue(value) }
private fun parseBoolean(value: String): BooleanValue? {
if (value == VALUE_TRUE || value == VALUE_FALSE) {
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavParserErrors.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavParserErrors.kt
index a800a42..9db93e1 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavParserErrors.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavParserErrors.kt
@@ -27,7 +27,7 @@
"'$value' as reference. Reference must be in format @[+][package:]res_type/resource_name"
fun nullDefaultValueReference(name: String?) = "android:defaultValue is @null, but '$name' " +
- "is of type \"reference\". Use \"0\" to signify a empty reference id"
+ "is of type \"reference\". Use \"0\" to signify a empty reference id"
fun invalidDefaultValue(value: String, type: NavType) = "Failed to parse defaultValue " +
"'$value' as $type"
@@ -36,30 +36,30 @@
" @[+][package:]id/resource_name "
fun defaultValueObjectType(type: String?) = "'$type' " +
- "doesn't allow default values other than @null"
+ "doesn't allow default values other than @null"
fun defaultNullButNotNullable(name: String?) = "android:defaultValue is @null, but '$name' " +
- "is not nullable. Add app:nullable=\"true\" to the argument to make it nullable."
+ "is not nullable. Add app:nullable=\"true\" to the argument to make it nullable."
fun typeIsNotNullable(typeName: String?) = "'$typeName' is a simple type " +
- "and cannot be nullable. Remove app:nullable=\"true\" from the argument."
+ "and cannot be nullable. Remove app:nullable=\"true\" from the argument."
fun sameSanitizedNameArguments(sanitizedName: String, args: List<Argument>) =
- "Multiple same name arguments. The named arguments: " +
+ "Multiple same name arguments. The named arguments: " +
"[${args.joinToString(", ") { it.name }}] result in the generator using " +
- "the same name: '$sanitizedName'."
+ "the same name: '$sanitizedName'."
fun sameSanitizedNameActions(sanitizedName: String, actions: List<Action>) =
- "Multiple same name actions. The action ids: " +
- "[${actions.joinToString(", ") { it.id.name }}] result in the " +
- "generator using the same name: '$sanitizedName'."
+ "Multiple same name actions. The action ids: " +
+ "[${actions.joinToString(", ") { it.id.name }}] result in the " +
+ "generator using the same name: '$sanitizedName'."
fun deprecatedTypeAttrUsed(name: String) =
- "The 'type' attribute used by argument '$name' is deprecated. " +
- "Please change all instances of 'type' in navigation resources to 'argType'."
+ "The 'type' attribute used by argument '$name' is deprecated. " +
+ "Please change all instances of 'type' in navigation resources to 'argType'."
val MISSING_GRAPH_ATTR = "Missing 'graph' attribute in <include> tag."
fun invalidNavReference(value: String) = "Failed to parse '$value' as a navigation reference." +
- " Reference must be in format @[package:]navigation/resource_name"
+ " Reference must be in format @[package:]navigation/resource_name"
}
\ No newline at end of file
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavSafeArgsGenerator.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavSafeArgsGenerator.kt
index 2ca06db..d48b33a1 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavSafeArgsGenerator.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/NavSafeArgsGenerator.kt
@@ -74,7 +74,9 @@
writeCodeFiles(
destination = nestedDestination,
parentDirectionsFileList = newParentDirectionFile?.let {
- listOf(it) + parentDirectionsFileList } ?: parentDirectionsFileList)
+ listOf(it) + parentDirectionsFileList
+ } ?: parentDirectionsFileList
+ )
}
}
writeCodeFiles(resolvedDestination, emptyList())
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/Types.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/Types.kt
index 679deea..0da8969 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/Types.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/Types.kt
@@ -140,10 +140,10 @@
data class ObjectType(val canonicalName: String) : NavType {
override fun bundlePutMethod() =
- throw UnsupportedOperationException("Use addBundlePutStatement instead.")
+ throw UnsupportedOperationException("Use addBundlePutStatement instead.")
override fun bundleGetMethod() =
- throw UnsupportedOperationException("Use addBundleGetStatement instead.")
+ throw UnsupportedOperationException("Use addBundleGetStatement instead.")
override fun toString() = "parcelable or serializable"
override fun allowsNullable() = true
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/java/JavaNavWriter.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/java/JavaNavWriter.kt
index 80ed320..6142002 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/java/JavaNavWriter.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/java/JavaNavWriter.kt
@@ -98,7 +98,8 @@
val actionTypeName = ClassName.get(
className.packageName(),
className.simpleName(),
- actionType.name)
+ actionType.name
+ )
MethodSpec.methodBuilder(methodName)
.addAnnotation(annotations.NONNULL_CLASSNAME)
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
@@ -117,8 +118,8 @@
val parentTypeSpec = it.wrapped.typeSpec
parentTypeSpec.methodSpecs.filter { method ->
method.hasModifier(Modifier.STATIC) &&
- getters.none { it.name == method.name } && // de-dupe local actions
- parentGetters.none { it.name == method.name } // de-dupe parent actions
+ getters.none { it.name == method.name } && // de-dupe local actions
+ parentGetters.none { it.name == method.name } // de-dupe parent actions
}.forEach { actionMethod ->
val params = actionMethod.parameters.joinToString(", ") { param -> param.name }
val methodSpec = MethodSpec.methodBuilder(actionMethod.name)
@@ -126,8 +127,10 @@
.addModifiers(actionMethod.modifiers)
.addParameters(actionMethod.parameters)
.returns(actionMethod.returnType)
- .addStatement("return $T.$L($params)",
- ClassName.get(parentPackageName, parentTypeSpec.name), actionMethod.name)
+ .addStatement(
+ "return $T.$L($params)",
+ ClassName.get(parentPackageName, parentTypeSpec.name), actionMethod.name
+ )
.build()
parentGetters.add(methodSpec)
}
@@ -135,9 +138,11 @@
return TypeSpec.classBuilder(className)
.addModifiers(Modifier.PUBLIC)
- .addTypes(actionTypes
- .filter { (action, _) -> action.args.isNotEmpty() }
- .map { (_, actionType) -> actionType })
+ .addTypes(
+ actionTypes
+ .filter { (action, _) -> action.args.isNotEmpty() }
+ .map { (_, actionType) -> actionType }
+ )
.addMethod(constructor)
.addMethods(getters + parentGetters)
.build()
@@ -224,9 +229,11 @@
}
if (arg.defaultValue == null) {
nextControlFlow("else")
- addStatement("throw new $T($S)", IllegalArgumentException::class.java,
+ addStatement(
+ "throw new $T($S)", IllegalArgumentException::class.java,
"Required argument \"${arg.name}\" is missing and does " +
- "not have an android:defaultValue")
+ "not have an android:defaultValue"
+ )
} else {
nextControlFlow("else")
addStatement(
@@ -388,11 +395,11 @@
fun copyMapContents(to: String, from: String) = CodeBlock.builder()
.addStatement(
- "$N.$N.putAll($N.$N)",
- to,
- hashMapFieldSpec.name,
- from,
- hashMapFieldSpec.name
+ "$N.$N.putAll($N.$N)",
+ to,
+ hashMapFieldSpec.name,
+ from,
+ hashMapFieldSpec.name
).build()
fun getters() = args.map { arg ->
@@ -423,7 +430,8 @@
addAnnotation(Override::class.java)
addModifiers(Modifier.PUBLIC)
addParameter(TypeName.OBJECT, "object")
- addCode("""
+ addCode(
+ """
if (this == object) {
return true;
}
@@ -431,7 +439,8 @@
return false;
}
- """.trimIndent())
+ """.trimIndent()
+ )
addStatement("$T that = ($T) object", className, className)
args.forEach { (name, type, _, _, sanitizedName) ->
beginControlFlow(
@@ -506,19 +515,21 @@
) = MethodSpec.methodBuilder("toString").apply {
addAnnotation(Override::class.java)
addModifiers(Modifier.PUBLIC)
- addCode(CodeBlock.builder().apply {
- if (toStringHeaderBlock != null) {
- add("${BEGIN_STMT}return $L", toStringHeaderBlock)
- } else {
- add("${BEGIN_STMT}return $S", "${className.simpleName()}{")
- }
- args.forEachIndexed { index, (_, _, _, _, sanitizedName) ->
- val getterName = getterFromArgName(sanitizedName, "()")
- val prefix = if (index == 0) "" else ", "
- add("\n+ $S + $L", "$prefix$sanitizedName=", getterName)
- }
- add("\n+ $S;\n$END_STMT", "}")
- }.build())
+ addCode(
+ CodeBlock.builder().apply {
+ if (toStringHeaderBlock != null) {
+ add("${BEGIN_STMT}return $L", toStringHeaderBlock)
+ } else {
+ add("${BEGIN_STMT}return $S", "${className.simpleName()}{")
+ }
+ args.forEachIndexed { index, (_, _, _, _, sanitizedName) ->
+ val getterName = getterFromArgName(sanitizedName, "()")
+ val prefix = if (index == 0) "" else ", "
+ add("\n+ $S + $L", "$prefix$sanitizedName=", getterName)
+ }
+ add("\n+ $S;\n$END_STMT", "}")
+ }.build()
+ )
returns(ClassName.get(String::class.java))
}.build()
@@ -543,7 +554,8 @@
beginControlFlow("if ($N == null)", variableName).apply {
addStatement(
"throw new $T($S)", IllegalArgumentException::class.java,
- "Argument \"${arg.name}\" is marked as non-null but was passed a null value.")
+ "Argument \"${arg.name}\" is marked as non-null but was passed a null value."
+ )
}
endControlFlow()
}
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/java/JavaTypes.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/java/JavaTypes.kt
index b495c26..f4caff7 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/java/JavaTypes.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/java/JavaTypes.kt
@@ -92,7 +92,7 @@
is ObjectType -> builder.apply {
beginControlFlow(
"if ($T.class.isAssignableFrom($T.class) " +
- "|| $T.class.isAssignableFrom($T.class))",
+ "|| $T.class.isAssignableFrom($T.class))",
PARCELABLE_CLASSNAME, arg.type.typeName(),
SERIALIZABLE_CLASSNAME, arg.type.typeName()
).apply {
@@ -103,8 +103,8 @@
}.nextControlFlow("else").apply {
addStatement(
"throw new UnsupportedOperationException($T.class.getName() + " +
- "\" must implement Parcelable or Serializable " +
- "or must be an Enum.\")",
+ "\" must implement Parcelable or Serializable " +
+ "or must be an Enum.\")",
arg.type.typeName()
)
}.endControlFlow()
@@ -112,11 +112,14 @@
is ObjectArrayType -> builder.apply {
val arrayName = "__array"
val baseType = (arg.type.typeName() as ArrayTypeName).componentType
- addStatement("$T[] $N = $N.$N($S)",
- PARCELABLE_CLASSNAME, arrayName, bundle, bundleGetMethod(), arg.name)
+ addStatement(
+ "$T[] $N = $N.$N($S)",
+ PARCELABLE_CLASSNAME, arrayName, bundle, bundleGetMethod(), arg.name
+ )
beginControlFlow("if ($N != null)", arrayName).apply {
addStatement("$N = new $T[$N.length]", lValue, baseType, arrayName)
- addStatement("$T.arraycopy($N, 0, $N, 0, $N.length)",
+ addStatement(
+ "$T.arraycopy($N, 0, $N, 0, $N.length)",
SYSTEM_CLASSNAME, arrayName, lValue, arrayName
)
}
@@ -160,7 +163,7 @@
}.nextControlFlow("else").apply {
addStatement(
"throw new UnsupportedOperationException($T.class.getName() + " +
- "\" must implement Parcelable or Serializable or must be an Enum.\")",
+ "\" must implement Parcelable or Serializable or must be an Enum.\")",
arg.type.typeName()
)
}.endControlFlow()
@@ -208,13 +211,15 @@
BoolArrayType -> ArrayTypeName.of(TypeName.BOOLEAN)
ReferenceType -> TypeName.INT
ReferenceArrayType -> ArrayTypeName.of(TypeName.INT)
- is ObjectType -> canonicalName.toClassNameParts().let { (packageName, simpleName, innerNames) ->
- ClassName.get(packageName, simpleName, *innerNames)
- }
+ is ObjectType ->
+ canonicalName.toClassNameParts().let { (packageName, simpleName, innerNames) ->
+ ClassName.get(packageName, simpleName, *innerNames)
+ }
is ObjectArrayType -> ArrayTypeName.of(
canonicalName.toClassNameParts().let { (packageName, simpleName, innerNames) ->
ClassName.get(packageName, simpleName, *innerNames)
- })
+ }
+ )
else -> throw IllegalStateException("Unknown type: $this")
}
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/kotlin/KotlinNavWriter.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/kotlin/KotlinNavWriter.kt
index 74fc3b0a..09ba357 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/kotlin/KotlinNavWriter.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/kotlin/KotlinNavWriter.kt
@@ -63,7 +63,8 @@
returns(NAV_DIRECTION_CLASSNAME)
addParameters(parameters)
if (action.args.isEmpty()) {
- addStatement("return %T(%L)",
+ addStatement(
+ "return %T(%L)",
ACTION_ONLY_NAV_DIRECTION_CLASSNAME, action.id.accessor()
)
} else {
@@ -84,7 +85,7 @@
val parentCompanionTypeSpec = parentTypeSpec.typeSpecs.first { it.isCompanion }
parentCompanionTypeSpec.funSpecs.filter { function ->
actionsFunSpec.none { it.name == function.name } && // de-dupe local actions
- parentActionsFunSpec.none { it.name == function.name } // de-dupe parent actions
+ parentActionsFunSpec.none { it.name == function.name } // de-dupe parent actions
}.forEach { functionSpec ->
val params = functionSpec.parameters.joinToString(", ") { param -> param.name }
val methodSpec = FunSpec.builder(functionSpec.name)
@@ -105,9 +106,10 @@
.addModifiers(KModifier.PRIVATE)
.build()
)
- .addTypes(actionTypes
- .filter { (action, _) -> action.args.isNotEmpty() }
- .map { (_, type) -> type }
+ .addTypes(
+ actionTypes
+ .filter { (action, _) -> action.args.isNotEmpty() }
+ .map { (_, type) -> type }
)
.addType(
TypeSpec.companionObjectBuilder()
@@ -146,16 +148,18 @@
}.build()
val constructorFunSpec = FunSpec.constructorBuilder()
- .addParameters(action.args.map { arg ->
- ParameterSpec.builder(
- name = arg.sanitizedName,
- type = arg.type.typeName().copy(nullable = arg.isNullable)
- ).apply {
- arg.defaultValue?.let {
- defaultValue(it.write())
- }
- }.build()
- })
+ .addParameters(
+ action.args.map { arg ->
+ ParameterSpec.builder(
+ name = arg.sanitizedName,
+ type = arg.type.typeName().copy(nullable = arg.isNullable)
+ ).apply {
+ arg.defaultValue?.let {
+ defaultValue(it.write())
+ }
+ }.build()
+ }
+ )
.build()
return if (action.args.isEmpty()) {
@@ -164,12 +168,14 @@
TypeSpec.classBuilder(className)
.addModifiers(KModifier.DATA)
.primaryConstructor(constructorFunSpec)
- .addProperties(action.args.map { arg ->
- PropertySpec.builder(
- arg.sanitizedName,
- arg.type.typeName().copy(nullable = arg.isNullable)
- ).initializer(arg.sanitizedName).build()
- })
+ .addProperties(
+ action.args.map { arg ->
+ PropertySpec.builder(
+ arg.sanitizedName,
+ arg.type.typeName().copy(nullable = arg.isNullable)
+ ).initializer(arg.sanitizedName).build()
+ }
+ )
}.addSuperinterface(NAV_DIRECTION_CLASSNAME)
.addModifiers(KModifier.PRIVATE)
.addFunction(getActionIdFunSpec)
@@ -183,12 +189,14 @@
val className = ClassName(destName.packageName(), "${destName.simpleName()}Args")
val constructorFunSpec = FunSpec.constructorBuilder()
- .addParameters(destination.args.map { arg ->
- ParameterSpec.builder(
- name = arg.sanitizedName,
- type = arg.type.typeName().copy(nullable = arg.isNullable)
- ).apply { arg.defaultValue?.let { defaultValue(it.write()) } }.build()
- })
+ .addParameters(
+ destination.args.map { arg ->
+ ParameterSpec.builder(
+ name = arg.sanitizedName,
+ type = arg.type.typeName().copy(nullable = arg.isNullable)
+ ).apply { arg.defaultValue?.let { defaultValue(it.write()) } }.build()
+ }
+ )
.build()
val toBundleFunSpec = FunSpec.builder("toBundle").apply {
@@ -236,7 +244,7 @@
"throw·%T(%S)",
IllegalArgumentException::class.asTypeName(),
"Argument \"${arg.name}\" is marked as non-null but was passed a " +
- "null value."
+ "null value."
)
}
endControlFlow()
@@ -250,7 +258,7 @@
"throw·%T(%S)",
IllegalArgumentException::class.asTypeName(),
"Required argument \"${arg.name}\" is missing and does not have an " +
- "android:defaultValue"
+ "android:defaultValue"
)
}
endControlFlow()
@@ -263,12 +271,14 @@
.addSuperinterface(NAV_ARGS_CLASSNAME)
.addModifiers(KModifier.DATA)
.primaryConstructor(constructorFunSpec)
- .addProperties(destination.args.map { arg ->
- PropertySpec.builder(
- arg.sanitizedName,
- arg.type.typeName().copy(nullable = arg.isNullable)
- ).initializer(arg.sanitizedName).build()
- })
+ .addProperties(
+ destination.args.map { arg ->
+ PropertySpec.builder(
+ arg.sanitizedName,
+ arg.type.typeName().copy(nullable = arg.isNullable)
+ ).initializer(arg.sanitizedName).build()
+ }
+ )
.addFunction(toBundleFunSpec)
.addType(
TypeSpec.companionObjectBuilder()
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/kotlin/KotlinTypes.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/kotlin/KotlinTypes.kt
index 4a1782a..0a919b0 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/kotlin/KotlinTypes.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/kotlin/KotlinTypes.kt
@@ -75,7 +75,7 @@
is ObjectType -> builder.apply {
beginControlFlow(
"if (%T::class.java.isAssignableFrom(%T::class.java) " +
- "|| %T::class.java.isAssignableFrom(%T::class.java))",
+ "|| %T::class.java.isAssignableFrom(%T::class.java))",
PARCELABLE_CLASSNAME, arg.type.typeName(),
SERIALIZABLE_CLASSNAME, arg.type.typeName()
)
@@ -96,7 +96,8 @@
val baseType = (arg.type.typeName() as ParameterizedTypeName).typeArguments.first()
addStatement(
"%L = %L.%L(%S)?.map { it as %T }?.toTypedArray()",
- lValue, bundle, bundleGetMethod(), arg.name, baseType)
+ lValue, bundle, bundleGetMethod(), arg.name, baseType
+ )
}
else -> builder.addStatement(
"%L = %L.%L(%S)",
@@ -165,9 +166,10 @@
BoolArrayType -> BooleanArray::class.asTypeName()
ReferenceType -> INT
ReferenceArrayType -> IntArray::class.asTypeName()
- is ObjectType -> canonicalName.toClassNameParts().let { (packageName, simpleName, innerNames) ->
- ClassName(packageName, simpleName, *innerNames)
- }
+ is ObjectType ->
+ canonicalName.toClassNameParts().let { (packageName, simpleName, innerNames) ->
+ ClassName(packageName, simpleName, *innerNames)
+ }
is ObjectArrayType -> ARRAY.parameterizedBy(
canonicalName.toClassNameParts().let { (packageName, simpleName, innerNames) ->
ClassName(packageName, simpleName, *innerNames)
diff --git a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/models/Argument.kt b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/models/Argument.kt
index 9e3dcf1..5c5e129 100644
--- a/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/models/Argument.kt
+++ b/navigation/navigation-safe-args-generator/src/main/kotlin/androidx/navigation/safe/args/generator/models/Argument.kt
@@ -29,8 +29,10 @@
) {
init {
if (isNullable && !type.allowsNullable()) {
- throw IllegalArgumentException("Argument is nullable but type $type " +
- "cannot be nullable.")
+ throw IllegalArgumentException(
+ "Argument is nullable but type $type " +
+ "cannot be nullable."
+ )
}
if (!isNullable && defaultValue == NullValue) {
throw IllegalArgumentException("Argument has null value but is not nullable.")
@@ -38,7 +40,7 @@
}
val sanitizedName = name.split("[^a-zA-Z0-9]".toRegex())
- .map { it.trim() }.joinToCamelCaseAsVar()
+ .map { it.trim() }.joinToCamelCaseAsVar()
fun isOptional() = defaultValue != null
diff --git a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/InvalidXmlTest.kt b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/InvalidXmlTest.kt
index 45f5981..7fa16a4 100644
--- a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/InvalidXmlTest.kt
+++ b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/InvalidXmlTest.kt
@@ -43,29 +43,54 @@
@Parameterized.Parameters(name = "({0})")
fun data() = listOf(
ErrorMessage("unnamed_destination_with_action.xml", 25, 5, UNNAMED_DESTINATION),
- ErrorMessage("invalid_default_value_reference.xml", 23, 9,
- invalidDefaultValueReference("foo/")),
- ErrorMessage("null_default_value_reference.xml", 23, 9,
- nullDefaultValueReference("myarg1")),
- ErrorMessage("invalid_default_value_int.xml", 24, 9,
- invalidDefaultValue("101034f", IntType)),
+ ErrorMessage(
+ "invalid_default_value_reference.xml", 23, 9,
+ invalidDefaultValueReference("foo/")
+ ),
+ ErrorMessage(
+ "null_default_value_reference.xml", 23, 9,
+ nullDefaultValueReference("myarg1")
+ ),
+ ErrorMessage(
+ "invalid_default_value_int.xml", 24, 9,
+ invalidDefaultValue("101034f", IntType)
+ ),
ErrorMessage("invalid_id_action.xml", 22, 44, invalidId("@+fppid/finish")),
ErrorMessage("invalid_id_destination.xml", 17, 1, invalidId("@1234234+id/foo")),
ErrorMessage("action_no_id.xml", 22, 5, mandatoryAttrMissingError("action", "id")),
- ErrorMessage("same_name_args.xml", 23, 9, sameSanitizedNameArguments("myArg", listOf(
- Argument("my_arg", StringType), Argument("my.arg", StringType)))),
- ErrorMessage("same_name_actions.xml", 22, 5,
- sameSanitizedNameActions("NextAction", listOf(
- Action(ResReference("a.b", "id", "next_action"),
- ResReference("a.b", "id", "first_screen")),
- Action(ResReference("a.b", "id", "nextAction"),
- ResReference("a.b", "id", "first_screen"))))),
+ ErrorMessage(
+ "same_name_args.xml", 23, 9,
+ sameSanitizedNameArguments(
+ "myArg",
+ listOf(
+ Argument("my_arg", StringType), Argument("my.arg", StringType)
+ )
+ )
+ ),
+ ErrorMessage(
+ "same_name_actions.xml", 22, 5,
+ sameSanitizedNameActions(
+ "NextAction",
+ listOf(
+ Action(
+ ResReference("a.b", "id", "next_action"),
+ ResReference("a.b", "id", "first_screen")
+ ),
+ Action(
+ ResReference("a.b", "id", "nextAction"),
+ ResReference("a.b", "id", "first_screen")
+ )
+ )
+ )
+ ),
ErrorMessage("null_but_not_nullable.xml", 24, 13, defaultNullButNotNullable("myArg")),
ErrorMessage("type_is_not_nullable.xml", 24, 13, typeIsNotNullable("integer")),
ErrorMessage("invalid_deprecated_type.xml", 24, 9, deprecatedTypeAttrUsed("myarg1")),
ErrorMessage("invalid_include_tag.xml", 30, 5, NavParserErrors.MISSING_GRAPH_ATTR),
- ErrorMessage("invalid_include_graph_attr.xml", 30, 5,
- invalidNavReference("to_include_login_test"))
+ ErrorMessage(
+ "invalid_include_graph_attr.xml", 30, 5,
+ invalidNavReference("to_include_login_test")
+ )
)
}
diff --git a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/JavaNavWriterTest.kt b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/JavaNavWriterTest.kt
index 819ad33..bcd9829 100644
--- a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/JavaNavWriterTest.kt
+++ b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/JavaNavWriterTest.kt
@@ -62,21 +62,28 @@
}
private fun toJavaFileObject(spec: TypeSpec) =
- JavaFile.builder("a.b", spec).build().toJavaFileObject()
+ JavaFile.builder("a.b", spec).build().toJavaFileObject()
private fun assertCompilesWithoutError(javaFileObject: JavaFileObject) {
JavaSourcesSubject.assertThat(
- loadSourceFileObject("a.b.R", "a/b"),
- loadSourceFileObject("a.b.secondreallyreallyreallyreallyreallyreally" +
- "reallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
- "longpackage.R", "a/b/secondreallyreallyreallyreallyreallyreally" +
- "reallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
- "longpackage"),
- JavaFileObjects.forSourceString("androidx.annotation.NonNull",
- "package androidx.annotation; public @interface NonNull {}"),
- JavaFileObjects.forSourceString("androidx.annotation.Nullable",
- "package androidx.annotation; public @interface Nullable {}"),
- javaFileObject
+ loadSourceFileObject("a.b.R", "a/b"),
+ loadSourceFileObject(
+ "a.b.secondreallyreallyreallyreallyreallyreally" +
+ "reallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
+ "longpackage.R",
+ "a/b/secondreallyreallyreallyreallyreallyreally" +
+ "reallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
+ "longpackage"
+ ),
+ JavaFileObjects.forSourceString(
+ "androidx.annotation.NonNull",
+ "package androidx.annotation; public @interface NonNull {}"
+ ),
+ JavaFileObjects.forSourceString(
+ "androidx.annotation.Nullable",
+ "package androidx.annotation; public @interface Nullable {}"
+ ),
+ javaFileObject
).compilesWithoutError()
}
@@ -84,35 +91,47 @@
this.parsesAs(fullClassName, "expected/java_nav_writer_test")
private fun compileFiles(vararg javaFileObject: JavaFileObject) = javac()
- .compile(loadSourceFileObject("a.b.R", "a/b"),
- JavaFileObjects.forSourceString("androidx.annotation.NonNull",
- "package androidx.annotation; public @interface NonNull {}"),
- JavaFileObjects.forSourceString("androidx.annotation.Nullable",
- "package androidx.annotation; public @interface Nullable {}"),
- *javaFileObject)
+ .compile(
+ loadSourceFileObject("a.b.R", "a/b"),
+ JavaFileObjects.forSourceString(
+ "androidx.annotation.NonNull",
+ "package androidx.annotation; public @interface NonNull {}"
+ ),
+ JavaFileObjects.forSourceString(
+ "androidx.annotation.Nullable",
+ "package androidx.annotation; public @interface Nullable {}"
+ ),
+ *javaFileObject
+ )
@Test
fun testDirectionClassGeneration() {
- val actionSpec = generateDirectionsTypeSpec(Action(id("next"), id("destA"),
+ val actionSpec = generateDirectionsTypeSpec(
+ Action(
+ id("next"), id("destA"),
listOf(
- Argument("main", StringType),
- Argument("mainInt", IntType),
- Argument("optional", StringType, StringValue("bla")),
- Argument("optionalInt", IntType, IntValue("239")),
- Argument(
- "optionalParcelable",
- ObjectType("android.content.pm.ActivityInfo"),
- NullValue,
- true
- ),
- Argument(
- "parcelable",
- ObjectType("android.content.pm.ActivityInfo")
- ),
- Argument(
- "innerData",
- ObjectType("android.content.pm.ActivityInfo\$WindowLayout")
- ))), true)
+ Argument("main", StringType),
+ Argument("mainInt", IntType),
+ Argument("optional", StringType, StringValue("bla")),
+ Argument("optionalInt", IntType, IntValue("239")),
+ Argument(
+ "optionalParcelable",
+ ObjectType("android.content.pm.ActivityInfo"),
+ NullValue,
+ true
+ ),
+ Argument(
+ "parcelable",
+ ObjectType("android.content.pm.ActivityInfo")
+ ),
+ Argument(
+ "innerData",
+ ObjectType("android.content.pm.ActivityInfo\$WindowLayout")
+ )
+ )
+ ),
+ true
+ )
val actual = toJavaFileObject(actionSpec)
JavaSourcesSubject.assertThat(actual).parsesAs("a.b.Next")
// actions spec must be inner class to be compiled, because of static modifier on class
@@ -130,18 +149,26 @@
@Test
fun testDirectionsClassGeneration() {
- val nextAction = Action(id("next"), id("destA"),
- listOf(
- Argument("main", StringType),
- Argument("optional", StringType, StringValue("bla"))))
+ val nextAction = Action(
+ id("next"), id("destA"),
+ listOf(
+ Argument("main", StringType),
+ Argument("optional", StringType, StringValue("bla"))
+ )
+ )
- val prevAction = Action(id("previous"), id("destB"),
- listOf(
- Argument("arg1", StringType),
- Argument("arg2", StringType)))
+ val prevAction = Action(
+ id("previous"), id("destB"),
+ listOf(
+ Argument("arg1", StringType),
+ Argument("arg2", StringType)
+ )
+ )
- val dest = Destination(null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(),
- listOf(prevAction, nextAction))
+ val dest = Destination(
+ null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(),
+ listOf(prevAction, nextAction)
+ )
val actual = generateDirectionsCodeFile(dest, emptyList(), true).toJavaFileObject()
JavaSourcesSubject.assertThat(actual).parsesAs("a.b.MainFragmentDirections")
@@ -150,37 +177,60 @@
@Test
fun testDirectionsClassGeneration_longPackage() {
- val funAction = Action(ResReference("a.b.secondreallyreallyreallyreally" +
- "reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
- "longpackage", "id", "next"), id("destA"),
- listOf())
+ val funAction = Action(
+ ResReference(
+ "a.b.secondreallyreallyreallyreally" +
+ "reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
+ "longpackage",
+ "id", "next"
+ ),
+ id("destA"),
+ listOf()
+ )
- val dest = Destination(null, ClassName.get("a.b.reallyreallyreallyreally" +
- "reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
- "longpackage", "LongPackageFragment"), "fragment", listOf(),
- listOf(funAction))
+ val dest = Destination(
+ null,
+ ClassName.get(
+ "a.b.reallyreallyreallyreally" +
+ "reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
+ "longpackage",
+ "LongPackageFragment"
+ ),
+ "fragment", listOf(),
+ listOf(funAction)
+ )
val actual = generateDirectionsCodeFile(dest, emptyList(), true).toJavaFileObject()
- JavaSourcesSubject.assertThat(actual).parsesAs("a.b.reallyreallyreallyreallyreally" +
+ JavaSourcesSubject.assertThat(actual).parsesAs(
+ "a.b.reallyreallyreallyreallyreally" +
"reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
- "longpackage.LongPackageFragmentDirections")
+ "longpackage.LongPackageFragmentDirections"
+ )
assertCompilesWithoutError(actual)
}
@Test
fun testDirectionsClassGeneration_sanitizedNames() {
- val nextAction = Action(id("next_action"), id("destA"),
- listOf(
- Argument("main_arg", StringType),
- Argument("optional.arg", StringType, StringValue("bla"))))
+ val nextAction = Action(
+ id("next_action"), id("destA"),
+ listOf(
+ Argument("main_arg", StringType),
+ Argument("optional.arg", StringType, StringValue("bla"))
+ )
+ )
- val prevAction = Action(id("previous_action"), id("destB"),
- listOf(
- Argument("arg_1", StringType),
- Argument("arg.2", StringType)))
+ val prevAction = Action(
+ id("previous_action"), id("destB"),
+ listOf(
+ Argument("arg_1", StringType),
+ Argument("arg.2", StringType)
+ )
+ )
- val dest = Destination(null, ClassName.get("a.b", "SanitizedMainFragment"),
- "fragment", listOf(), listOf(prevAction, nextAction))
+ val dest = Destination(
+ null, ClassName.get("a.b", "SanitizedMainFragment"),
+ "fragment", listOf(), listOf(prevAction, nextAction)
+ )
val actual = generateDirectionsCodeFile(dest, emptyList(), true).toJavaFileObject()
JavaSourcesSubject.assertThat(actual).parsesAs("a.b.SanitizedMainFragmentDirections")
@@ -189,30 +239,45 @@
@Test
fun testArgumentsClassGeneration() {
- val dest = Destination(null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(
+ val dest = Destination(
+ null, ClassName.get("a.b", "MainFragment"), "fragment",
+ listOf(
Argument("main", StringType),
Argument("optional", IntType, IntValue("-1")),
- Argument("reference", ReferenceType, ReferenceValue(ResReference("a.b", "drawable",
- "background"))),
+ Argument(
+ "reference", ReferenceType,
+ ReferenceValue(
+ ResReference(
+ "a.b", "drawable",
+ "background"
+ )
+ )
+ ),
Argument("referenceZeroDefaultValue", ReferenceType, IntValue("0")),
Argument("floatArg", FloatType, FloatValue("1")),
Argument("floatArrayArg", FloatArrayType),
- Argument("objectArrayArg", ObjectArrayType(
- "android.content.pm.ActivityInfo")),
+ Argument(
+ "objectArrayArg",
+ ObjectArrayType(
+ "android.content.pm.ActivityInfo"
+ )
+ ),
Argument("boolArg", BoolType, BooleanValue("true")),
Argument(
- "optionalParcelable",
- ObjectType("android.content.pm.ActivityInfo"),
- NullValue,
- true
+ "optionalParcelable",
+ ObjectType("android.content.pm.ActivityInfo"),
+ NullValue,
+ true
),
Argument(
"enumArg",
ObjectType("java.nio.file.AccessMode"),
EnumValue(ObjectType("java.nio.file.AccessMode"), "READ"),
false
- )),
- listOf())
+ )
+ ),
+ listOf()
+ )
val actual = generateArgsCodeFile(dest, true).toJavaFileObject()
JavaSourcesSubject.assertThat(actual).parsesAs("a.b.MainFragmentArgs")
@@ -221,12 +286,16 @@
@Test
fun testArgumentsClassGeneration_sanitizedNames() {
- val dest = Destination(null, ClassName.get("a.b", "SanitizedMainFragment"),
- "fragment", listOf(
+ val dest = Destination(
+ null, ClassName.get("a.b", "SanitizedMainFragment"),
+ "fragment",
+ listOf(
Argument("name.with.dot", IntType),
Argument("name_with_underscore", IntType),
- Argument("name with spaces", IntType)),
- listOf())
+ Argument("name with spaces", IntType)
+ ),
+ listOf()
+ )
val actual = generateArgsCodeFile(dest, true).toJavaFileObject()
JavaSourcesSubject.assertThat(actual).parsesAs("a.b.SanitizedMainFragmentArgs")
@@ -235,10 +304,14 @@
@Test
fun testArgumentsClassGeneration_innerClassName() {
- val dest = Destination(null, ClassName.get("a.b", "MainFragment\$InnerFragment"),
- "fragment", listOf(
- Argument("mainArg", StringType)),
- listOf())
+ val dest = Destination(
+ null, ClassName.get("a.b", "MainFragment\$InnerFragment"),
+ "fragment",
+ listOf(
+ Argument("mainArg", StringType)
+ ),
+ listOf()
+ )
val actual = generateArgsCodeFile(dest, true).toJavaFileObject()
JavaSourcesSubject.assertThat(actual).parsesAs("a.b.MainFragment\$InnerFragmentArgs")
@@ -248,8 +321,10 @@
@Test
fun testGeneratedDirectionEqualsImpl() {
val nextAction = Action(id("next"), id("destA"), listOf(Argument("main", StringType)))
- val dest = Destination(null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(),
- listOf(nextAction))
+ val dest = Destination(
+ null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(),
+ listOf(nextAction)
+ )
val actual = generateDirectionsCodeFile(dest, emptyList(), true).toJavaFileObject()
@@ -271,16 +346,20 @@
@Test
fun testGeneratedDirectionHashCodeImpl() {
val nextAction = Action(id("next"), id("destA"), listOf(Argument("main", StringType)))
- val dest = Destination(null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(),
- listOf(nextAction))
+ val dest = Destination(
+ null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(),
+ listOf(nextAction)
+ )
val actual = generateDirectionsCodeFile(dest, emptyList(), true).toJavaFileObject()
val generatedFiles = compileFiles(actual).generatedFiles()
val loader = InMemoryGeneratedClassLoader(generatedFiles)
- fun createNextObj(mainArgValue: String): Any? = loader.loadClass("a.b" +
- ".MainFragmentDirections")
+ fun createNextObj(mainArgValue: String): Any? = loader.loadClass(
+ "a.b" +
+ ".MainFragmentDirections"
+ )
.getDeclaredMethod("next", String::class.java)
.invoke(null, mainArgValue)
diff --git a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/KotlinNavWriterTest.kt b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/KotlinNavWriterTest.kt
index 5dc291c..0bf214c 100644
--- a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/KotlinNavWriterTest.kt
+++ b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/KotlinNavWriterTest.kt
@@ -64,7 +64,8 @@
@Test
fun testDirectionClassGeneration() {
- val action = Action(id("next"), id("destA"),
+ val action = Action(
+ id("next"), id("destA"),
listOf(
Argument("main", StringType),
Argument("mainInt", IntType),
@@ -83,23 +84,29 @@
Argument(
"innerData",
ObjectType("android.content.pm.ActivityInfo\$WindowLayout")
- )))
+ )
+ )
+ )
val actual = generateDirectionsTypeSpec(action, false)
assertThat(wrappedInnerClass(actual).toString()).parsesAs("a.b.Next")
}
@Test
fun testDirectionsClassGeneration() {
- val nextAction = Action(id("next"), id("destA"),
+ val nextAction = Action(
+ id("next"), id("destA"),
listOf(
Argument("main", StringType),
Argument("optional", StringType, StringValue("bla"))
- ))
+ )
+ )
val prevAction = Action(id("previous"), id("destB"), emptyList())
- val dest = Destination(null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(),
- listOf(prevAction, nextAction))
+ val dest = Destination(
+ null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(),
+ listOf(prevAction, nextAction)
+ )
val actual = generateDirectionsCodeFile(dest, emptyList(), false)
assertThat(actual.toString()).parsesAs("a.b.MainFragmentDirections")
@@ -107,11 +114,15 @@
@Test
fun testDirectionsClassGeneration_withKeywordId() {
- val funAction = Action(ResReference("fun.is.in", "id", "next"), id("destA"),
- listOf())
+ val funAction = Action(
+ ResReference("fun.is.in", "id", "next"), id("destA"),
+ listOf()
+ )
- val dest = Destination(null, ClassName.get("a.b", "FunFragment"), "fragment", listOf(),
- listOf(funAction))
+ val dest = Destination(
+ null, ClassName.get("a.b", "FunFragment"), "fragment", listOf(),
+ listOf(funAction)
+ )
val actual = generateDirectionsCodeFile(dest, emptyList(), false)
assertThat(actual.toString()).parsesAs("a.b.FunFragmentDirections")
@@ -119,47 +130,73 @@
@Test
fun testDirectionsClassGeneration_longPackage() {
- val funAction = Action(ResReference("a.b.secondreallyreallyreallyreally" +
- "reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
- "longpackage", "id", "next"), id("destA"),
- listOf())
+ val funAction = Action(
+ ResReference(
+ "a.b.secondreallyreallyreallyreally" +
+ "reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
+ "longpackage",
+ "id", "next"
+ ),
+ id("destA"),
+ listOf()
+ )
- val dest = Destination(null, ClassName.get("a.b.reallyreallyreallyreally" +
- "reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
- "longpackage", "LongPackageFragment"), "fragment", listOf(),
- listOf(funAction))
+ val dest = Destination(
+ null,
+ ClassName.get(
+ "a.b.reallyreallyreallyreally" +
+ "reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
+ "longpackage",
+ "LongPackageFragment"
+ ),
+ "fragment", listOf(),
+ listOf(funAction)
+ )
val actual = generateDirectionsCodeFile(dest, emptyList(), false)
- assertThat(actual.toString()).parsesAs("a.b.reallyreallyreallyreallyreally" +
+ assertThat(actual.toString()).parsesAs(
+ "a.b.reallyreallyreallyreallyreally" +
"reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" +
- "longpackage.LongPackageFragmentDirections")
+ "longpackage.LongPackageFragmentDirections"
+ )
}
@Test
fun testArgumentsClassGeneration() {
- val dest = Destination(null, ClassName.get("a.b", "MainFragment"), "fragment", listOf(
- Argument("main", StringType),
- Argument("optional", IntType, IntValue("-1")),
- Argument("reference", ReferenceType, ReferenceValue(ResReference("a.b", "drawable",
- "background"))),
- Argument("referenceZeroDefaultValue", ReferenceType, IntValue("0")),
- Argument("floatArg", FloatType, FloatValue("1")),
- Argument("floatArrayArg", FloatArrayType),
- Argument("objectArrayArg", ObjectArrayType("android.content.pm.ActivityInfo")),
- Argument("boolArg", BoolType, BooleanValue("true")),
- Argument(
- "optionalParcelable",
- ObjectType("android.content.pm.ActivityInfo"),
- NullValue,
- true
+ val dest = Destination(
+ null, ClassName.get("a.b", "MainFragment"), "fragment",
+ listOf(
+ Argument("main", StringType),
+ Argument("optional", IntType, IntValue("-1")),
+ Argument(
+ "reference", ReferenceType,
+ ReferenceValue(
+ ResReference(
+ "a.b", "drawable",
+ "background"
+ )
+ )
+ ),
+ Argument("referenceZeroDefaultValue", ReferenceType, IntValue("0")),
+ Argument("floatArg", FloatType, FloatValue("1")),
+ Argument("floatArrayArg", FloatArrayType),
+ Argument("objectArrayArg", ObjectArrayType("android.content.pm.ActivityInfo")),
+ Argument("boolArg", BoolType, BooleanValue("true")),
+ Argument(
+ "optionalParcelable",
+ ObjectType("android.content.pm.ActivityInfo"),
+ NullValue,
+ true
+ ),
+ Argument(
+ "enumArg",
+ ObjectType("java.nio.file.AccessMode"),
+ EnumValue(ObjectType("java.nio.file.AccessMode"), "READ"),
+ false
+ )
),
- Argument(
- "enumArg",
- ObjectType("java.nio.file.AccessMode"),
- EnumValue(ObjectType("java.nio.file.AccessMode"), "READ"),
- false
- )),
- listOf())
+ listOf()
+ )
val actual = generateArgsCodeFile(dest, false)
assertThat(actual.toString()).parsesAs("a.b.MainFragmentArgs")
@@ -167,13 +204,21 @@
@Test
fun testArgumentClassGeneration_longArgumentName() {
- val dest = Destination(null, ClassName.get("a.b",
- "ReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReally" +
- "LongNameFragment"), "fragment",
- listOf(), listOf())
+ val dest = Destination(
+ null,
+ ClassName.get(
+ "a.b",
+ "ReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReally" +
+ "ReallyLongNameFragment"
+ ),
+ "fragment",
+ listOf(), listOf()
+ )
val actual = generateArgsCodeFile(dest, false)
- assertThat(actual.toString()).parsesAs("a.b.ReallyReallyReallyReallyReally" +
- "ReallyReallyReallyReallyReallyReallyReallyReallyReallyLongNameMainFragmentArgs")
+ assertThat(actual.toString()).parsesAs(
+ "a.b.ReallyReallyReallyReallyReally" +
+ "ReallyReallyReallyReallyReallyReallyReallyReallyReallyLongNameMainFragmentArgs"
+ )
}
-}
\ No newline at end of file
+}
diff --git a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavArgumentResolverTest.kt b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavArgumentResolverTest.kt
index a77cb72..b9c2d88 100644
--- a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavArgumentResolverTest.kt
+++ b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavArgumentResolverTest.kt
@@ -34,53 +34,86 @@
private fun id(id: String) = ResReference("a.b", "id", id)
private fun createTemplateDestination(name: String) =
- Destination(
- id(name), ClassName.get("foo", "Fragment${name.capitalize()}"), "test",
- listOf(
- Argument("arg1", StringType),
- Argument("arg2", StringType, StringValue("foo"))
- ), emptyList())
+ Destination(
+ id(name), ClassName.get("foo", "Fragment${name.capitalize()}"), "test",
+ listOf(
+ Argument("arg1", StringType),
+ Argument("arg2", StringType, StringValue("foo"))
+ ),
+ emptyList()
+ )
@Test
fun test() {
val dest1Template = createTemplateDestination("first")
val dest2Template = createTemplateDestination("second")
- val outerScopeAction = Action(id("toOuterScope"), id("outerScope"),
- listOf(Argument("boo", StringType)))
- val dest1 = dest1Template.copy(actions = listOf(Action(id("action1"), dest2Template.id),
- outerScopeAction))
- val dest2 = dest2Template.copy(actions = listOf(Action(id("action2"), dest1Template.id,
- listOf(Argument("arg1", StringType, StringValue("actionValue")),
- Argument("actionArg", StringType)))))
+ val outerScopeAction = Action(
+ id("toOuterScope"), id("outerScope"),
+ listOf(Argument("boo", StringType))
+ )
+ val dest1 = dest1Template.copy(
+ actions = listOf(
+ Action(id("action1"), dest2Template.id),
+ outerScopeAction
+ )
+ )
+ val dest2 = dest2Template.copy(
+ actions = listOf(
+ Action(
+ id("action2"), dest1Template.id,
+ listOf(
+ Argument("arg1", StringType, StringValue("actionValue")),
+ Argument("actionArg", StringType)
+ )
+ )
+ )
+ )
- val topLevel = Destination(null, null, "test",
- emptyList(), emptyList(), listOf(dest1, dest2))
+ val topLevel = Destination(
+ null, null, "test",
+ emptyList(), emptyList(), listOf(dest1, dest2)
+ )
val resolveArguments = resolveArguments(topLevel)
assertThat(resolveArguments.nested.size, `is`(2))
val resolvedAction1 = Action(id("action1"), dest2Template.id, dest2.args)
- assertThat(resolveArguments.nested[0].actions, `is`(listOf(resolvedAction1,
- outerScopeAction)))
+ assertThat(
+ resolveArguments.nested[0].actions,
+ `is`(
+ listOf(
+ resolvedAction1,
+ outerScopeAction
+ )
+ )
+ )
- val resolvedAction2 = Action(id("action2"), dest1Template.id, listOf(
+ val resolvedAction2 = Action(
+ id("action2"), dest1Template.id,
+ listOf(
Argument("arg1", StringType, StringValue("actionValue")),
Argument("actionArg", StringType),
Argument("arg2", StringType, StringValue("foo"))
- ))
+ )
+ )
assertThat(resolveArguments.nested[1].actions, `is`(listOf(resolvedAction2)))
}
@Test
fun testIncompatibleTypes() {
val dest1 = createTemplateDestination("first")
- val invalidAction = Action(id("action"), dest1.id, listOf(
+ val invalidAction = Action(
+ id("action"), dest1.id,
+ listOf(
Argument("arg2", IntType, IntValue("11")),
Argument("arg1", StringType)
- ))
+ )
+ )
- val topLevel = Destination(null, null, "test", emptyList(), listOf(invalidAction),
- listOf(dest1))
+ val topLevel = Destination(
+ null, null, "test", emptyList(), listOf(invalidAction),
+ listOf(dest1)
+ )
try {
resolveArguments(topLevel)
diff --git a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavGeneratorTest.kt b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavGeneratorTest.kt
index 401dbe6..7f29cd0 100644
--- a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavGeneratorTest.kt
+++ b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavGeneratorTest.kt
@@ -75,14 +75,17 @@
@Test
fun naive_test() {
- val output = generateSafeArgs("foo", "foo.flavor",
- testData("naive_test.xml"), workingDir.root)
+ val output = generateSafeArgs(
+ "foo", "foo.flavor",
+ testData("naive_test.xml"), workingDir.root
+ )
val fileNames = output.fileNames
val expectedSet = setOf(
- "androidx.navigation.testapp.MainFragmentDirections",
- "foo.flavor.NextFragmentDirections",
- "androidx.navigation.testapp.MainFragmentArgs",
- "foo.flavor.NextFragmentArgs")
+ "androidx.navigation.testapp.MainFragmentDirections",
+ "foo.flavor.NextFragmentDirections",
+ "androidx.navigation.testapp.MainFragmentArgs",
+ "foo.flavor.NextFragmentArgs"
+ )
assertThat(output.errors.isEmpty(), `is`(true))
assertThat(fileNames.toSet(), `is`(expectedSet))
fileNames.forEach { name ->
@@ -94,14 +97,17 @@
@Test
fun nested_test() {
- val output = generateSafeArgs("foo", "foo.flavor",
- testData("nested_login_test.xml"), workingDir.root)
+ val output = generateSafeArgs(
+ "foo", "foo.flavor",
+ testData("nested_login_test.xml"), workingDir.root
+ )
val fileNames = output.fileNames
val expectedSet = setOf(
- "foo.flavor.MainFragmentDirections",
- "foo.LoginDirections",
- "foo.flavor.account.LoginFragmentDirections",
- "foo.flavor.account.RegisterFragmentDirections")
+ "foo.flavor.MainFragmentDirections",
+ "foo.LoginDirections",
+ "foo.flavor.account.LoginFragmentDirections",
+ "foo.flavor.account.RegisterFragmentDirections"
+ )
assertThat(output.errors.isEmpty(), `is`(true))
assertThat(fileNames.toSet(), `is`(expectedSet))
fileNames.forEach { name ->
@@ -112,7 +118,7 @@
val codeFiles = fileNames
.mapIndexed { index, name -> name to (output.files[index]) }
- .associate { it }
+ .associate { it }
codeFiles.forEach { (name, file) ->
file.assertParsesAs(name, "nested")
}
@@ -120,13 +126,16 @@
@Test
fun nested_same_action_test() {
- val output = generateSafeArgs("foo", "foo.flavor",
- testData("nested_same_action_test.xml"), workingDir.root)
+ val output = generateSafeArgs(
+ "foo", "foo.flavor",
+ testData("nested_same_action_test.xml"), workingDir.root
+ )
val fileNames = output.fileNames
val expectedSet = setOf(
"foo.flavor.MainFragmentDirections",
"foo.SettingsDirections",
- "foo.flavor.SettingsFragmentDirections")
+ "foo.flavor.SettingsFragmentDirections"
+ )
assertThat(output.errors.isEmpty(), `is`(true))
assertThat(fileNames.toSet(), `is`(expectedSet))
fileNames.forEach { name ->
@@ -145,15 +154,18 @@
@Test
fun nested_overridden_action_test() {
- val output = generateSafeArgs("foo", "foo.flavor",
- testData("nested_overridden_action_test.xml"), workingDir.root)
+ val output = generateSafeArgs(
+ "foo", "foo.flavor",
+ testData("nested_overridden_action_test.xml"), workingDir.root
+ )
val fileNames = output.fileNames
val expectedSet = setOf(
"foo.flavor.MainFragmentDirections",
"foo.SettingsDirections",
"foo.flavor.SettingsFragmentDirections",
"foo.InnerSettingsDirections",
- "foo.flavor.InnerSettingsFragmentDirections")
+ "foo.flavor.InnerSettingsFragmentDirections"
+ )
assertThat(output.errors.isEmpty(), `is`(true))
assertThat(fileNames.toSet(), `is`(expectedSet))
fileNames.forEach { name ->
diff --git a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavParserTest.kt b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavParserTest.kt
index e45da8a..f71bd42 100644
--- a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavParserTest.kt
+++ b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/NavParserTest.kt
@@ -36,32 +36,42 @@
@Test
fun testNaiveGraph() {
val id: (String) -> ResReference = { id -> ResReference("a.b", "id", id) }
- val navGraph = NavParser.parseNavigationFile(testData("naive_test.xml"),
- "a.b", "foo.app", Context())
+ val navGraph = NavParser.parseNavigationFile(
+ testData("naive_test.xml"),
+ "a.b", "foo.app", Context()
+ )
val nameFirst = ClassName.get("androidx.navigation.testapp", "MainFragment")
val nameNext = ClassName.get("foo.app", "NextFragment")
- val expectedFirst = Destination(id("first_screen"), nameFirst, "fragment",
- listOf(Argument("myarg1", StringType, StringValue("one"))),
- listOf(Action(id("next"), id("next_fragment"), listOf(
+ val expectedFirst = Destination(
+ id("first_screen"), nameFirst, "fragment",
+ listOf(Argument("myarg1", StringType, StringValue("one"))),
+ listOf(
+ Action(
+ id("next"), id("next_fragment"),
+ listOf(
Argument("myarg2", StringType),
Argument("randomArgument", StringType),
Argument("intArgument", IntType, IntValue("261")),
Argument("referenceZeroDefaultValue", ReferenceType, IntValue("0")),
Argument(
- "activityInfo",
- ObjectType("android.content.pm.ActivityInfo")
+ "activityInfo",
+ ObjectType("android.content.pm.ActivityInfo")
),
Argument(
- "activityInfoNull",
- ObjectType("android.content.pm.ActivityInfo"),
- NullValue,
- true
+ "activityInfoNull",
+ ObjectType("android.content.pm.ActivityInfo"),
+ NullValue,
+ true
),
Argument("intArrayArg", IntArrayType),
Argument("stringArrayArg", StringArrayType),
- Argument("objectArrayArg", ObjectArrayType(
- "android.content.pm.ActivityInfo")),
+ Argument(
+ "objectArrayArg",
+ ObjectArrayType(
+ "android.content.pm.ActivityInfo"
+ )
+ ),
Argument(
"enumArg",
ObjectType("java.nio.file.AccessMode"),
@@ -82,55 +92,72 @@
),
Argument("implicitNullString", StringType, NullValue, true),
Argument("explicitNullString", StringType, NullValue, true)
- ))))
+ )
+ )
+ )
+ )
- val expectedNext = Destination(id("next_fragment"), nameNext, "fragment",
- listOf(Argument("myarg2", StringType)),
- listOf(Action(id("next"), id("first_screen")),
- Action(id("finish"), null)))
+ val expectedNext = Destination(
+ id("next_fragment"), nameNext, "fragment",
+ listOf(Argument("myarg2", StringType)),
+ listOf(
+ Action(id("next"), id("first_screen")),
+ Action(id("finish"), null)
+ )
+ )
- val expectedGraph = Destination(null, null, "navigation", emptyList(), emptyList(),
- listOf(expectedFirst, expectedNext))
+ val expectedGraph = Destination(
+ null, null, "navigation", emptyList(), emptyList(),
+ listOf(expectedFirst, expectedNext)
+ )
assertThat(navGraph, `is`(expectedGraph))
}
@Test
fun testNestedGraph() {
val id: (String) -> ResReference = { id -> ResReference("a.b", "id", id) }
- val navGraph = NavParser.parseNavigationFile(testData("nested_login_test.xml"),
- "a.b", "foo.app", Context())
+ val navGraph = NavParser.parseNavigationFile(
+ testData("nested_login_test.xml"),
+ "a.b", "foo.app", Context()
+ )
val expectedMainFragment = Destination(
- id = id("main_fragment"),
- name = ClassName.get("foo.app", "MainFragment"),
- type = "fragment",
- args = emptyList(),
- actions = listOf(Action(id("start_login"), id("login"))))
+ id = id("main_fragment"),
+ name = ClassName.get("foo.app", "MainFragment"),
+ type = "fragment",
+ args = emptyList(),
+ actions = listOf(Action(id("start_login"), id("login")))
+ )
val expectedNestedFragment1 = Destination(
- id = id("login_fragment"),
- name = ClassName.get("foo.app.account", "LoginFragment"),
- type = "fragment",
- args = emptyList(),
- actions = listOf(Action(id("register"), id("register_fragment"))))
+ id = id("login_fragment"),
+ name = ClassName.get("foo.app.account", "LoginFragment"),
+ type = "fragment",
+ args = emptyList(),
+ actions = listOf(Action(id("register"), id("register_fragment")))
+ )
val expectedNestedFragment2 = Destination(
- id = id("register_fragment"),
- name = ClassName.get("foo.app.account", "RegisterFragment"),
- type = "fragment",
- args = emptyList(),
- actions = emptyList())
+ id = id("register_fragment"),
+ name = ClassName.get("foo.app.account", "RegisterFragment"),
+ type = "fragment",
+ args = emptyList(),
+ actions = emptyList()
+ )
val expectedNestedGraph = Destination(
- id = id("login"),
- name = ClassName.get("a.b", "Login"),
- type = "navigation",
- args = emptyList(),
- actions = listOf(Action(id("action_done"), null)),
- nested = listOf(expectedNestedFragment1, expectedNestedFragment2))
+ id = id("login"),
+ name = ClassName.get("a.b", "Login"),
+ type = "navigation",
+ args = emptyList(),
+ actions = listOf(Action(id("action_done"), null)),
+ nested = listOf(expectedNestedFragment1, expectedNestedFragment2)
+ )
- val expectedGraph = Destination(null, null, "navigation", emptyList(), emptyList(),
- listOf(expectedMainFragment, expectedNestedGraph))
+ val expectedGraph = Destination(
+ null, null, "navigation", emptyList(), emptyList(),
+ listOf(expectedMainFragment, expectedNestedGraph)
+ )
assertThat(navGraph, `is`(expectedGraph))
}
@@ -139,20 +166,28 @@
fun testNestedIncludedGraph() {
val id: (String) -> ResReference = { id -> ResReference("a.b", "id", id) }
val nestedIncludeNavGraph = NavParser.parseNavigationFile(
- testData("nested_include_login_test.xml"), "a.b", "foo.app", Context())
+ testData("nested_include_login_test.xml"), "a.b", "foo.app", Context()
+ )
val expectedMainFragment = Destination(
- id = id("main_fragment"),
- name = ClassName.get("foo.app", "MainFragment"),
- type = "fragment",
- args = emptyList(),
- actions = listOf(Action(id("start_login"), id("login"))))
+ id = id("main_fragment"),
+ name = ClassName.get("foo.app", "MainFragment"),
+ type = "fragment",
+ args = emptyList(),
+ actions = listOf(Action(id("start_login"), id("login")))
+ )
- val expectedIncluded = IncludedDestination(ResReference("a.b", "navigation",
- "to_include_login_test"))
+ val expectedIncluded = IncludedDestination(
+ ResReference(
+ "a.b", "navigation",
+ "to_include_login_test"
+ )
+ )
- val expectedGraph = Destination(null, null, "navigation", emptyList(), emptyList(),
- listOf(expectedMainFragment), listOf(expectedIncluded))
+ val expectedGraph = Destination(
+ null, null, "navigation", emptyList(), emptyList(),
+ listOf(expectedMainFragment), listOf(expectedIncluded)
+ )
assertThat(nestedIncludeNavGraph, `is`(expectedGraph))
}
@@ -161,12 +196,18 @@
fun testReferenceParsing() {
assertThat(parseReference("@+id/next", "a.b"), `is`(ResReference("a.b", "id", "next")))
assertThat(parseReference("@id/next", "a.b"), `is`(ResReference("a.b", "id", "next")))
- assertThat(parseReference("@android:string/text", "a.b"),
- `is`(ResReference("android", "string", "text")))
- assertThat(parseReference("@android:id/text", "a.b"),
- `is`(ResReference("android", "id", "text")))
- assertThat(parseReference("@not.android:string/text", "a.b"),
- `is`(ResReference("not.android", "string", "text")))
+ assertThat(
+ parseReference("@android:string/text", "a.b"),
+ `is`(ResReference("android", "string", "text"))
+ )
+ assertThat(
+ parseReference("@android:id/text", "a.b"),
+ `is`(ResReference("android", "id", "text"))
+ )
+ assertThat(
+ parseReference("@not.android:string/text", "a.b"),
+ `is`(ResReference("not.android", "string", "text"))
+ )
}
@Test
@@ -227,41 +268,73 @@
assertThat(infer("123L"), `is`(longArg("123L")))
assertThat(infer("1234123412341234L"), `is`(longArg("1234123412341234L")))
- assertThat(infer("@integer/test_integer_arg"),
- `is`(resolvedReferenceArg("a.b", IntType, "integer", "test_integer_arg")))
- assertThat(infer("@dimen/test_dimen_arg"),
- `is`(resolvedReferenceArg("a.b", IntType, "dimen", "test_dimen_arg")))
- assertThat(infer("@style/AppTheme"),
- `is`(resolvedReferenceArg("a.b", ReferenceType, "style", "AppTheme")))
- assertThat(infer("@string/test_string_arg"),
- `is`(resolvedReferenceArg("a.b", StringType, "string", "test_string_arg")))
- assertThat(infer("@color/test_color_arg"),
- `is`(resolvedReferenceArg("a.b", IntType, "color", "test_color_arg")))
+ assertThat(
+ infer("@integer/test_integer_arg"),
+ `is`(resolvedReferenceArg("a.b", IntType, "integer", "test_integer_arg"))
+ )
+ assertThat(
+ infer("@dimen/test_dimen_arg"),
+ `is`(resolvedReferenceArg("a.b", IntType, "dimen", "test_dimen_arg"))
+ )
+ assertThat(
+ infer("@style/AppTheme"),
+ `is`(resolvedReferenceArg("a.b", ReferenceType, "style", "AppTheme"))
+ )
+ assertThat(
+ infer("@string/test_string_arg"),
+ `is`(resolvedReferenceArg("a.b", StringType, "string", "test_string_arg"))
+ )
+ assertThat(
+ infer("@color/test_color_arg"),
+ `is`(resolvedReferenceArg("a.b", IntType, "color", "test_color_arg"))
+ )
}
@Test
fun testArgSanitizedName() {
- assertEquals("camelCaseName",
- Argument("camelCaseName", IntType).sanitizedName)
- assertEquals("ALLCAPSNAME",
- Argument("ALLCAPSNAME", IntType).sanitizedName)
- assertEquals("alllowercasename",
- Argument("alllowercasename", IntType).sanitizedName)
- assertEquals("nameWithUnderscore",
- Argument("name_with_underscore", IntType).sanitizedName)
- assertEquals("NameWithUnderscore",
- Argument("Name_With_Underscore", IntType).sanitizedName)
- assertEquals("NAMEWITHUNDERSCORE",
- Argument("NAME_WITH_UNDERSCORE", IntType).sanitizedName)
- assertEquals("nameWithSpaces",
- Argument("name with spaces", IntType).sanitizedName)
- assertEquals("nameWithDot",
- Argument("name.with.dot", IntType).sanitizedName)
- assertEquals("nameWithDollars",
- Argument("name\$with\$dollars", IntType).sanitizedName)
- assertEquals("nameWithBangs",
- Argument("name!with!bangs", IntType).sanitizedName)
- assertEquals("nameWithHyphens",
- Argument("name-with-hyphens", IntType).sanitizedName)
+ assertEquals(
+ "camelCaseName",
+ Argument("camelCaseName", IntType).sanitizedName
+ )
+ assertEquals(
+ "ALLCAPSNAME",
+ Argument("ALLCAPSNAME", IntType).sanitizedName
+ )
+ assertEquals(
+ "alllowercasename",
+ Argument("alllowercasename", IntType).sanitizedName
+ )
+ assertEquals(
+ "nameWithUnderscore",
+ Argument("name_with_underscore", IntType).sanitizedName
+ )
+ assertEquals(
+ "NameWithUnderscore",
+ Argument("Name_With_Underscore", IntType).sanitizedName
+ )
+ assertEquals(
+ "NAMEWITHUNDERSCORE",
+ Argument("NAME_WITH_UNDERSCORE", IntType).sanitizedName
+ )
+ assertEquals(
+ "nameWithSpaces",
+ Argument("name with spaces", IntType).sanitizedName
+ )
+ assertEquals(
+ "nameWithDot",
+ Argument("name.with.dot", IntType).sanitizedName
+ )
+ assertEquals(
+ "nameWithDollars",
+ Argument("name\$with\$dollars", IntType).sanitizedName
+ )
+ assertEquals(
+ "nameWithBangs",
+ Argument("name!with!bangs", IntType).sanitizedName
+ )
+ assertEquals(
+ "nameWithHyphens",
+ Argument("name-with-hyphens", IntType).sanitizedName
+ )
}
}
\ No newline at end of file
diff --git a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/TestUtils.kt b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/TestUtils.kt
index 728f47c..0cad640 100644
--- a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/TestUtils.kt
+++ b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/TestUtils.kt
@@ -25,7 +25,7 @@
fun JavaCodeFile.toJavaFileObject() = this.wrapped.toJavaFileObject()
fun JavaSourcesSubject.parsesAs(fullClassName: String, folder: String = "expected") =
- this.parsesAs(loadSourceFileObject(fullClassName, folder))
+ this.parsesAs(loadSourceFileObject(fullClassName, folder))
fun loadSourceString(fullClassName: String, folder: String, fileExtension: String): String {
val folderPath = "src/test/test-data/${if (folder.isEmpty()) "" else "$folder/"}"
diff --git a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/WritableValueTest.kt b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/WritableValueTest.kt
index d7335c9..3f7d890 100644
--- a/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/WritableValueTest.kt
+++ b/navigation/navigation-safe-args-generator/src/test/kotlin/androidx/navigation/safe/args/generator/WritableValueTest.kt
@@ -40,7 +40,9 @@
@Test
fun testReferenceWrite() {
- assertThat(ReferenceValue(ResReference("foo", "id", "bla")).write().toString(),
- `is`("foo.R.id.bla"))
+ assertThat(
+ ReferenceValue(ResReference("foo", "id", "bla")).write().toString(),
+ `is`("foo.R.id.bla")
+ )
}
}
\ No newline at end of file
diff --git a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/ArgumentsGenerationTask.kt b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/ArgumentsGenerationTask.kt
index c95843e..a66edb1 100644
--- a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/ArgumentsGenerationTask.kt
+++ b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/ArgumentsGenerationTask.kt
@@ -81,9 +81,12 @@
navigationXml = file,
outputDir = out,
useAndroidX = useAndroidX,
- generateKotlin = generateKotlin).generate()
- Mapping(file.relativeTo(
- projectLayout.projectDirectory.asFile).path,
+ generateKotlin = generateKotlin
+ ).generate()
+ Mapping(
+ file.relativeTo(
+ projectLayout.projectDirectory.asFile
+ ).path,
output.fileNames
) to output.errors
}.unzip().let { (mappings, errorLists) -> mappings to errorLists.flatten() }
@@ -143,16 +146,16 @@
File(projectLayout.projectDirectory.asFile, it.navFile) in changedInputs
}
modified.flatMap { it.javaFiles }
- .filter { name -> name !in newJavaFiles }
- .forEach { javaName ->
- val fileExtension = if (generateKotlin) { ".kt" } else { ".java" }
- val fileName =
- "${javaName.replace('.', File.separatorChar)}$fileExtension"
- val file = File(outputDir, fileName)
- if (file.exists()) {
- file.delete()
- }
+ .filter { name -> name !in newJavaFiles }
+ .forEach { javaName ->
+ val fileExtension = if (generateKotlin) { ".kt" } else { ".java" }
+ val fileName =
+ "${javaName.replace('.', File.separatorChar)}$fileExtension"
+ val file = File(outputDir, fileName)
+ if (file.exists()) {
+ file.delete()
}
+ }
writeMappings(unmodified + newMapping)
failIfErrors(errors)
}
@@ -161,14 +164,15 @@
if (errors.isNotEmpty()) {
val errString = errors.joinToString("\n") { it.toClickableText() }
throw GradleException(
- "androidx.navigation.safeargs plugin failed.\n " +
- "Following errors found: \n$errString")
+ "androidx.navigation.safeargs plugin failed.\n " +
+ "Following errors found: \n$errString"
+ )
}
}
}
private fun ErrorMessage.toClickableText() = "$path:$line:$column " +
- "(${File(path).name}:$line): \n" +
- "error: $message"
+ "(${File(path).name}:$line): \n" +
+ "error: $message"
private data class Mapping(val navFile: String, val javaFiles: List<String>)
diff --git a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt
index 3ec30e5..fe012d4 100644
--- a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt
+++ b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt
@@ -46,19 +46,22 @@
extension is LibraryExtension -> {
extension.libraryVariants.all(action)
}
- else -> throw GradleException("safeargs plugin must be used with android app," +
- "library or feature plugin")
+ else -> throw GradleException(
+ "safeargs plugin must be used with android app," +
+ "library or feature plugin"
+ )
}
}
override fun apply(project: Project) {
val extension = project.extensions.findByType(BaseExtension::class.java)
- ?: throw GradleException("safeargs plugin must be used with android plugin")
+ ?: throw GradleException("safeargs plugin must be used with android plugin")
val isKotlinProject =
project.extensions.findByType(KotlinProjectExtension::class.java) != null
if (!isKotlinProject && generateKotlin) {
throw GradleException(
- "androidx.navigation.safeargs.kotlin plugin must be used with kotlin plugin")
+ "androidx.navigation.safeargs.kotlin plugin must be used with kotlin plugin"
+ )
}
forEachVariant(extension) { variant ->
val task = project.tasks.create(
diff --git a/navigation/navigation-safe-args-gradle-plugin/src/test/kotlin/androidx/navigation/safeargs/gradle/BasePluginTest.kt b/navigation/navigation-safe-args-gradle-plugin/src/test/kotlin/androidx/navigation/safeargs/gradle/BasePluginTest.kt
index 3117aba..ca3a089 100644
--- a/navigation/navigation-safe-args-gradle-plugin/src/test/kotlin/androidx/navigation/safeargs/gradle/BasePluginTest.kt
+++ b/navigation/navigation-safe-args-gradle-plugin/src/test/kotlin/androidx/navigation/safeargs/gradle/BasePluginTest.kt
@@ -113,7 +113,7 @@
maven { url "${props.prebuiltsRoot}/androidx/internal" }
}
}
- """.trimIndent()
+ """.trimIndent()
)
}
diff --git a/navigation/navigation-testing/build.gradle b/navigation/navigation-testing/build.gradle
index aa7bc0d..3172c9c 100644
--- a/navigation/navigation-testing/build.gradle
+++ b/navigation/navigation-testing/build.gradle
@@ -31,6 +31,7 @@
api(project(":navigation:navigation-runtime-ktx"))
androidTestImplementation(project(":internal-testutils-navigation"))
+ androidTestImplementation(project(":navigation:navigation-fragment-ktx"))
androidTestImplementation(ANDROIDX_TEST_CORE)
androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
androidTestImplementation(ANDROIDX_TEST_EXT_TRUTH)
diff --git a/navigation/navigation-testing/src/androidTest/java/androidx/navigation/testing/TestNavHostControllerTest.kt b/navigation/navigation-testing/src/androidTest/java/androidx/navigation/testing/TestNavHostControllerTest.kt
index 729b71d..7586544 100644
--- a/navigation/navigation-testing/src/androidTest/java/androidx/navigation/testing/TestNavHostControllerTest.kt
+++ b/navigation/navigation-testing/src/androidTest/java/androidx/navigation/testing/TestNavHostControllerTest.kt
@@ -17,6 +17,16 @@
package androidx.navigation.testing
import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentController
+import androidx.fragment.app.FragmentHostCallback
+import androidx.navigation.NavOptions
+import androidx.navigation.Navigator
+import androidx.navigation.createGraph
+import androidx.navigation.fragment.FragmentNavigator
+import androidx.navigation.fragment.fragment
import androidx.navigation.plusAssign
import androidx.navigation.testing.test.R
import androidx.test.core.app.ApplicationProvider
@@ -68,6 +78,18 @@
}
@Test
+ fun testDsl() {
+ navController.navigatorProvider += NoOpFragmentNavigator()
+ navController.graph = navController.createGraph(R.id.test_graph, R.id.start_test) {
+ fragment<Fragment>(R.id.start_test)
+ }
+ val backStack = navController.backStack
+ assertThat(backStack).hasSize(2)
+ assertThat(backStack[1].destination)
+ .isInstanceOf(FragmentNavigator.Destination::class.java)
+ }
+
+ @Test
fun testSetDestinationId() {
navController.setGraph(R.navigation.test_graph)
navController.setCurrentDestination(R.id.third_test)
@@ -92,3 +114,23 @@
assertThat(actualArgs).string("arg").isEqualTo("test")
}
}
+
[email protected]("fragment")
+class NoOpFragmentNavigator : FragmentNavigator(
+ ApplicationProvider.getApplicationContext(),
+ FragmentController.createController(object : FragmentHostCallback<Nothing>(
+ ApplicationProvider.getApplicationContext(), Handler(Looper.getMainLooper()), 0
+ ) {
+ override fun onGetHost() = null
+ }).supportFragmentManager,
+ 0
+) {
+ override fun popBackStack() = true
+
+ override fun navigate(
+ destination: Destination,
+ args: Bundle?,
+ navOptions: NavOptions?,
+ navigatorExtras: Navigator.Extras?
+ ) = destination
+}
diff --git a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/Activity.kt b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/Activity.kt
index 93ce7be..13e1d29b 100644
--- a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/Activity.kt
+++ b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/Activity.kt
@@ -44,8 +44,10 @@
navController: NavController,
drawerLayout: DrawerLayout?
) {
- NavigationUI.setupActionBarWithNavController(this, navController,
- AppBarConfiguration(navController.graph, drawerLayout))
+ NavigationUI.setupActionBarWithNavController(
+ this, navController,
+ AppBarConfiguration(navController.graph, drawerLayout)
+ )
}
/**
diff --git a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/CollapsingToolbarLayout.kt b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/CollapsingToolbarLayout.kt
index 89c3859..99d45e7 100644
--- a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/CollapsingToolbarLayout.kt
+++ b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/CollapsingToolbarLayout.kt
@@ -45,8 +45,10 @@
navController: NavController,
drawerLayout: DrawerLayout?
) {
- NavigationUI.setupWithNavController(this, toolbar, navController,
- AppBarConfiguration(navController.graph, drawerLayout))
+ NavigationUI.setupWithNavController(
+ this, toolbar, navController,
+ AppBarConfiguration(navController.graph, drawerLayout)
+ )
}
/**
diff --git a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/MenuItem.kt b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/MenuItem.kt
index cf87716..ee637cd 100644
--- a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/MenuItem.kt
+++ b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/MenuItem.kt
@@ -33,4 +33,4 @@
* @return True if the [NavController] was able to navigate to the destination.
*/
fun MenuItem.onNavDestinationSelected(navController: NavController): Boolean =
- NavigationUI.onNavDestinationSelected(this, navController)
+ NavigationUI.onNavDestinationSelected(this, navController)
diff --git a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/NavController.kt b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/NavController.kt
index f5adbf8..30ff16b 100644
--- a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/NavController.kt
+++ b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/NavController.kt
@@ -27,8 +27,10 @@
* @return True if the [NavController] was able to navigate up.
*/
fun NavController.navigateUp(drawerLayout: Openable?): Boolean =
- NavigationUI.navigateUp(this,
- AppBarConfiguration(graph, drawerLayout))
+ NavigationUI.navigateUp(
+ this,
+ AppBarConfiguration(graph, drawerLayout)
+ )
/**
* Handles the Up button by delegating its behavior to the given [NavController].
@@ -36,4 +38,4 @@
* @return True if the [NavController] was able to navigate up.
*/
fun NavController.navigateUp(appBarConfiguration: AppBarConfiguration): Boolean =
- NavigationUI.navigateUp(this, appBarConfiguration)
+ NavigationUI.navigateUp(this, appBarConfiguration)
diff --git a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/Toolbar.kt b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/Toolbar.kt
index af01cd1..787b0ab 100644
--- a/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/Toolbar.kt
+++ b/navigation/navigation-ui-ktx/src/main/java/androidx/navigation/ui/Toolbar.kt
@@ -42,8 +42,10 @@
navController: NavController,
drawerLayout: DrawerLayout?
) {
- NavigationUI.setupWithNavController(this, navController,
- AppBarConfiguration(navController.graph, drawerLayout))
+ NavigationUI.setupWithNavController(
+ this, navController,
+ AppBarConfiguration(navController.graph, drawerLayout)
+ )
}
/**
diff --git a/paging/common/src/main/kotlin/androidx/paging/ContiguousPagedList.kt b/paging/common/src/main/kotlin/androidx/paging/ContiguousPagedList.kt
index a5c30b7..22965ea 100644
--- a/paging/common/src/main/kotlin/androidx/paging/ContiguousPagedList.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/ContiguousPagedList.kt
@@ -47,7 +47,9 @@
pagingSource,
PagedStorage<V>(),
config
-), PagedStorage.Callback, LegacyPageFetcher.PageConsumer<V> {
+),
+ PagedStorage.Callback,
+ LegacyPageFetcher.PageConsumer<V> {
internal companion object {
internal fun getPrependItemsRequested(
prefetchDistance: Int,
@@ -251,9 +253,9 @@
*/
private fun tryDispatchBoundaryCallbacks(post: Boolean) {
val dispatchBegin = boundaryCallbackBeginDeferred &&
- lowestIndexAccessed <= config.prefetchDistance
+ lowestIndexAccessed <= config.prefetchDistance
val dispatchEnd = boundaryCallbackEndDeferred &&
- highestIndexAccessed >= size - 1 - config.prefetchDistance
+ highestIndexAccessed >= size - 1 - config.prefetchDistance
if (!dispatchBegin && !dispatchEnd) return
@@ -304,7 +306,7 @@
0,
this,
initialPage.itemsBefore != COUNT_UNDEFINED &&
- initialPage.itemsAfter != COUNT_UNDEFINED
+ initialPage.itemsAfter != COUNT_UNDEFINED
)
} else {
// If placeholder are disabled, avoid passing leading/trailing nulls, since PagingSource
@@ -374,7 +376,7 @@
// we drop a page. Note that we don't use config.enablePlaceholders, since the
// PagingSource may have opted not to load any.
replacePagesWithNulls = storage.placeholdersBefore > 0 ||
- storage.placeholdersAfter > 0
+ storage.placeholdersAfter > 0
}
@MainThread
diff --git a/paging/common/src/main/kotlin/androidx/paging/DataSource.kt b/paging/common/src/main/kotlin/androidx/paging/DataSource.kt
index 1ad5e07..830542d 100644
--- a/paging/common/src/main/kotlin/androidx/paging/DataSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/DataSource.kt
@@ -479,8 +479,8 @@
if (itemsBefore == COUNT_UNDEFINED || itemsAfter == COUNT_UNDEFINED) {
throw IllegalStateException(
"Placeholders requested, but totalCount not provided. Please call the" +
- " three-parameter onResult method, or disable placeholders in the" +
- " PagedList.Config"
+ " three-parameter onResult method, or disable placeholders in the" +
+ " PagedList.Config"
)
}
@@ -488,20 +488,21 @@
val totalCount = itemsBefore + data.size + itemsAfter
throw IllegalArgumentException(
"PositionalDataSource requires initial load size to be a multiple of page" +
- " size to support internal tiling. loadSize ${data.size}, position" +
- " $itemsBefore, totalCount $totalCount, pageSize $pageSize"
+ " size to support internal tiling. loadSize ${data.size}, position" +
+ " $itemsBefore, totalCount $totalCount, pageSize $pageSize"
)
}
if (itemsBefore % pageSize != 0) {
throw IllegalArgumentException(
"Initial load must be pageSize aligned.Position = $itemsBefore, pageSize =" +
- " $pageSize"
+ " $pageSize"
)
}
}
override fun equals(other: Any?) = when (other) {
- is BaseResult<*> -> data == other.data &&
+ is BaseResult<*> ->
+ data == other.data &&
prevKey == other.prevKey &&
nextKey == other.nextKey &&
itemsBefore == other.itemsBefore &&
diff --git a/paging/common/src/main/kotlin/androidx/paging/ItemKeyedDataSource.kt b/paging/common/src/main/kotlin/androidx/paging/ItemKeyedDataSource.kt
index 342ae99..10ea32b 100644
--- a/paging/common/src/main/kotlin/androidx/paging/ItemKeyedDataSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/ItemKeyedDataSource.kt
@@ -178,40 +178,45 @@
@VisibleForTesting
internal suspend fun loadInitial(params: LoadInitialParams<Key>) =
suspendCancellableCoroutine<BaseResult<Value>> { cont ->
- loadInitial(params, object : LoadInitialCallback<Value>() {
- override fun onResult(data: List<Value>, position: Int, totalCount: Int) {
- cont.resume(
- BaseResult(
- data = data,
- prevKey = data.getPrevKey(),
- nextKey = data.getNextKey(),
- itemsBefore = position,
- itemsAfter = totalCount - data.size - position
+ loadInitial(
+ params,
+ object : LoadInitialCallback<Value>() {
+ override fun onResult(data: List<Value>, position: Int, totalCount: Int) {
+ cont.resume(
+ BaseResult(
+ data = data,
+ prevKey = data.getPrevKey(),
+ nextKey = data.getNextKey(),
+ itemsBefore = position,
+ itemsAfter = totalCount - data.size - position
+ )
)
- )
- }
+ }
- override fun onResult(data: List<Value>) {
- cont.resume(
- BaseResult(
- data = data,
- prevKey = data.getPrevKey(),
- nextKey = data.getNextKey()
+ override fun onResult(data: List<Value>) {
+ cont.resume(
+ BaseResult(
+ data = data,
+ prevKey = data.getPrevKey(),
+ nextKey = data.getNextKey()
+ )
)
- )
+ }
}
- })
+ )
}
@Suppress("DEPRECATION")
private fun CancellableContinuation<BaseResult<Value>>.asCallback() =
object : ItemKeyedDataSource.LoadCallback<Value>() {
override fun onResult(data: List<Value>) {
- resume(BaseResult(
- data,
- data.getPrevKey(),
- data.getNextKey()
- ))
+ resume(
+ BaseResult(
+ data,
+ data.getPrevKey(),
+ data.getNextKey()
+ )
+ )
}
}
diff --git a/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt b/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
index c0e5c8f..d3b44a6 100644
--- a/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
@@ -96,9 +96,10 @@
}
}
PAGE_KEYED -> null
- ITEM_KEYED -> state.anchorPosition
- ?.let { anchorPosition -> state.closestItemToPosition(anchorPosition) }
- ?.let { item -> dataSource.getKeyInternal(item) }
+ ITEM_KEYED ->
+ state.anchorPosition
+ ?.let { anchorPosition -> state.closestItemToPosition(anchorPosition) }
+ ?.let { item -> dataSource.getKeyInternal(item) }
}
}
diff --git a/paging/common/src/main/kotlin/androidx/paging/LoadState.kt b/paging/common/src/main/kotlin/androidx/paging/LoadState.kt
index 4f8c10c..d5ff053 100644
--- a/paging/common/src/main/kotlin/androidx/paging/LoadState.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/LoadState.kt
@@ -50,7 +50,7 @@
override fun equals(other: Any?): Boolean {
return other is NotLoading &&
- endOfPaginationReached == other.endOfPaginationReached
+ endOfPaginationReached == other.endOfPaginationReached
}
override fun hashCode(): Int {
@@ -73,7 +73,7 @@
override fun equals(other: Any?): Boolean {
return other is Loading &&
- endOfPaginationReached == other.endOfPaginationReached
+ endOfPaginationReached == other.endOfPaginationReached
}
override fun hashCode(): Int {
@@ -93,8 +93,8 @@
) : LoadState(false) {
override fun equals(other: Any?): Boolean {
return other is Error &&
- endOfPaginationReached == other.endOfPaginationReached &&
- error == other.error
+ endOfPaginationReached == other.endOfPaginationReached &&
+ error == other.error
}
override fun hashCode(): Int {
diff --git a/paging/common/src/main/kotlin/androidx/paging/PageEvent.kt b/paging/common/src/main/kotlin/androidx/paging/PageEvent.kt
index 47bbb74..cbe2120 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PageEvent.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PageEvent.kt
@@ -38,11 +38,11 @@
init {
require(loadType == APPEND || placeholdersBefore >= 0) {
"Append state defining placeholdersBefore must be > 0, but was" +
- " $placeholdersBefore"
+ " $placeholdersBefore"
}
require(loadType == PREPEND || placeholdersAfter >= 0) {
"Prepend state defining placeholdersAfter must be > 0, but was" +
- " $placeholdersAfter"
+ " $placeholdersAfter"
}
}
@@ -178,7 +178,7 @@
init {
require(loadState is LoadState.Loading || loadState is LoadState.Error) {
"LoadStateUpdates can only be used for Loading or Error. To update loadState to " +
- "Idle or Done, use Insert / Drop events."
+ "Idle or Done, use Insert / Drop events."
}
}
}
diff --git a/paging/common/src/main/kotlin/androidx/paging/PageFetcher.kt b/paging/common/src/main/kotlin/androidx/paging/PageFetcher.kt
index afce683..19c7871 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PageFetcher.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PageFetcher.kt
@@ -61,7 +61,7 @@
emit(remoteMediatorAccessor?.initialize() == LAUNCH_INITIAL_REFRESH)
}
.scan(null) { previousGeneration: PageFetcherSnapshot<Key, Value>?,
- triggerRemoteRefresh ->
+ triggerRemoteRefresh ->
var pagingSource = generateNewPagingSource(previousGeneration?.pagingSource)
while (pagingSource.invalid) {
pagingSource = generateNewPagingSource(previousGeneration?.pagingSource)
diff --git a/paging/common/src/main/kotlin/androidx/paging/PageKeyedDataSource.kt b/paging/common/src/main/kotlin/androidx/paging/PageKeyedDataSource.kt
index 910130a..ac773ac 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PageKeyedDataSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PageKeyedDataSource.kt
@@ -195,29 +195,36 @@
private suspend fun loadInitial(params: LoadInitialParams<Key>) =
suspendCancellableCoroutine<BaseResult<Value>> { cont ->
- loadInitial(params, object : LoadInitialCallback<Key, Value>() {
- override fun onResult(
- data: List<Value>,
- position: Int,
- totalCount: Int,
- previousPageKey: Key?,
- nextPageKey: Key?
- ) {
- cont.resume(
- BaseResult(
- data = data,
- prevKey = previousPageKey,
- nextKey = nextPageKey,
- itemsBefore = position,
- itemsAfter = totalCount - data.size - position
+ loadInitial(
+ params,
+ object : LoadInitialCallback<Key, Value>() {
+ override fun onResult(
+ data: List<Value>,
+ position: Int,
+ totalCount: Int,
+ previousPageKey: Key?,
+ nextPageKey: Key?
+ ) {
+ cont.resume(
+ BaseResult(
+ data = data,
+ prevKey = previousPageKey,
+ nextKey = nextPageKey,
+ itemsBefore = position,
+ itemsAfter = totalCount - data.size - position
+ )
)
- )
- }
+ }
- override fun onResult(data: List<Value>, previousPageKey: Key?, nextPageKey: Key?) {
- cont.resume(BaseResult(data, previousPageKey, nextPageKey))
+ override fun onResult(
+ data: List<Value>,
+ previousPageKey: Key?,
+ nextPageKey: Key?
+ ) {
+ cont.resume(BaseResult(data, previousPageKey, nextPageKey))
+ }
}
- })
+ )
}
private suspend fun loadBefore(params: LoadParams<Key>) =
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagedList.kt b/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
index de27969..ddf2ac5c 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
@@ -252,7 +252,7 @@
*/
@Deprecated(
message = "PagedList is deprecated and has been replaced by PagingData, which no " +
- "longer supports constructing snapshots of loaded data manually.",
+ "longer supports constructing snapshots of loaded data manually.",
replaceWith = ReplaceWith("Pager.flow", "androidx.paging.Pager")
)
class Builder<Key : Any, Value : Any> {
@@ -372,7 +372,7 @@
*/
@Deprecated(
message = "Passing an executor will cause it get wrapped as a CoroutineDispatcher, " +
- "consider passing a CoroutineDispatcher directly",
+ "consider passing a CoroutineDispatcher directly",
replaceWith = ReplaceWith(
"setNotifyDispatcher(fetchExecutor.asCoroutineDispatcher())",
"kotlinx.coroutines.asCoroutineDispatcher"
@@ -405,7 +405,7 @@
*/
@Deprecated(
message = "Passing an executor will cause it get wrapped as a CoroutineDispatcher, " +
- "consider passing a CoroutineDispatcher directly",
+ "consider passing a CoroutineDispatcher directly",
replaceWith = ReplaceWith(
"setFetchDispatcher(fetchExecutor.asCoroutineDispatcher())",
"kotlinx.coroutines.asCoroutineDispatcher"
@@ -740,15 +740,15 @@
if (!enablePlaceholders && prefetchDistance == 0) {
throw IllegalArgumentException(
"Placeholders and prefetch are the only ways" +
- " to trigger loading of more data in the PagedList, so either" +
- " placeholders must be enabled, or prefetch distance must be > 0."
+ " to trigger loading of more data in the PagedList, so either" +
+ " placeholders must be enabled, or prefetch distance must be > 0."
)
}
if (maxSize != MAX_SIZE_UNBOUNDED && maxSize < pageSize + prefetchDistance * 2) {
throw IllegalArgumentException(
"Maximum size must be at least pageSize + 2*prefetchDist" +
- ", pageSize=$pageSize, prefetchDist=$prefetchDistance" +
- ", maxSize=$maxSize"
+ ", pageSize=$pageSize, prefetchDist=$prefetchDistance" +
+ ", maxSize=$maxSize"
)
}
@@ -945,8 +945,8 @@
*/
@Deprecated(
message = "DataSource is deprecated and has been replaced by PagingSource. PagedList " +
- "offers indirect ways of controlling fetch ('loadAround()', 'retry()') so that " +
- "you should not need to access the DataSource/PagingSource."
+ "offers indirect ways of controlling fetch ('loadAround()', 'retry()') so that " +
+ "you should not need to access the DataSource/PagingSource."
)
val dataSource: DataSource<*, T>
@Suppress("DocumentExceptions")
@@ -958,7 +958,7 @@
}
throw IllegalStateException(
"Attempt to access dataSource on a PagedList that was instantiated with a " +
- "${pagingSource::class.java.simpleName} instead of a DataSource"
+ "${pagingSource::class.java.simpleName} instead of a DataSource"
)
}
@@ -1169,8 +1169,8 @@
*/
@Deprecated(
"Dispatching a diff since snapshot created is behavior that can be instead " +
- "tracked by attaching a Callback to the PagedList that is mutating, and tracking " +
- "changes since calling PagedList.snapshot()."
+ "tracked by attaching a Callback to the PagedList that is mutating, and tracking " +
+ "changes since calling PagedList.snapshot()."
)
fun addWeakCallback(previousSnapshot: List<T>?, callback: Callback) {
if (previousSnapshot != null && previousSnapshot !== this) {
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagedStorage.kt b/paging/common/src/main/kotlin/androidx/paging/PagedStorage.kt
index c5927cf..cb25e20 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagedStorage.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagedStorage.kt
@@ -26,7 +26,9 @@
* This class only holds data, and does not have any notion of the ideas of async loads, or
* prefetching.
*/
-internal class PagedStorage<T : Any> : AbstractList<T>, LegacyPageFetcher.KeyProvider<Any>,
+internal class PagedStorage<T : Any> :
+ AbstractList<T>,
+ LegacyPageFetcher.KeyProvider<Any>,
NullPaddedList<T> {
private val pages = mutableListOf<Page<*, T>>()
@@ -232,8 +234,8 @@
private fun needsTrim(maxSize: Int, requiredRemaining: Int, localPageIndex: Int): Boolean {
val page = pages[localPageIndex]
return storageCount > maxSize &&
- pages.size > 2 &&
- storageCount - page.data.size >= requiredRemaining
+ pages.size > 2 &&
+ storageCount - page.data.size >= requiredRemaining
}
fun needsTrimFromFront(maxSize: Int, requiredRemaining: Int) =
@@ -244,8 +246,8 @@
fun shouldPreTrimNewPage(maxSize: Int, requiredRemaining: Int, countToBeAdded: Int) =
storageCount + countToBeAdded > maxSize &&
- pages.size > 1 &&
- storageCount >= requiredRemaining
+ pages.size > 1 &&
+ storageCount >= requiredRemaining
internal fun trimFromFront(
insertNulls: Boolean,
@@ -353,5 +355,5 @@
override fun toString(): String =
"leading $placeholdersBefore, storage $storageCount, trailing $placeholdersAfter " +
- pages.joinToString(" ")
+ pages.joinToString(" ")
}
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagingConfig.kt b/paging/common/src/main/kotlin/androidx/paging/PagingConfig.kt
index 544c057..14b74ea 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagingConfig.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagingConfig.kt
@@ -137,15 +137,15 @@
if (!enablePlaceholders && prefetchDistance == 0) {
throw IllegalArgumentException(
"Placeholders and prefetch are the only ways" +
- " to trigger loading of more data in PagingData, so either placeholders" +
- " must be enabled, or prefetch distance must be > 0."
+ " to trigger loading of more data in PagingData, so either placeholders" +
+ " must be enabled, or prefetch distance must be > 0."
)
}
if (maxSize != MAX_SIZE_UNBOUNDED && maxSize < pageSize + prefetchDistance * 2) {
throw IllegalArgumentException(
"Maximum size must be at least pageSize + 2*prefetchDist" +
- ", pageSize=$pageSize, prefetchDist=$prefetchDistance" +
- ", maxSize=$maxSize"
+ ", pageSize=$pageSize, prefetchDist=$prefetchDistance" +
+ ", maxSize=$maxSize"
)
}
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagingDataDiffer.kt b/paging/common/src/main/kotlin/androidx/paging/PagingDataDiffer.kt
index 746fefc..73a049f 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagingDataDiffer.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagingDataDiffer.kt
@@ -178,7 +178,7 @@
event.combinedLoadStates.prepend.endOfPaginationReached
val appendDone = event.combinedLoadStates.append.endOfPaginationReached
val canContinueLoading = !(event.loadType == PREPEND && prependDone) &&
- !(event.loadType == APPEND && appendDone)
+ !(event.loadType == APPEND && appendDone)
if (!canContinueLoading) {
// Reset lastAccessedIndexUnfulfilled since endOfPaginationReached
@@ -187,8 +187,8 @@
} else if (lastAccessedIndexUnfulfilled) {
val shouldResendHint =
lastAccessedIndex < presenter.placeholdersBefore ||
- lastAccessedIndex > presenter.placeholdersBefore +
- presenter.storageCount
+ lastAccessedIndex > presenter.placeholdersBefore +
+ presenter.storageCount
if (shouldResendHint) {
receiver?.accessHint(
@@ -300,7 +300,7 @@
*/
@Deprecated(
"dataRefreshFlow is now redundant with the information passed from loadStateFlow and " +
- "getItemCount, and will be removed in a future alpha version"
+ "getItemCount, and will be removed in a future alpha version"
)
@ExperimentalPagingApi
@OptIn(FlowPreview::class)
@@ -354,7 +354,7 @@
*/
@Deprecated(
"dataRefreshListener is now redundant with the information passed from loadStateListener " +
- "and getItemCount, and will be removed in a future alpha version"
+ "and getItemCount, and will be removed in a future alpha version"
)
@ExperimentalPagingApi
fun addDataRefreshListener(listener: (isEmpty: Boolean) -> Unit) {
@@ -370,7 +370,7 @@
*/
@Deprecated(
"dataRefreshListener is now redundant with the information passed from loadStateListener " +
- "and getItemCount, and will be removed in a future alpha version"
+ "and getItemCount, and will be removed in a future alpha version"
)
@ExperimentalPagingApi
fun removeDataRefreshListener(listener: (isEmpty: Boolean) -> Unit) {
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagingSource.kt b/paging/common/src/main/kotlin/androidx/paging/PagingSource.kt
index dabe6c0..345b7cf 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagingSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagingSource.kt
@@ -105,7 +105,7 @@
*/
@Deprecated(
message = "PagingConfig.pageSize will be removed in future versions, use " +
- "PagingConfig.loadSize instead.",
+ "PagingConfig.loadSize instead.",
replaceWith = ReplaceWith("loadSize")
)
val pageSize: Int = loadSize
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagingState.kt b/paging/common/src/main/kotlin/androidx/paging/PagingState.kt
index acbc715..053cb41 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagingState.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagingState.kt
@@ -48,15 +48,15 @@
override fun equals(other: Any?): Boolean {
return other is PagingState<*, *> &&
- pages == other.pages &&
- anchorPosition == other.anchorPosition &&
- config == other.config &&
- leadingPlaceholderCount == other.leadingPlaceholderCount
+ pages == other.pages &&
+ anchorPosition == other.anchorPosition &&
+ config == other.config &&
+ leadingPlaceholderCount == other.leadingPlaceholderCount
}
override fun hashCode(): Int {
return pages.hashCode() + anchorPosition.hashCode() + config.hashCode() +
- leadingPlaceholderCount.hashCode()
+ leadingPlaceholderCount.hashCode()
}
/**
diff --git a/paging/common/src/main/kotlin/androidx/paging/PositionalDataSource.kt b/paging/common/src/main/kotlin/androidx/paging/PositionalDataSource.kt
index 8b134c2..2804dcd 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PositionalDataSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PositionalDataSource.kt
@@ -347,55 +347,60 @@
@VisibleForTesting
internal suspend fun loadInitial(params: LoadInitialParams) =
suspendCancellableCoroutine<BaseResult<T>> { cont ->
- loadInitial(params, object : LoadInitialCallback<T>() {
- override fun onResult(data: List<T>, position: Int, totalCount: Int) {
- if (isInvalid) {
- // NOTE: this isInvalid check works around
- // https://issuetracker.google.com/issues/124511903
- cont.resume(BaseResult.empty())
- } else {
- val nextKey = position + data.size
- resume(
- params, BaseResult(
- data = data,
- // skip passing prevKey if nothing else to load
- prevKey = if (position == 0) null else position,
- // skip passing nextKey if nothing else to load
- nextKey = if (nextKey == totalCount) null else nextKey,
- itemsBefore = position,
- itemsAfter = totalCount - data.size - position
+ loadInitial(
+ params,
+ object : LoadInitialCallback<T>() {
+ override fun onResult(data: List<T>, position: Int, totalCount: Int) {
+ if (isInvalid) {
+ // NOTE: this isInvalid check works around
+ // https://issuetracker.google.com/issues/124511903
+ cont.resume(BaseResult.empty())
+ } else {
+ val nextKey = position + data.size
+ resume(
+ params,
+ BaseResult(
+ data = data,
+ // skip passing prevKey if nothing else to load
+ prevKey = if (position == 0) null else position,
+ // skip passing nextKey if nothing else to load
+ nextKey = if (nextKey == totalCount) null else nextKey,
+ itemsBefore = position,
+ itemsAfter = totalCount - data.size - position
+ )
)
- )
+ }
}
- }
- override fun onResult(data: List<T>, position: Int) {
- if (isInvalid) {
- // NOTE: this isInvalid check works around
- // https://issuetracker.google.com/issues/124511903
- cont.resume(BaseResult.empty())
- } else {
- resume(
- params, BaseResult(
- data = data,
- // skip passing prevKey if nothing else to load
- prevKey = if (position == 0) null else position,
- // can't do same for nextKey, since we don't know if load is terminal
- nextKey = position + data.size,
- itemsBefore = position,
- itemsAfter = COUNT_UNDEFINED
+ override fun onResult(data: List<T>, position: Int) {
+ if (isInvalid) {
+ // NOTE: this isInvalid check works around
+ // https://issuetracker.google.com/issues/124511903
+ cont.resume(BaseResult.empty())
+ } else {
+ resume(
+ params,
+ BaseResult(
+ data = data,
+ // skip passing prevKey if nothing else to load
+ prevKey = if (position == 0) null else position,
+ // can't do same for nextKey, since we don't know if load is terminal
+ nextKey = position + data.size,
+ itemsBefore = position,
+ itemsAfter = COUNT_UNDEFINED
+ )
)
- )
+ }
}
- }
- private fun resume(params: LoadInitialParams, result: BaseResult<T>) {
- if (params.placeholdersEnabled) {
- result.validateForInitialTiling(params.pageSize)
+ private fun resume(params: LoadInitialParams, result: BaseResult<T>) {
+ if (params.placeholdersEnabled) {
+ result.validateForInitialTiling(params.pageSize)
+ }
+ cont.resume(result)
}
- cont.resume(result)
}
- })
+ )
}
/**
@@ -410,23 +415,26 @@
*/
private suspend fun loadRange(params: LoadRangeParams) =
suspendCancellableCoroutine<BaseResult<T>> { cont ->
- loadRange(params, object : LoadRangeCallback<T>() {
- override fun onResult(data: List<T>) {
- // skip passing prevKey if nothing else to load. We only do this for prepend
- // direction, since 0 as first index is well defined, but max index may not be
- val prevKey = if (params.startPosition == 0) null else params.startPosition
- when {
- isInvalid -> cont.resume(BaseResult.empty())
- else -> cont.resume(
- BaseResult(
- data = data,
- prevKey = prevKey,
- nextKey = params.startPosition + data.size
+ loadRange(
+ params,
+ object : LoadRangeCallback<T>() {
+ override fun onResult(data: List<T>) {
+ // skip passing prevKey if nothing else to load. We only do this for prepend
+ // direction, since 0 as first index is well defined, but max index may not be
+ val prevKey = if (params.startPosition == 0) null else params.startPosition
+ when {
+ isInvalid -> cont.resume(BaseResult.empty())
+ else -> cont.resume(
+ BaseResult(
+ data = data,
+ prevKey = prevKey,
+ nextKey = params.startPosition + data.size
+ )
)
- )
+ }
}
}
- })
+ )
}
/**
diff --git a/paging/common/src/main/kotlin/androidx/paging/Separators.kt b/paging/common/src/main/kotlin/androidx/paging/Separators.kt
index 5154f5b..7c8149b 100644
--- a/paging/common/src/main/kotlin/androidx/paging/Separators.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/Separators.kt
@@ -134,7 +134,7 @@
beforeOffsets != null && afterOffsets == null -> beforeOffsets
else -> throw IllegalArgumentException(
"Separator page expected adjacentPageBefore or adjacentPageAfter, but both were" +
- " null."
+ " null."
)
},
hintOriginalPageOffset = hintOriginalPageOffset,
diff --git a/paging/common/src/main/kotlin/androidx/paging/TransformablePage.kt b/paging/common/src/main/kotlin/androidx/paging/TransformablePage.kt
index a4e378c..0893e16 100644
--- a/paging/common/src/main/kotlin/androidx/paging/TransformablePage.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/TransformablePage.kt
@@ -65,7 +65,7 @@
require(hintOriginalIndices == null || hintOriginalIndices.size == data.size) {
"If originalIndices (size = ${hintOriginalIndices!!.size}) is provided," +
- " it must be same length as data (size = ${data.size})"
+ " it must be same length as data (size = ${data.size})"
}
}
diff --git a/paging/common/src/main/kotlin/androidx/paging/WrapperItemKeyedDataSource.kt b/paging/common/src/main/kotlin/androidx/paging/WrapperItemKeyedDataSource.kt
index 67f7b1e..a4eb776 100644
--- a/paging/common/src/main/kotlin/androidx/paging/WrapperItemKeyedDataSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/WrapperItemKeyedDataSource.kt
@@ -55,31 +55,40 @@
}
override fun loadInitial(params: LoadInitialParams<K>, callback: LoadInitialCallback<B>) {
- source.loadInitial(params, object : LoadInitialCallback<A>() {
- override fun onResult(data: List<A>, position: Int, totalCount: Int) {
- callback.onResult(convertWithStashedKeys(data), position, totalCount)
- }
+ source.loadInitial(
+ params,
+ object : LoadInitialCallback<A>() {
+ override fun onResult(data: List<A>, position: Int, totalCount: Int) {
+ callback.onResult(convertWithStashedKeys(data), position, totalCount)
+ }
- override fun onResult(data: List<A>) {
- callback.onResult(convertWithStashedKeys(data))
+ override fun onResult(data: List<A>) {
+ callback.onResult(convertWithStashedKeys(data))
+ }
}
- })
+ )
}
override fun loadAfter(params: LoadParams<K>, callback: LoadCallback<B>) {
- source.loadAfter(params, object : LoadCallback<A>() {
- override fun onResult(data: List<A>) {
- callback.onResult(convertWithStashedKeys(data))
+ source.loadAfter(
+ params,
+ object : LoadCallback<A>() {
+ override fun onResult(data: List<A>) {
+ callback.onResult(convertWithStashedKeys(data))
+ }
}
- })
+ )
}
override fun loadBefore(params: LoadParams<K>, callback: LoadCallback<B>) {
- source.loadBefore(params, object : LoadCallback<A>() {
- override fun onResult(data: List<A>) {
- callback.onResult(convertWithStashedKeys(data))
+ source.loadBefore(
+ params,
+ object : LoadCallback<A>() {
+ override fun onResult(data: List<A>) {
+ callback.onResult(convertWithStashedKeys(data))
+ }
}
- })
+ )
}
override fun getKey(item: B): K = synchronized(keyMap) {
diff --git a/paging/common/src/main/kotlin/androidx/paging/WrapperPageKeyedDataSource.kt b/paging/common/src/main/kotlin/androidx/paging/WrapperPageKeyedDataSource.kt
index 62b2c94..a886b56 100644
--- a/paging/common/src/main/kotlin/androidx/paging/WrapperPageKeyedDataSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/WrapperPageKeyedDataSource.kt
@@ -35,36 +35,51 @@
override fun invalidate() = source.invalidate()
override fun loadInitial(params: LoadInitialParams<K>, callback: LoadInitialCallback<K, B>) {
- source.loadInitial(params, object : LoadInitialCallback<K, A>() {
- override fun onResult(
- data: List<A>,
- position: Int,
- totalCount: Int,
- previousPageKey: K?,
- nextPageKey: K?
- ) {
- val convertedData = convert(listFunction, data)
- callback.onResult(convertedData, position, totalCount, previousPageKey, nextPageKey)
- }
+ source.loadInitial(
+ params,
+ object : LoadInitialCallback<K, A>() {
+ override fun onResult(
+ data: List<A>,
+ position: Int,
+ totalCount: Int,
+ previousPageKey: K?,
+ nextPageKey: K?
+ ) {
+ val convertedData = convert(listFunction, data)
+ callback.onResult(
+ convertedData,
+ position,
+ totalCount,
+ previousPageKey,
+ nextPageKey
+ )
+ }
- override fun onResult(data: List<A>, previousPageKey: K?, nextPageKey: K?) {
- val convertedData = convert(listFunction, data)
- callback.onResult(convertedData, previousPageKey, nextPageKey)
+ override fun onResult(data: List<A>, previousPageKey: K?, nextPageKey: K?) {
+ val convertedData = convert(listFunction, data)
+ callback.onResult(convertedData, previousPageKey, nextPageKey)
+ }
}
- })
+ )
}
override fun loadBefore(params: LoadParams<K>, callback: LoadCallback<K, B>) {
- source.loadBefore(params, object : LoadCallback<K, A>() {
- override fun onResult(data: List<A>, adjacentPageKey: K?) =
- callback.onResult(convert(listFunction, data), adjacentPageKey)
- })
+ source.loadBefore(
+ params,
+ object : LoadCallback<K, A>() {
+ override fun onResult(data: List<A>, adjacentPageKey: K?) =
+ callback.onResult(convert(listFunction, data), adjacentPageKey)
+ }
+ )
}
override fun loadAfter(params: LoadParams<K>, callback: LoadCallback<K, B>) {
- source.loadAfter(params, object : LoadCallback<K, A>() {
- override fun onResult(data: List<A>, adjacentPageKey: K?) =
- callback.onResult(convert(listFunction, data), adjacentPageKey)
- })
+ source.loadAfter(
+ params,
+ object : LoadCallback<K, A>() {
+ override fun onResult(data: List<A>, adjacentPageKey: K?) =
+ callback.onResult(convert(listFunction, data), adjacentPageKey)
+ }
+ )
}
}
diff --git a/paging/common/src/main/kotlin/androidx/paging/WrapperPositionalDataSource.kt b/paging/common/src/main/kotlin/androidx/paging/WrapperPositionalDataSource.kt
index 8f1c939..799f51c 100644
--- a/paging/common/src/main/kotlin/androidx/paging/WrapperPositionalDataSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/WrapperPositionalDataSource.kt
@@ -35,18 +35,25 @@
override fun invalidate() = source.invalidate()
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<B>) {
- source.loadInitial(params, object : LoadInitialCallback<A>() {
- override fun onResult(data: List<A>, position: Int, totalCount: Int) =
- callback.onResult(convert(listFunction, data), position, totalCount)
+ source.loadInitial(
+ params,
+ object : LoadInitialCallback<A>() {
+ override fun onResult(data: List<A>, position: Int, totalCount: Int) =
+ callback.onResult(convert(listFunction, data), position, totalCount)
- override fun onResult(data: List<A>, position: Int) =
- callback.onResult(convert(listFunction, data), position)
- })
+ override fun onResult(data: List<A>, position: Int) =
+ callback.onResult(convert(listFunction, data), position)
+ }
+ )
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<B>) {
- source.loadRange(params, object : LoadRangeCallback<A>() {
- override fun onResult(data: List<A>) = callback.onResult(convert(listFunction, data))
- })
+ source.loadRange(
+ params,
+ object : LoadRangeCallback<A>() {
+ override fun onResult(data: List<A>) =
+ callback.onResult(convert(listFunction, data))
+ }
+ )
}
}
diff --git a/paging/common/src/test/kotlin/androidx/paging/CachingTest.kt b/paging/common/src/test/kotlin/androidx/paging/CachingTest.kt
index 9a6bf2a..2760e4f 100644
--- a/paging/common/src/test/kotlin/androidx/paging/CachingTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/CachingTest.kt
@@ -314,9 +314,11 @@
onEach?.invoke()
}
.onEach {
- items.addAll(it.pages.flatMap {
- it.data
- })
+ items.addAll(
+ it.pages.flatMap {
+ it.data
+ }
+ )
loadedPageCount += it.pages.size
if (items.size < expectedSize) {
receiver.accessHint(
diff --git a/paging/common/src/test/kotlin/androidx/paging/ContiguousPagedListTest.kt b/paging/common/src/test/kotlin/androidx/paging/ContiguousPagedListTest.kt
index fbcfc83..7681464 100644
--- a/paging/common/src/test/kotlin/androidx/paging/ContiguousPagedListTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/ContiguousPagedListTest.kt
@@ -150,16 +150,16 @@
}
private fun <E : Any> PagedList<E>.addLoadStateCapture(desiredType: LoadType):
- Pair<Any, MutableList<StateChange>> {
- val list = mutableListOf<StateChange>()
- val listener = { type: LoadType, state: LoadState ->
- if (type == desiredType) {
- list.add(StateChange(type, state))
+ Pair<Any, MutableList<StateChange>> {
+ val list = mutableListOf<StateChange>()
+ val listener = { type: LoadType, state: LoadState ->
+ if (type == desiredType) {
+ list.add(StateChange(type, state))
+ }
}
+ addWeakLoadStateListener(listener)
+ return Pair(listener, list)
}
- addWeakLoadStateListener(listener)
- return Pair(listener, list)
- }
private fun verifyRange(start: Int, count: Int, actual: PagedStorage<Item>) {
if (placeholdersEnabled) {
@@ -191,7 +191,7 @@
initialKey: Int,
loadSize: Int,
pageSize:
- Int
+ Int
): Page<Int, Item> = runBlocking {
val result = load(
PagingSource.LoadParams.Refresh(
diff --git a/paging/common/src/test/kotlin/androidx/paging/ItemKeyedDataSourceTest.kt b/paging/common/src/test/kotlin/androidx/paging/ItemKeyedDataSourceTest.kt
index 3ca6467..5448b6d 100644
--- a/paging/common/src/test/kotlin/androidx/paging/ItemKeyedDataSourceTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/ItemKeyedDataSourceTest.kt
@@ -366,31 +366,40 @@
get() = source.isInvalid
override fun loadInitial(params: LoadInitialParams<K>, callback: LoadInitialCallback<B>) {
- source.loadInitial(params, object : LoadInitialCallback<A>() {
- override fun onResult(data: List<A>, position: Int, totalCount: Int) {
- callback.onResult(convert(data), position, totalCount)
- }
+ source.loadInitial(
+ params,
+ object : LoadInitialCallback<A>() {
+ override fun onResult(data: List<A>, position: Int, totalCount: Int) {
+ callback.onResult(convert(data), position, totalCount)
+ }
- override fun onResult(data: List<A>) {
- callback.onResult(convert(data))
+ override fun onResult(data: List<A>) {
+ callback.onResult(convert(data))
+ }
}
- })
+ )
}
override fun loadAfter(params: LoadParams<K>, callback: LoadCallback<B>) {
- source.loadAfter(params, object : LoadCallback<A>() {
- override fun onResult(data: List<A>) {
- callback.onResult(convert(data))
+ source.loadAfter(
+ params,
+ object : LoadCallback<A>() {
+ override fun onResult(data: List<A>) {
+ callback.onResult(convert(data))
+ }
}
- })
+ )
}
override fun loadBefore(params: LoadParams<K>, callback: LoadCallback<B>) {
- source.loadBefore(params, object : LoadCallback<A>() {
- override fun onResult(data: List<A>) {
- callback.onResult(convert(data))
+ source.loadBefore(
+ params,
+ object : LoadCallback<A>() {
+ override fun onResult(data: List<A>) {
+ callback.onResult(convert(data))
+ }
}
- })
+ )
}
protected abstract fun convert(source: List<A>): List<B>
diff --git a/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt b/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
index 1b3ff79..a9e2c3d 100644
--- a/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
@@ -218,7 +218,8 @@
assertEquals(
listOf(
Result(APPEND, rangeResult(6, 8))
- ), consumer.takeResults()
+ ),
+ consumer.takeResults()
)
assertEquals(
@@ -228,7 +229,8 @@
APPEND,
NotLoading(endOfPaginationReached = false)
)
- ), consumer.takeStateChanges()
+ ),
+ consumer.takeStateChanges()
)
pager.tryScheduleAppend()
@@ -237,7 +239,8 @@
assertEquals(
listOf(
Result(APPEND, rangeResult(8, 9))
- ), consumer.takeResults()
+ ),
+ consumer.takeResults()
)
assertEquals(
@@ -263,7 +266,8 @@
assertEquals(
listOf(
Result(PREPEND, rangeResult(2, 4))
- ), consumer.takeResults()
+ ),
+ consumer.takeResults()
)
assertEquals(
@@ -282,7 +286,8 @@
assertEquals(
listOf(
Result(PREPEND, rangeResult(0, 2))
- ), consumer.takeResults()
+ ),
+ consumer.takeResults()
)
assertEquals(
listOf(
diff --git a/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotStateTest.kt b/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotStateTest.kt
index 1966502..3bd282a 100644
--- a/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotStateTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotStateTest.kt
@@ -41,7 +41,8 @@
assertEquals(0, pagerState.placeholdersAfter)
pagerState.insert(
- loadId = 0, loadType = REFRESH, page = Page(
+ loadId = 0, loadType = REFRESH,
+ page = Page(
data = listOf(),
prevKey = -1,
nextKey = 1,
@@ -54,7 +55,8 @@
assertEquals(0, pagerState.placeholdersAfter)
pagerState.insert(
- loadId = 0, loadType = PREPEND, page = Page(
+ loadId = 0, loadType = PREPEND,
+ page = Page(
data = listOf(),
prevKey = -2,
nextKey = 0,
@@ -62,7 +64,8 @@
)
)
pagerState.insert(
- loadId = 0, loadType = APPEND, page = Page(
+ loadId = 0, loadType = APPEND,
+ page = Page(
data = listOf(),
prevKey = 0,
nextKey = 2,
diff --git a/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt b/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
index 81d26e4..73083d8 100644
--- a/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
@@ -3047,7 +3047,8 @@
)
)
val prependHintWithPresenterUpdate = GenerationalViewportHint(
- generationId = 0, hint = ViewportHint(
+ generationId = 0,
+ hint = ViewportHint(
pageOffset = -10,
indexInPage = 0,
presentedItemsBefore = -5,
diff --git a/paging/common/src/test/kotlin/androidx/paging/PageKeyedDataSourceTest.kt b/paging/common/src/test/kotlin/androidx/paging/PageKeyedDataSourceTest.kt
index 5ddb98c..44398e8 100644
--- a/paging/common/src/test/kotlin/androidx/paging/PageKeyedDataSourceTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/PageKeyedDataSourceTest.kt
@@ -340,43 +340,52 @@
params: LoadInitialParams<K>,
callback: LoadInitialCallback<K, B>
) {
- source.loadInitial(params, object : LoadInitialCallback<K, A>() {
- override fun onResult(
- data: List<A>,
- position: Int,
- totalCount: Int,
- previousPageKey: K?,
- nextPageKey: K?
- ) {
- callback.onResult(
- convert(data),
- position,
- totalCount,
- previousPageKey,
- nextPageKey
- )
- }
+ source.loadInitial(
+ params,
+ object : LoadInitialCallback<K, A>() {
+ override fun onResult(
+ data: List<A>,
+ position: Int,
+ totalCount: Int,
+ previousPageKey: K?,
+ nextPageKey: K?
+ ) {
+ callback.onResult(
+ convert(data),
+ position,
+ totalCount,
+ previousPageKey,
+ nextPageKey
+ )
+ }
- override fun onResult(data: List<A>, previousPageKey: K?, nextPageKey: K?) {
- callback.onResult(convert(data), previousPageKey, nextPageKey)
+ override fun onResult(data: List<A>, previousPageKey: K?, nextPageKey: K?) {
+ callback.onResult(convert(data), previousPageKey, nextPageKey)
+ }
}
- })
+ )
}
override fun loadBefore(params: LoadParams<K>, callback: LoadCallback<K, B>) {
- source.loadBefore(params, object : LoadCallback<K, A>() {
- override fun onResult(data: List<A>, adjacentPageKey: K?) {
- callback.onResult(convert(data), adjacentPageKey)
+ source.loadBefore(
+ params,
+ object : LoadCallback<K, A>() {
+ override fun onResult(data: List<A>, adjacentPageKey: K?) {
+ callback.onResult(convert(data), adjacentPageKey)
+ }
}
- })
+ )
}
override fun loadAfter(params: LoadParams<K>, callback: LoadCallback<K, B>) {
- source.loadAfter(params, object : LoadCallback<K, A>() {
- override fun onResult(data: List<A>, adjacentPageKey: K?) {
- callback.onResult(convert(data), adjacentPageKey)
+ source.loadAfter(
+ params,
+ object : LoadCallback<K, A>() {
+ override fun onResult(data: List<A>, adjacentPageKey: K?) {
+ callback.onResult(convert(data), adjacentPageKey)
+ }
}
- })
+ )
}
protected abstract fun convert(source: List<A>): List<B>
@@ -401,7 +410,7 @@
// load initial
@Suppress("UNCHECKED_CAST")
val loadInitialCallback = mock(PageKeyedDataSource.LoadInitialCallback::class.java)
- as PageKeyedDataSource.LoadInitialCallback<String, String>
+ as PageKeyedDataSource.LoadInitialCallback<String, String>
val initParams = PageKeyedDataSource.LoadInitialParams<String>(4, true)
wrapper.loadInitial(initParams, loadInitialCallback)
@@ -415,7 +424,7 @@
@Suppress("UNCHECKED_CAST")
// load after
var loadCallback = mock(PageKeyedDataSource.LoadCallback::class.java)
- as PageKeyedDataSource.LoadCallback<String, String>
+ as PageKeyedDataSource.LoadCallback<String, String>
wrapper.loadAfter(PageKeyedDataSource.LoadParams(expectedInitial.next!!, 4), loadCallback)
val expectedAfter = PAGE_MAP[expectedInitial.next]!!
verify(loadCallback).onResult(expectedAfter.data.map { it.toString() }, expectedAfter.next)
@@ -427,7 +436,7 @@
// load before
@Suppress("UNCHECKED_CAST")
loadCallback = mock(PageKeyedDataSource.LoadCallback::class.java)
- as PageKeyedDataSource.LoadCallback<String, String>
+ as PageKeyedDataSource.LoadCallback<String, String>
wrapper.loadBefore(PageKeyedDataSource.LoadParams(expectedAfter.prev!!, 4), loadCallback)
verify(loadCallback).onResult(
expectedInitial.data.map { it.toString() },
diff --git a/paging/common/src/test/kotlin/androidx/paging/PositionalDataSourceTest.kt b/paging/common/src/test/kotlin/androidx/paging/PositionalDataSourceTest.kt
index bbbab99..97f3f4f 100644
--- a/paging/common/src/test/kotlin/androidx/paging/PositionalDataSourceTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/PositionalDataSourceTest.kt
@@ -49,7 +49,8 @@
@Test
fun computeInitialLoadPositionZero() {
assertEquals(
- 0, computeInitialLoadPos(
+ 0,
+ computeInitialLoadPos(
requestedStartPosition = 0,
requestedLoadSize = 30,
pageSize = 10,
@@ -61,7 +62,8 @@
@Test
fun computeInitialLoadPositionRequestedPositionIncluded() {
assertEquals(
- 10, computeInitialLoadPos(
+ 10,
+ computeInitialLoadPos(
requestedStartPosition = 10,
requestedLoadSize = 10,
pageSize = 10,
@@ -73,7 +75,8 @@
@Test
fun computeInitialLoadPositionRound() {
assertEquals(
- 10, computeInitialLoadPos(
+ 10,
+ computeInitialLoadPos(
requestedStartPosition = 13,
requestedLoadSize = 30,
pageSize = 10,
@@ -85,7 +88,8 @@
@Test
fun computeInitialLoadPositionEndAdjusted() {
assertEquals(
- 70, computeInitialLoadPos(
+ 70,
+ computeInitialLoadPos(
requestedStartPosition = 99,
requestedLoadSize = 30,
pageSize = 10,
@@ -97,7 +101,8 @@
@Test
fun computeInitialLoadPositionEndAdjustedAndAligned() {
assertEquals(
- 70, computeInitialLoadPos(
+ 70,
+ computeInitialLoadPos(
requestedStartPosition = 99,
requestedLoadSize = 35,
pageSize = 10,
@@ -280,23 +285,29 @@
get() = source.isInvalid
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<B>) {
- source.loadInitial(params, object : LoadInitialCallback<A>() {
- override fun onResult(data: List<A>, position: Int, totalCount: Int) {
- callback.onResult(convert(data), position, totalCount)
- }
+ source.loadInitial(
+ params,
+ object : LoadInitialCallback<A>() {
+ override fun onResult(data: List<A>, position: Int, totalCount: Int) {
+ callback.onResult(convert(data), position, totalCount)
+ }
- override fun onResult(data: List<A>, position: Int) {
- callback.onResult(convert(data), position)
+ override fun onResult(data: List<A>, position: Int) {
+ callback.onResult(convert(data), position)
+ }
}
- })
+ )
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<B>) {
- source.loadRange(params, object : LoadRangeCallback<A>() {
- override fun onResult(data: List<A>) {
- callback.onResult(convert(data))
+ source.loadRange(
+ params,
+ object : LoadRangeCallback<A>() {
+ override fun onResult(data: List<A>) {
+ callback.onResult(convert(data))
+ }
}
- })
+ )
}
protected abstract fun convert(source: List<A>): List<B>
@@ -360,7 +371,7 @@
// load initial
@Suppress("UNCHECKED_CAST")
val loadInitialCallback = mock(PositionalDataSource.LoadInitialCallback::class.java)
- as PositionalDataSource.LoadInitialCallback<String>
+ as PositionalDataSource.LoadInitialCallback<String>
val initParams = PositionalDataSource.LoadInitialParams(0, 2, 1, true)
wrapper.loadInitial(initParams, loadInitialCallback)
verify(loadInitialCallback).onResult(listOf("0", "5"), 0, 5)
@@ -372,7 +383,7 @@
// load range
@Suppress("UNCHECKED_CAST")
val loadRangeCallback = mock(PositionalDataSource.LoadRangeCallback::class.java)
- as PositionalDataSource.LoadRangeCallback<String>
+ as PositionalDataSource.LoadRangeCallback<String>
wrapper.loadRange(PositionalDataSource.LoadRangeParams(2, 3), loadRangeCallback)
verify(loadRangeCallback).onResult(listOf("4", "8", "12"))
// load range - error
@@ -443,13 +454,15 @@
@OptIn(ExperimentalCoroutinesApi::class)
private fun verifyRefreshIsTerminal(counted: Boolean): Unit = testScope.runBlockingTest {
val dataSource = ListDataSource(list = listOf(0, 1, 2), counted = counted)
- dataSource.load(DataSource.Params(
- type = LoadType.REFRESH,
- key = 0,
- initialLoadSize = 3,
- placeholdersEnabled = false,
- pageSize = 1
- )).apply {
+ dataSource.load(
+ DataSource.Params(
+ type = LoadType.REFRESH,
+ key = 0,
+ initialLoadSize = 3,
+ placeholdersEnabled = false,
+ pageSize = 1
+ )
+ ).apply {
assertEquals(listOf(0, 1, 2), data)
// prepends always return prevKey = null if they return the first item
assertEquals(null, prevKey)
@@ -457,13 +470,15 @@
assertEquals(if (counted) null else 3, nextKey)
}
- dataSource.load(DataSource.Params(
- type = LoadType.PREPEND,
- key = 1,
- initialLoadSize = 3,
- placeholdersEnabled = false,
- pageSize = 1
- )).apply {
+ dataSource.load(
+ DataSource.Params(
+ type = LoadType.PREPEND,
+ key = 1,
+ initialLoadSize = 3,
+ placeholdersEnabled = false,
+ pageSize = 1
+ )
+ ).apply {
// prepends should return prevKey = null if they return the first item
assertEquals(listOf(0), data)
assertEquals(null, prevKey)
diff --git a/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt b/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt
index 4edaec7..c84d77d 100644
--- a/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt
@@ -582,9 +582,11 @@
combinedLoadStates = localLoadStatesOf()
)
).insertEventSeparators<PrimaryType, Base> { before, after ->
- return@insertEventSeparators (if (before != null && after != null) {
- SeparatorType("B")
- } else null)
+ return@insertEventSeparators (
+ if (before != null && after != null) {
+ SeparatorType("B")
+ } else null
+ )
}.toList()
)
}
diff --git a/paging/common/src/test/kotlin/androidx/paging/SeparatorsWithRemoteMediatorTest.kt b/paging/common/src/test/kotlin/androidx/paging/SeparatorsWithRemoteMediatorTest.kt
index 9a314ab..4118bac 100644
--- a/paging/common/src/test/kotlin/androidx/paging/SeparatorsWithRemoteMediatorTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/SeparatorsWithRemoteMediatorTest.kt
@@ -175,11 +175,13 @@
hintOriginalPageOffset = originalPageOffset,
hintOriginalIndices = data.fold(mutableListOf()) { acc, s ->
acc.apply {
- add(when {
- acc.isEmpty() -> 0
- s.all { it.isUpperCase() } -> acc.last()
- else -> acc.last() + 1
- })
+ add(
+ when {
+ acc.isEmpty() -> 0
+ s.all { it.isUpperCase() } -> acc.last()
+ else -> acc.last() + 1
+ }
+ )
}
}
)
diff --git a/paging/guava/src/test/java/androidx/paging/ListenableFuturePagingDataTest.kt b/paging/guava/src/test/java/androidx/paging/ListenableFuturePagingDataTest.kt
index e7557ab..17ef357 100644
--- a/paging/guava/src/test/java/androidx/paging/ListenableFuturePagingDataTest.kt
+++ b/paging/guava/src/test/java/androidx/paging/ListenableFuturePagingDataTest.kt
@@ -37,27 +37,36 @@
@Test
fun map() = testDispatcher.runBlockingTest {
- val transformed = original.mapAsync(AsyncFunction<String, String> {
- Futures.immediateFuture(it + it)
- }, testDispatcher.asExecutor())
+ val transformed = original.mapAsync(
+ AsyncFunction<String, String> {
+ Futures.immediateFuture(it + it)
+ },
+ testDispatcher.asExecutor()
+ )
differ.collectFrom(transformed)
assertEquals(listOf("aa", "bb", "cc"), differ.currentList)
}
@Test
fun flatMap() = testDispatcher.runBlockingTest {
- val transformed = original.flatMapAsync(AsyncFunction<String, Iterable<String>> {
- Futures.immediateFuture(listOf(it!!, it))
- }, testDispatcher.asExecutor())
+ val transformed = original.flatMapAsync(
+ AsyncFunction<String, Iterable<String>> {
+ Futures.immediateFuture(listOf(it!!, it))
+ },
+ testDispatcher.asExecutor()
+ )
differ.collectFrom(transformed)
assertEquals(listOf("a", "a", "b", "b", "c", "c"), differ.currentList)
}
@Test
fun filter() = testDispatcher.runBlockingTest {
- val filtered = original.filterAsync(AsyncFunction {
- Futures.immediateFuture(it != "b")
- }, testDispatcher.asExecutor())
+ val filtered = original.filterAsync(
+ AsyncFunction {
+ Futures.immediateFuture(it != "b")
+ },
+ testDispatcher.asExecutor()
+ )
differ.collectFrom(filtered)
assertEquals(listOf("a", "c"), differ.currentList)
}
diff --git a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/custom/PagedListSampleActivity.kt b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/custom/PagedListSampleActivity.kt
index a770a7a..c9634cb 100644
--- a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/custom/PagedListSampleActivity.kt
+++ b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/custom/PagedListSampleActivity.kt
@@ -48,8 +48,10 @@
)
@Suppress("DEPRECATION")
- viewModel.livePagedList.observe(this,
- Observer<PagedList<Item>> { pagingAdapter.submitList(it) })
+ viewModel.livePagedList.observe(
+ this,
+ Observer<PagedList<Item>> { pagingAdapter.submitList(it) }
+ )
setupLoadStateButtons(viewModel, pagingAdapter)
diff --git a/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt b/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt
index f37d3da..7aa4945 100644
--- a/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt
+++ b/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt
@@ -149,9 +149,12 @@
val pagedListHolder: Array<PagedList<String>?> = arrayOfNulls(1)
@Suppress("DEPRECATION")
- livePagedList.observe(lifecycleOwner, Observer<PagedList<String>> { newList ->
- pagedListHolder[0] = newList
- })
+ livePagedList.observe(
+ lifecycleOwner,
+ Observer<PagedList<String>> { newList ->
+ pagedListHolder[0] = newList
+ }
+ )
// initially, immediately get passed empty initial list
assertNotNull(pagedListHolder[0])
@@ -185,9 +188,12 @@
val pagedListHolder: Array<PagedList<String>?> = arrayOfNulls(1)
@Suppress("DEPRECATION")
- livePagedList.observe(lifecycleOwner, Observer<PagedList<String>> { newList ->
- pagedListHolder[0] = newList
- })
+ livePagedList.observe(
+ lifecycleOwner,
+ Observer<PagedList<String>> { newList ->
+ pagedListHolder[0] = newList
+ }
+ )
val loadStates = mutableListOf<LoadStateEvent>()
@@ -215,7 +221,8 @@
),
LoadStateEvent(REFRESH, Loading),
LoadStateEvent(REFRESH, Error(EXCEPTION))
- ), loadStates
+ ),
+ loadStates
)
initPagedList.retry()
@@ -236,7 +243,8 @@
LoadStateEvent(REFRESH, Loading),
LoadStateEvent(REFRESH, Error(EXCEPTION)),
LoadStateEvent(REFRESH, Loading)
- ), loadStates
+ ),
+ loadStates
)
// the IDLE result shows up on the next PagedList
diff --git a/paging/runtime/src/main/java/androidx/paging/AsyncPagingDataDiffer.kt b/paging/runtime/src/main/java/androidx/paging/AsyncPagingDataDiffer.kt
index bbd6924..cbeb45a 100644
--- a/paging/runtime/src/main/java/androidx/paging/AsyncPagingDataDiffer.kt
+++ b/paging/runtime/src/main/java/androidx/paging/AsyncPagingDataDiffer.kt
@@ -282,7 +282,7 @@
@Suppress("DEPRECATION")
@Deprecated(
"dataRefreshFlow is now redundant with the information passed from loadStateFlow and " +
- "getItemCount, and will be removed in a future alpha version"
+ "getItemCount, and will be removed in a future alpha version"
)
@ExperimentalPagingApi
val dataRefreshFlow: Flow<Boolean> = differBase.dataRefreshFlow
@@ -297,7 +297,7 @@
*/
@Deprecated(
"dataRefreshListener is now redundant with the information passed from loadStateListener " +
- "and getItemCount, and will be removed in a future alpha version"
+ "and getItemCount, and will be removed in a future alpha version"
)
@ExperimentalPagingApi
fun addDataRefreshListener(listener: (isEmpty: Boolean) -> Unit) {
@@ -314,7 +314,7 @@
*/
@Deprecated(
"dataRefreshListener is now redundant with the information passed from loadStateListener " +
- "and getItemCount, and will be removed in a future alpha version"
+ "and getItemCount, and will be removed in a future alpha version"
)
@ExperimentalPagingApi
fun removeDataRefreshListener(listener: (isEmpty: Boolean) -> Unit) {
diff --git a/paging/runtime/src/main/java/androidx/paging/NullPaddedListDiffHelper.kt b/paging/runtime/src/main/java/androidx/paging/NullPaddedListDiffHelper.kt
index 2488a97..76e92a2 100644
--- a/paging/runtime/src/main/java/androidx/paging/NullPaddedListDiffHelper.kt
+++ b/paging/runtime/src/main/java/androidx/paging/NullPaddedListDiffHelper.kt
@@ -38,41 +38,44 @@
val oldSize = storageCount
val newSize = newList.storageCount
- return DiffUtil.calculateDiff(object : DiffUtil.Callback() {
- override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
- val oldItem = getFromStorage(oldItemPosition)
- val newItem = newList.getFromStorage(newItemPosition)
+ return DiffUtil.calculateDiff(
+ object : DiffUtil.Callback() {
+ override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
+ val oldItem = getFromStorage(oldItemPosition)
+ val newItem = newList.getFromStorage(newItemPosition)
- return when {
- oldItem === newItem -> true
- else -> diffCallback.getChangePayload(oldItem, newItem)
+ return when {
+ oldItem === newItem -> true
+ else -> diffCallback.getChangePayload(oldItem, newItem)
+ }
}
- }
- override fun getOldListSize() = oldSize
+ override fun getOldListSize() = oldSize
- override fun getNewListSize() = newSize
+ override fun getNewListSize() = newSize
- override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
- val oldItem = getFromStorage(oldItemPosition)
- val newItem = newList.getFromStorage(newItemPosition)
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ val oldItem = getFromStorage(oldItemPosition)
+ val newItem = newList.getFromStorage(newItemPosition)
- return when {
- oldItem === newItem -> true
- else -> diffCallback.areItemsTheSame(oldItem, newItem)
+ return when {
+ oldItem === newItem -> true
+ else -> diffCallback.areItemsTheSame(oldItem, newItem)
+ }
}
- }
- override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
- val oldItem = getFromStorage(oldItemPosition)
- val newItem = newList.getFromStorage(newItemPosition)
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ val oldItem = getFromStorage(oldItemPosition)
+ val newItem = newList.getFromStorage(newItemPosition)
- return when {
- oldItem === newItem -> true
- else -> diffCallback.areContentsTheSame(oldItem, newItem)
+ return when {
+ oldItem === newItem -> true
+ else -> diffCallback.areContentsTheSame(oldItem, newItem)
+ }
}
- }
- }, true)
+ },
+ true
+ )
}
private class OffsettingListUpdateCallback internal constructor(
diff --git a/paging/runtime/src/main/java/androidx/paging/PagingDataAdapter.kt b/paging/runtime/src/main/java/androidx/paging/PagingDataAdapter.kt
index 24192c5..bacdc4e 100644
--- a/paging/runtime/src/main/java/androidx/paging/PagingDataAdapter.kt
+++ b/paging/runtime/src/main/java/androidx/paging/PagingDataAdapter.kt
@@ -287,7 +287,7 @@
@Suppress("DEPRECATION")
@Deprecated(
"dataRefreshFlow is now redundant with the information passed from loadStateFlow and " +
- "getItemCount, and will be removed in a future alpha version"
+ "getItemCount, and will be removed in a future alpha version"
)
@ExperimentalPagingApi
val dataRefreshFlow: Flow<Boolean> = differ.dataRefreshFlow
@@ -302,7 +302,7 @@
*/
@Deprecated(
"dataRefreshListener is now redundant with the information passed from loadStateListener " +
- "and getItemCount, and will be removed in a future alpha version"
+ "and getItemCount, and will be removed in a future alpha version"
)
@ExperimentalPagingApi
fun addDataRefreshListener(listener: (isEmpty: Boolean) -> Unit) {
@@ -319,7 +319,7 @@
*/
@Deprecated(
"dataRefreshListener is now redundant with the information passed from loadStateListener " +
- "and getItemCount, and will be removed in a future alpha version"
+ "and getItemCount, and will be removed in a future alpha version"
)
@ExperimentalPagingApi
fun removeDataRefreshListener(listener: (isEmpty: Boolean) -> Unit) {
diff --git a/paging/rxjava2/src/main/java/androidx/paging/rxjava2/RxRemoteMediator.kt b/paging/rxjava2/src/main/java/androidx/paging/rxjava2/RxRemoteMediator.kt
index dee83d5..e9cc0d4 100644
--- a/paging/rxjava2/src/main/java/androidx/paging/rxjava2/RxRemoteMediator.kt
+++ b/paging/rxjava2/src/main/java/androidx/paging/rxjava2/RxRemoteMediator.kt
@@ -84,9 +84,9 @@
open fun initializeSingle(): Single<InitializeAction> = Single.just(LAUNCH_INITIAL_REFRESH)
final override suspend fun load(loadType: LoadType, state: PagingState<Key, Value>):
- MediatorResult {
- return loadSingle(loadType, state).await()
- }
+ MediatorResult {
+ return loadSingle(loadType, state).await()
+ }
final override suspend fun initialize(): InitializeAction {
return initializeSingle().await()
diff --git a/paging/rxjava2/src/test/java/androidx/paging/RxPagedListBuilderTest.kt b/paging/rxjava2/src/test/java/androidx/paging/RxPagedListBuilderTest.kt
index d944adb..8708e51 100644
--- a/paging/rxjava2/src/test/java/androidx/paging/RxPagedListBuilderTest.kt
+++ b/paging/rxjava2/src/test/java/androidx/paging/RxPagedListBuilderTest.kt
@@ -203,7 +203,8 @@
assertEquals(
listOf(
LoadStateEvent(REFRESH, Loading)
- ), loadStates
+ ),
+ loadStates
)
fetchScheduler.triggerActions()
@@ -214,7 +215,8 @@
listOf(
LoadStateEvent(REFRESH, Loading),
LoadStateEvent(REFRESH, Error(EXCEPTION))
- ), loadStates
+ ),
+ loadStates
)
initPagedList.retry()
@@ -226,7 +228,8 @@
LoadStateEvent(REFRESH, Loading),
LoadStateEvent(REFRESH, Error(EXCEPTION)),
LoadStateEvent(REFRESH, Loading)
- ), loadStates
+ ),
+ loadStates
)
// flush loadInitial, should succeed now
fetchScheduler.triggerActions()
@@ -248,7 +251,8 @@
REFRESH,
NotLoading(endOfPaginationReached = false)
)
- ), loadStates
+ ),
+ loadStates
)
}
diff --git a/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxRemoteMediator.kt b/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxRemoteMediator.kt
index 1d65a7f..942bedf 100644
--- a/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxRemoteMediator.kt
+++ b/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxRemoteMediator.kt
@@ -83,9 +83,9 @@
open fun initializeSingle(): Single<InitializeAction> = Single.just(LAUNCH_INITIAL_REFRESH)
final override suspend fun load(loadType: LoadType, state: PagingState<Key, Value>):
- MediatorResult {
- return loadSingle(loadType, state).await()
- }
+ MediatorResult {
+ return loadSingle(loadType, state).await()
+ }
final override suspend fun initialize(): InitializeAction {
return initializeSingle().await()
diff --git a/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt
index 27cfb29..145160c 100644
--- a/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt
+++ b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt
@@ -103,17 +103,23 @@
*/
pagingDataStream.map { pagingData ->
// map outer stream, so we can perform transformations on each paging generation
- pagingData.insertSeparatorsAsync(AsyncFunction<AdjacentItems<String>, String?> {
- Futures.submit(Callable<String?> {
- val (before, after) = it!!
- if (after != null && before?.first() != after.first()) {
- // separator - after is first item that starts with its first letter
- after.first().toUpperCase().toString()
- } else {
- // no separator - either end of list, or first letters of before/after are the same
- null
- }
- }, executor)
- }, executor)
+ pagingData.insertSeparatorsAsync(
+ AsyncFunction<AdjacentItems<String>, String?> {
+ Futures.submit(
+ Callable<String?> {
+ val (before, after) = it!!
+ if (after != null && before?.first() != after.first()) {
+ // separator - after is first item that starts with its first letter
+ after.first().toUpperCase().toString()
+ } else {
+ // no separator - either end of list, or first letters of before/after are the same
+ null
+ }
+ },
+ executor
+ )
+ },
+ executor
+ )
}
}
diff --git a/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt
index 0f90965..76b6c6c 100644
--- a/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt
+++ b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt
@@ -135,17 +135,25 @@
.map { item ->
ItemUiModel(item) // convert items in stream to ItemUiModel
}
- .insertSeparatorsAsync(AsyncFunction<AdjacentItems<ItemUiModel>, UiModel?> {
- Futures.submit(Callable<UiModel> {
- val (before, after) = it!!
- if (after != null && before?.item?.label?.first() != after.item.label.first()) {
- // separator - after is first item that starts with its first letter
- SeparatorUiModel(after.item.label.first().toUpperCase())
- } else {
- // no separator - either end of list, or first letters of before/after are the same
- null
- }
- }, executor)
- }, executor)
+ .insertSeparatorsAsync(
+ AsyncFunction<AdjacentItems<ItemUiModel>, UiModel?> {
+ Futures.submit(
+ Callable<UiModel> {
+ val (before, after) = it!!
+ if (after != null &&
+ before?.item?.label?.first() != after.item.label.first()
+ ) {
+ // separator - after is first item that starts with its first letter
+ SeparatorUiModel(after.item.label.first().toUpperCase())
+ } else {
+ // no separator - either end of list, or first letters of before/after are the same
+ null
+ }
+ },
+ executor
+ )
+ },
+ executor
+ )
}
}
diff --git a/playground-common/playground.properties b/playground-common/playground.properties
index b3f8a1f..0727968 100644
--- a/playground-common/playground.properties
+++ b/playground-common/playground.properties
@@ -28,7 +28,7 @@
androidx.enableDocumentation=false
# Disable coverage
androidx.coverageEnabled=false
-androidx.playground.snapshotBuildId=6878660
+androidx.playground.snapshotBuildId=6890839
androidx.playground.metalavaBuildId=6879116
androidx.playground.dokkaBuildId=6852039
androidx.studio.type=playground
diff --git a/preference/preference-ktx/src/androidTest/java/androidx/preference/PreferenceGroupTest.kt b/preference/preference-ktx/src/androidTest/java/androidx/preference/PreferenceGroupTest.kt
index 7c2c2da..2ad2bf3 100644
--- a/preference/preference-ktx/src/androidTest/java/androidx/preference/PreferenceGroupTest.kt
+++ b/preference/preference-ktx/src/androidTest/java/androidx/preference/PreferenceGroupTest.kt
@@ -45,7 +45,7 @@
@UiThreadTest
fun setup() {
preferenceGroup =
- rule.activity.setupPreferenceHierarchy(R.xml.test_preferencegroup).preferenceScreen
+ rule.activity.setupPreferenceHierarchy(R.xml.test_preferencegroup).preferenceScreen
}
@UiThreadTest
diff --git a/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceFragmentCompatInterfaceTest.kt b/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceFragmentCompatInterfaceTest.kt
index 0a622ef..4f60ae0 100644
--- a/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceFragmentCompatInterfaceTest.kt
+++ b/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceFragmentCompatInterfaceTest.kt
@@ -315,7 +315,8 @@
}
}
-class WithInterfaceTestActivity : NoInterfaceTestActivity(),
+class WithInterfaceTestActivity :
+ NoInterfaceTestActivity(),
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback,
PreferenceFragmentCompat.OnPreferenceStartScreenCallback,
PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {
diff --git a/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceViewHolderStateTest.kt b/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceViewHolderStateTest.kt
index ff857640..b096df4 100644
--- a/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceViewHolderStateTest.kt
+++ b/preference/preference/src/androidTest/java/androidx/preference/tests/PreferenceViewHolderStateTest.kt
@@ -158,11 +158,13 @@
// Scroll until the end, ensuring all Preferences have been bound.
onView(withId(R.id.recycler_view))
- .perform(repeatedlyUntil(
- swipeUp(),
- hasDescendant(withText("${disabledTitle}40")),
- maxAttempts
- ))
+ .perform(
+ repeatedlyUntil(
+ swipeUp(),
+ hasDescendant(withText("${disabledTitle}40")),
+ maxAttempts
+ )
+ )
// All preferences should have the correct title color
preferences.forEach { preference ->
diff --git a/preference/preference/src/androidTest/java/androidx/preference/tests/SeekBarPreferenceTest.kt b/preference/preference/src/androidTest/java/androidx/preference/tests/SeekBarPreferenceTest.kt
index ebbf6db..5e994bc 100644
--- a/preference/preference/src/androidTest/java/androidx/preference/tests/SeekBarPreferenceTest.kt
+++ b/preference/preference/src/androidTest/java/androidx/preference/tests/SeekBarPreferenceTest.kt
@@ -245,7 +245,8 @@
* A [ViewAction] that drags a [SeekBar] from its left edge to the right edge of the screen
*/
private fun dragSeekBar(): ViewAction {
- return GeneralSwipeAction(Swipe.FAST,
+ return GeneralSwipeAction(
+ Swipe.FAST,
CoordinatesProvider { view ->
val location = IntArray(2)
view.getLocationOnScreen(location)
@@ -253,7 +254,8 @@
val posY = location[1]
// Start at the beginning of the seekbar
floatArrayOf(posX.toFloat(), posY.toFloat())
- }, CoordinatesProvider { view ->
+ },
+ CoordinatesProvider { view ->
val location = IntArray(2)
view.getLocationOnScreen(location)
// We want to swipe all the way to the right edge of the screen to avoid
@@ -264,7 +266,8 @@
val posX = metrics.widthPixels
val posY = location[1]
floatArrayOf(posX.toFloat(), posY.toFloat())
- }, Press.PINPOINT
+ },
+ Press.PINPOINT
)
}
diff --git a/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/DiffBenchmark.kt b/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/DiffBenchmark.kt
index 3e93979..1f997a5 100644
--- a/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/DiffBenchmark.kt
+++ b/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/DiffBenchmark.kt
@@ -136,8 +136,8 @@
}
override fun toString() = name +
- "_dispatchUpdates_$dispatchUpdates" +
- "_detectMoves_$detectMoves" +
- "_size_[${before.size}_${after.size}]"
+ "_dispatchUpdates_$dispatchUpdates" +
+ "_detectMoves_$detectMoves" +
+ "_size_[${before.size}_${after.size}]"
}
}
\ No newline at end of file
diff --git a/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/RecyclerViewActivity.kt b/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/RecyclerViewActivity.kt
index 30054b8..a75d40e 100644
--- a/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/RecyclerViewActivity.kt
+++ b/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/RecyclerViewActivity.kt
@@ -27,9 +27,10 @@
val recyclerView: RecyclerView by lazy {
RecyclerView(this).apply {
layoutManager = LinearLayoutManager(
- this@RecyclerViewActivity,
- RecyclerView.VERTICAL,
- false)
+ this@RecyclerViewActivity,
+ RecyclerView.VERTICAL,
+ false
+ )
layoutParams = FrameLayout.LayoutParams(100, 100)
}
}
diff --git a/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/ScrollBenchmark.kt b/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/ScrollBenchmark.kt
index 8a87443..524455f31 100644
--- a/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/ScrollBenchmark.kt
+++ b/recyclerview/recyclerview-benchmark/src/androidTest/java/androidx/recyclerview/benchmark/ScrollBenchmark.kt
@@ -133,7 +133,8 @@
var inflater: (ViewGroup) -> View = {
LayoutInflater.from(it.context).inflate(
- R.layout.item_view, it, false)
+ R.layout.item_view, it, false
+ )
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TrivialViewHolder {
diff --git a/recyclerview/recyclerview-lint/src/test/java/androidx/recyclerview/lint/InvalidSetHasFixedSizeTest.kt b/recyclerview/recyclerview-lint/src/test/java/androidx/recyclerview/lint/InvalidSetHasFixedSizeTest.kt
index 369b46a..33af63c 100644
--- a/recyclerview/recyclerview-lint/src/test/java/androidx/recyclerview/lint/InvalidSetHasFixedSizeTest.kt
+++ b/recyclerview/recyclerview-lint/src/test/java/androidx/recyclerview/lint/InvalidSetHasFixedSizeTest.kt
@@ -28,7 +28,8 @@
@Test
fun testCorrectUseOfHasFixedSize() {
val resourceIds = kotlin(
- "com/example/R.kt", """
+ "com/example/R.kt",
+ """
package com.example
object R {
@@ -40,7 +41,8 @@
).indented().within("src")
val source = kotlin(
- "com/example/Example.kt", """
+ "com/example/Example.kt",
+ """
package com.example
import android.view.View
@@ -83,7 +85,8 @@
@Test
fun testCorrectUseOfHasFixedSize2() {
val resourceIds = kotlin(
- "com/example/R.kt", """
+ "com/example/R.kt",
+ """
package com.example
object R {
@@ -95,7 +98,8 @@
).indented().within("src")
val source = kotlin(
- "com/example/Example.kt", """
+ "com/example/Example.kt",
+ """
package com.example
import android.view.View
@@ -140,7 +144,8 @@
@Test
fun testInCorrectUsageOfFixedSize() {
val resourceIds = kotlin(
- "com/example/R.kt", """
+ "com/example/R.kt",
+ """
package com.example
object R {
@@ -152,7 +157,8 @@
).indented().within("src")
val source = kotlin(
- "com/example/Example.kt", """
+ "com/example/Example.kt",
+ """
package com.example
import android.view.View
@@ -190,19 +196,22 @@
.issues(InvalidSetHasFixedSizeDetector.ISSUE)
.run()
/* ktlint-disable max-line-length */
- .expect("""
+ .expect(
+ """
src/com/example/Example.kt:10: Error: When using `setHasFixedSize() in an RecyclerView, wrap_content cannot be used as a value for size in the scrolling direction. [InvalidSetHasFixedSize]
recyclerView?.setHasFixedSize(true)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 errors, 0 warnings
- """.trimIndent())
- /* ktlint-enable max-line-length */
+ """.trimIndent()
+ )
+ /* ktlint-enable max-line-length */
}
@Test
fun testInCorrectUsageOfFixedSize2() {
val resourceIds = kotlin(
- "com/example/R.kt", """
+ "com/example/R.kt",
+ """
package com.example
object R {
@@ -214,7 +223,8 @@
).indented().within("src")
val source = kotlin(
- "com/example/Example.kt", """
+ "com/example/Example.kt",
+ """
package com.example
import android.view.View
@@ -253,19 +263,22 @@
.issues(InvalidSetHasFixedSizeDetector.ISSUE)
.run()
/* ktlint-disable max-line-length */
- .expect("""
+ .expect(
+ """
src/com/example/Example.kt:10: Error: When using `setHasFixedSize() in an RecyclerView, wrap_content cannot be used as a value for size in the scrolling direction. [InvalidSetHasFixedSize]
recyclerView?.setHasFixedSize(true)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 errors, 0 warnings
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
}
@Test
fun testInCorrectUseOfHasFixedSize3() {
val resourceIds = kotlin(
- "com/example/R.kt", """
+ "com/example/R.kt",
+ """
package com.example
object R {
@@ -277,7 +290,8 @@
).indented().within("src")
val source = kotlin(
- "com/example/Example.kt", """
+ "com/example/Example.kt",
+ """
package com.example
import android.view.View
@@ -319,12 +333,14 @@
.issues(InvalidSetHasFixedSizeDetector.ISSUE)
.run()
/* ktlint-disable max-line-length */
- .expect("""
+ .expect(
+ """
src/com/example/Example.kt:14: Error: When using `setHasFixedSize() in an RecyclerView, wrap_content cannot be used as a value for size in the scrolling direction. [InvalidSetHasFixedSize]
recyclerView?.setHasFixedSize(true)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 errors, 0 warnings
- """.trimIndent())
- /* ktlint-enable max-line-length */
+ """.trimIndent()
+ )
+ /* ktlint-enable max-line-length */
}
}
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/AsyncListDifferTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/AsyncListDifferTest.kt
index 82a8861..f61999b 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/AsyncListDifferTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/AsyncListDifferTest.kt
@@ -42,11 +42,13 @@
private fun createDiffer(
listUpdateCallback: ListUpdateCallback = IGNORE_CALLBACK
): AsyncListDiffer<String> {
- return AsyncListDiffer(listUpdateCallback,
- AsyncDifferConfig.Builder(STRING_DIFF_CALLBACK)
- .setMainThreadExecutor(mMainThread)
- .setBackgroundThreadExecutor(mBackgroundThread)
- .build())
+ return AsyncListDiffer(
+ listUpdateCallback,
+ AsyncDifferConfig.Builder(STRING_DIFF_CALLBACK)
+ .setMainThreadExecutor(mMainThread)
+ .setBackgroundThreadExecutor(mBackgroundThread)
+ .build()
+ )
}
@Test
@@ -293,7 +295,7 @@
@Suppress("UNCHECKED_CAST")
val listener = mock(AsyncListDiffer.ListListener::class.java)
- as AsyncListDiffer.ListListener<String>
+ as AsyncListDiffer.ListListener<String>
differ.addListListener(listener)
val callback = mock(Runnable::class.java)
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterSubject.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterSubject.kt
index d793794..e18b094 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterSubject.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterSubject.kt
@@ -99,12 +99,12 @@
object Factory : Subject.Factory<ConcatAdapterSubject, ConcatAdapter> {
override fun createSubject(metadata: FailureMetadata, actual: ConcatAdapter):
- ConcatAdapterSubject {
- return ConcatAdapterSubject(
- metadata = metadata,
- adapter = actual
- )
- }
+ ConcatAdapterSubject {
+ return ConcatAdapterSubject(
+ metadata = metadata,
+ adapter = actual
+ )
+ }
}
companion object {
@@ -144,13 +144,13 @@
metadata: FailureMetadata,
globalPosition: Int
):
- BindingSubject {
- return BindingSubject(
- metadata = metadata,
- recyclerView = recyclerView,
- globalPosition = globalPosition
- )
- }
+ BindingSubject {
+ return BindingSubject(
+ metadata = metadata,
+ recyclerView = recyclerView,
+ globalPosition = globalPosition
+ )
+ }
}
}
}
\ No newline at end of file
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterTest.kt
index ac0d412..01619d2 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterTest.kt
@@ -82,10 +82,12 @@
@Test
fun attachAndDetachAll() {
val concatenated = ConcatAdapter()
- val adapter1 = NestedTestAdapter(10,
+ val adapter1 = NestedTestAdapter(
+ 10,
getLayoutParams = {
LayoutParams(MATCH_PARENT, 3)
- })
+ }
+ )
concatenated.addAdapter(adapter1)
recyclerView.adapter = concatenated
measureAndLayout(100, 50)
@@ -95,10 +97,12 @@
assertThat(recyclerView.childCount).isEqualTo(0)
assertThat(adapter1.attachedViewHolders()).isEmpty()
- val adapter2 = NestedTestAdapter(5,
+ val adapter2 = NestedTestAdapter(
+ 5,
getLayoutParams = {
LayoutParams(MATCH_PARENT, 3)
- })
+ }
+ )
concatenated.addAdapter(adapter2)
assertThat(recyclerView.isLayoutRequested).isTrue()
measureAndLayout(100, 200)
@@ -953,12 +957,12 @@
val excludedMethods = setOf(
"registerAdapterDataObserver(" +
- "[androidx.recyclerview.widget.RecyclerView.AdapterDataObserver]) : void",
+ "[androidx.recyclerview.widget.RecyclerView.AdapterDataObserver]) : void",
"unregisterAdapterDataObserver(" +
- "[androidx.recyclerview.widget.RecyclerView.AdapterDataObserver]) : void",
+ "[androidx.recyclerview.widget.RecyclerView.AdapterDataObserver]) : void",
"canRestoreState([]) : boolean",
"onBindViewHolder([androidx.recyclerview.widget.RecyclerView.ViewHolder, int, " +
- "java.util.List]) : void"
+ "java.util.List]) : void"
)
val adapterMethods = RecyclerView.Adapter::class.java.declaredMethods.filterNot {
Modifier.isPrivate(it.modifiers) || Modifier.isFinal(it.modifiers)
@@ -974,7 +978,7 @@
"""
ConcatAdapter should override all methods in RecyclerView.Adapter for future
compatibility. If you want to exclude a method, update the test.
- """.trimIndent()
+ """.trimIndent()
).that(concatenatedAdapterMethods).containsAtLeastElementsIn(adapterMethods)
}
@@ -1000,7 +1004,8 @@
val concatenated = ConcatAdapter(
Builder()
.setIsolateViewTypes(false)
- .build(), adapter1, adapter2
+ .build(),
+ adapter1, adapter2
)
assertThat(concatenated).bindView(recyclerView, 2)
.verifyBoundTo(adapter1, 2)
@@ -1029,7 +1034,8 @@
val concatenated = ConcatAdapter(
Builder()
.setIsolateViewTypes(false)
- .build(), adapter1, adapter2
+ .build(),
+ adapter1, adapter2
)
assertThat(concatenated).bindView(recyclerView, 0)
.verifyBoundTo(adapter1, 0)
@@ -1062,12 +1068,14 @@
)
assertThat(concatenatedAdapter).hasStableIds()
assertThat(concatenatedAdapter).throwsException {
- it.addAdapter(NestedTestAdapter(10).also { nested ->
- nested.setHasStableIds(false)
- })
+ it.addAdapter(
+ NestedTestAdapter(10).also { nested ->
+ nested.setHasStableIds(false)
+ }
+ )
}.hasMessageThat().contains(
"All sub adapters must have stable ids when stable id mode" +
- " is ISOLATED_STABLE_IDS or SHARED_STABLE_IDS"
+ " is ISOLATED_STABLE_IDS or SHARED_STABLE_IDS"
)
}
@@ -1078,12 +1086,14 @@
)
assertThat(concatenatedAdapter).hasStableIds()
assertThat(concatenatedAdapter).throwsException {
- it.addAdapter(NestedTestAdapter(10).also { nested ->
- nested.setHasStableIds(false)
- })
+ it.addAdapter(
+ NestedTestAdapter(10).also { nested ->
+ nested.setHasStableIds(false)
+ }
+ )
}.hasMessageThat().contains(
"All sub adapters must have stable ids when stable id mode" +
- " is ISOLATED_STABLE_IDS or SHARED_STABLE_IDS"
+ " is ISOLATED_STABLE_IDS or SHARED_STABLE_IDS"
)
}
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearLayoutManagerRemoveShownItemsTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearLayoutManagerRemoveShownItemsTest.kt
index f3540ad..3d907a4 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearLayoutManagerRemoveShownItemsTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearLayoutManagerRemoveShownItemsTest.kt
@@ -173,9 +173,11 @@
mLayoutManager.waitForLayout(2)
// .. when we remove all laid out items ..
- val removeFrom = llm.run { List(childCount) {
- getPosition(getChildAt(it)!!)
- }.minOrNull() }!!
+ val removeFrom = llm.run {
+ List(childCount) {
+ getPosition(getChildAt(it)!!)
+ }.minOrNull()
+ }!!
mLayoutManager.expectLayouts(2)
mTestAdapter.deleteAndNotify(removeFrom, llm.childCount)
mLayoutManager.waitForLayout(2)
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearSnapHelperCenterTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearSnapHelperCenterTest.kt
index e07f889..ac974a6 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearSnapHelperCenterTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearSnapHelperCenterTest.kt
@@ -34,7 +34,9 @@
startPadded: Boolean,
endPadded: Boolean,
clipToPadding: Boolean
-) : BaseSnapHelperCenterTest(vertical, startPadded, endPadded,
- clipToPadding) {
+) : BaseSnapHelperCenterTest(
+ vertical, startPadded, endPadded,
+ clipToPadding
+) {
override val snapHelper = LinearSnapHelper()
}
\ No newline at end of file
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ListAdapterTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ListAdapterTest.kt
index 53d1342..2c7e135 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ListAdapterTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ListAdapterTest.kt
@@ -69,7 +69,7 @@
fun initialState() {
@Suppress("UNCHECKED_CAST")
val listener = mock(AsyncListDiffer.ListListener::class.java)
- as AsyncListDiffer.ListListener<String>
+ as AsyncListDiffer.ListListener<String>
val adapter = Adapter(listener)
assertEquals(0, adapter.itemCount)
@@ -108,7 +108,7 @@
val callback = mock(Runnable::class.java)
@Suppress("UNCHECKED_CAST")
val listener = mock(AsyncListDiffer.ListListener::class.java)
- as AsyncListDiffer.ListListener<String>
+ as AsyncListDiffer.ListListener<String>
val adapter = Adapter(listener)
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewMeasureTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewMeasureTest.kt
index 46b5e92..473da05 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewMeasureTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewMeasureTest.kt
@@ -56,10 +56,10 @@
@JvmStatic
@Parameterized.Parameters(
name = "childWidth = {0}, childHeight = {1}, firstWidthMode = {2}, firstWidth = {3}, " +
- "firstHeightMode = {4}, firstHeight = {5}, secondWidthMode = {6}, " +
- "secondWidth = {7}, secondHeightMode = {8}, secondHeight = {9}, " +
- "expectedWidthMode = {10}, expectedWidth = {11}, expectedHeightMode = {12}, " +
- "expectedHeight = {13}"
+ "firstHeightMode = {4}, firstHeight = {5}, secondWidthMode = {6}, " +
+ "secondWidth = {7}, secondHeightMode = {8}, secondHeight = {9}, " +
+ "expectedWidthMode = {10}, expectedWidth = {11}, expectedHeightMode = {12}, " +
+ "expectedHeight = {13}"
)
fun data(): List<Array<Any>> {
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingFlingTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingFlingTest.kt
index c85bf36..6954bc2 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingFlingTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingFlingTest.kt
@@ -59,7 +59,8 @@
@Rule
@JvmField
val mActivityResetRule: ActivityScenarioResetRule<TestActivity> = TestActivity.ResetRule(
- mActivityRule.scenario)
+ mActivityRule.scenario
+ )
@Before
@Throws(Throwable::class)
@@ -151,10 +152,10 @@
val up = MotionEvent.obtain(0, elapsedTime, MotionEvent.ACTION_UP, x3, y3, 0)
mActivityRule.runOnUiThread {
- mNestedScrollingParent.dispatchTouchEvent(down)
- mNestedScrollingParent.dispatchTouchEvent(move1)
- mNestedScrollingParent.dispatchTouchEvent(move2)
- mNestedScrollingParent.dispatchTouchEvent(up)
+ mNestedScrollingParent.dispatchTouchEvent(down)
+ mNestedScrollingParent.dispatchTouchEvent(move1)
+ mNestedScrollingParent.dispatchTouchEvent(move2)
+ mNestedScrollingParent.dispatchTouchEvent(up)
}
val (expected, errorRange) =
@@ -173,8 +174,10 @@
)
}
- inner class NestedScrollingParent(context: Context) : FrameLayout(context),
- NestedScrollingChild3, NestedScrollingParent3 {
+ inner class NestedScrollingParent(context: Context) :
+ FrameLayout(context),
+ NestedScrollingChild3,
+ NestedScrollingParent3 {
var preScrollX: Int = 0
var postScrollX: Int = 0
@@ -424,10 +427,10 @@
@JvmStatic
@Parameterized.Parameters(
name = "orientationVertical:{0}, " +
- "scrollDirectionForward:{1}, " +
- "rvIntercepts:{2}, " +
- "preScrollConsumption:{3}, " +
- "postScrollConsumption:{4}"
+ "scrollDirectionForward:{1}, " +
+ "rvIntercepts:{2}, " +
+ "preScrollConsumption:{3}, " +
+ "postScrollConsumption:{4}"
)
fun data(): Collection<Array<Any>> {
val configurations = ArrayList<Array<Any>>()
@@ -443,55 +446,64 @@
rvIntercepts,
0,
0
- ), arrayOf(
+ ),
+ arrayOf(
orientationVertical,
scrollDirectionForward,
rvIntercepts,
25,
0
- ), arrayOf(
+ ),
+ arrayOf(
orientationVertical,
scrollDirectionForward,
rvIntercepts,
50,
0
- ), arrayOf(
+ ),
+ arrayOf(
orientationVertical,
scrollDirectionForward,
rvIntercepts,
100,
0
- ), arrayOf(
+ ),
+ arrayOf(
orientationVertical,
scrollDirectionForward,
rvIntercepts,
0,
25
- ), arrayOf(
+ ),
+ arrayOf(
orientationVertical,
scrollDirectionForward,
rvIntercepts,
0,
50
- ), arrayOf(
+ ),
+ arrayOf(
orientationVertical,
scrollDirectionForward,
rvIntercepts,
0,
100
- ), arrayOf(
+ ),
+ arrayOf(
orientationVertical,
scrollDirectionForward,
rvIntercepts,
12,
13
- ), arrayOf(
+ ),
+ arrayOf(
orientationVertical,
scrollDirectionForward,
rvIntercepts,
25,
25
- ), arrayOf(
+ ),
+ arrayOf(
orientationVertical,
scrollDirectionForward,
rvIntercepts,
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewSmoothScrollToPositionTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewSmoothScrollToPositionTest.kt
index 950031d..dcfcbd6 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewSmoothScrollToPositionTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewSmoothScrollToPositionTest.kt
@@ -140,11 +140,13 @@
// Act
- BaseRecyclerViewInstrumentationTest.mActivityRule.runOnUiThread(Runnable {
- recyclerView.smoothScrollToPosition(
- targetPosition
- )
- })
+ BaseRecyclerViewInstrumentationTest.mActivityRule.runOnUiThread(
+ Runnable {
+ recyclerView.smoothScrollToPosition(
+ targetPosition
+ )
+ }
+ )
// Assert
diff --git a/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt b/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt
index fbd8e60..5114f04 100644
--- a/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt
+++ b/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt
@@ -60,7 +60,7 @@
LOG:
$log
END_LOG
- """.trimIndent()
+ """.trimIndent()
)
}
}
diff --git a/room/common/src/test/java/androidx/room/AnnotationRetentionPolicyTest.kt b/room/common/src/test/java/androidx/room/AnnotationRetentionPolicyTest.kt
index 5d9f646..09a2707 100644
--- a/room/common/src/test/java/androidx/room/AnnotationRetentionPolicyTest.kt
+++ b/room/common/src/test/java/androidx/room/AnnotationRetentionPolicyTest.kt
@@ -37,7 +37,7 @@
val retentionPolicy = it.getAnnotation(java.lang.annotation.Retention::class.java).value
assert(retentionPolicy == RetentionPolicy.CLASS) {
"Expected ${it.name} annotation to have retention policy CLASS" +
- " but it is $retentionPolicy"
+ " but it is $retentionPolicy"
}
}
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XAnnotated.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XAnnotated.kt
new file mode 100644
index 0000000..bc43682
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XAnnotated.kt
@@ -0,0 +1,52 @@
+/*
+ * 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
+
+import kotlin.reflect.KClass
+
+/**
+ * Common interface implemented by elements that might have annotations.
+ */
+interface XAnnotated {
+ /**
+ * 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 [hasAnnotationWithPackage]
+ */
+ 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 hasAnnotationWithPackage(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)
+}
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt
index 3fafecb..b18909e 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt
@@ -17,7 +17,6 @@
package androidx.room.compiler.processing
import kotlin.contracts.contract
-import kotlin.reflect.KClass
/**
* Represents an element declared in code.
@@ -27,41 +26,13 @@
* @see XVariableElement
* @see XTypeElement
*/
-interface XElement {
+interface XElement : XAnnotated {
/**
* 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 [hasAnnotationWithPackage]
- */
- 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 hasAnnotationWithPackage(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)
-
- /**
* Casts current element to [XTypeElement].
*/
fun asTypeElement() = this as XTypeElement
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XFiler.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XFiler.kt
new file mode 100644
index 0000000..dce852c
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XFiler.kt
@@ -0,0 +1,28 @@
+/*
+ * 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
+
+import com.squareup.javapoet.JavaFile
+
+/**
+ * Code generation interface for XProcessing.
+ */
+interface XFiler {
+ fun write(javaFile: JavaFile)
+}
+
+fun JavaFile.writeTo(generator: XFiler) = generator.write(this)
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodType.kt
index 92a0208..9dbb428 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodType.kt
@@ -17,6 +17,7 @@
package androidx.room.compiler.processing
import com.squareup.javapoet.TypeVariableName
+import kotlin.contracts.contract
/**
* Represents a type information for a method.
@@ -38,11 +39,14 @@
* 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
+/**
+ * Returns `true` if this method type represents a suspend function
+ */
+fun XMethodType.isSuspendFunction(): Boolean {
+ contract {
+ returns(true) implies (this@isSuspendFunction is XSuspendMethodType)
+ }
+ return this is XSuspendMethodType
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
index 11858cd..908cc4b 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
@@ -18,7 +18,6 @@
import androidx.room.compiler.processing.javac.JavacProcessingEnv
import com.squareup.javapoet.TypeName
-import javax.annotation.processing.Filer
import javax.annotation.processing.ProcessingEnvironment
import kotlin.reflect.KClass
@@ -40,7 +39,7 @@
/**
* The API to generate files
*/
- val filer: Filer
+ val filer: XFiler
/**
* Looks for the [XTypeElement] with the given qualified name and returns `null` if it does not
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XSuspendMethodType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XSuspendMethodType.kt
new file mode 100644
index 0000000..997efac
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XSuspendMethodType.kt
@@ -0,0 +1,24 @@
+/*
+ * 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
+
+interface XSuspendMethodType : XMethodType {
+ /**
+ * IfReturns the real return type as seen by Kotlin.
+ */
+ fun getSuspendFunctionReturnType(): XType
+}
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacAnnotationBox.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacAnnotationBox.kt
index c7c26484..bff4938 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacAnnotationBox.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacAnnotationBox.kt
@@ -113,7 +113,8 @@
"getAsAnnotationBoxArray" -> map[args[0]]
else -> map[method.name]
}
- })
+ }
+ )
}
@Suppress("DEPRECATION")
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacArrayType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacArrayType.kt
index a6533d6..87489e2 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacArrayType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacArrayType.kt
@@ -31,7 +31,8 @@
) : JavacType(
env,
typeMirror
-), XArrayType {
+),
+ XArrayType {
constructor(
env: JavacProcessingEnv,
typeMirror: ArrayType,
@@ -71,6 +72,7 @@
env.wrap<JavacType>(
typeMirror = componentType,
kotlinType = kotlinType?.typeArguments?.firstOrNull(),
- elementNullability = componentTypeNullability)
+ elementNullability = componentTypeNullability
+ )
}
}
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacConstructorElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacConstructorElement.kt
index 2144339..4145442 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacConstructorElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacConstructorElement.kt
@@ -30,7 +30,8 @@
env,
containing,
element
-), XConstructorElement {
+),
+ XConstructorElement {
init {
check(element.kind == ElementKind.CONSTRUCTOR) {
"Constructor element is constructed with invalid type: $element"
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacDeclaredType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacDeclaredType.kt
index ce3a84f..bed2e88 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacDeclaredType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacDeclaredType.kt
@@ -28,7 +28,8 @@
override val kotlinType: KmType?
) : JavacType(
env, typeMirror
-), XDeclaredType {
+),
+ XDeclaredType {
constructor(
env: JavacProcessingEnv,
typeMirror: DeclaredType,
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacExecutableElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacExecutableElement.kt
index c1a0648..2278c43 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacExecutableElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacExecutableElement.kt
@@ -29,7 +29,9 @@
) : JavacElement(
env,
element
-), XExecutableElement, XHasModifiers by JavacHasModifiers(element) {
+),
+ XExecutableElement,
+ XHasModifiers by JavacHasModifiers(element) {
abstract val kotlinMetadata: KmExecutable?
val descriptor by lazy {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacFiler.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacFiler.kt
new file mode 100644
index 0000000..354236a
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacFiler.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.javac
+
+import androidx.room.compiler.processing.XFiler
+import com.squareup.javapoet.JavaFile
+import javax.annotation.processing.Filer
+
+internal class JavacFiler(val filer: Filer) : XFiler {
+ override fun write(javaFile: JavaFile) {
+ javaFile.writeTo(filer)
+ }
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodElement.kt
index f0bde58..ecf16d7 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodElement.kt
@@ -37,7 +37,8 @@
env,
containing,
element
-), XMethodElement {
+),
+ XMethodElement {
init {
check(element.kind == ElementKind.METHOD) {
"Method element is constructed with invalid type: $element"
@@ -57,7 +58,7 @@
override val executableType: JavacMethodType by lazy {
val asMemberOf = env.typeUtils.asMemberOf(containing.type.typeMirror, element)
- JavacMethodType(
+ JavacMethodType.create(
env = env,
element = this,
executableType = MoreTypes.asExecutable(asMemberOf)
@@ -88,7 +89,7 @@
} else {
check(other is JavacDeclaredType)
val asMemberOf = env.typeUtils.asMemberOf(other.typeMirror, element)
- JavacMethodType(
+ JavacMethodType.create(
env = env,
element = this,
executableType = MoreTypes.asExecutable(asMemberOf)
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodType.kt
index 2b968988..cb42583 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodType.kt
@@ -17,12 +17,13 @@
package androidx.room.compiler.processing.javac
import androidx.room.compiler.processing.XMethodType
+import androidx.room.compiler.processing.XSuspendMethodType
import androidx.room.compiler.processing.XType
import com.google.auto.common.MoreTypes
import com.squareup.javapoet.TypeVariableName
import javax.lang.model.type.ExecutableType
-internal class JavacMethodType(
+internal sealed class JavacMethodType(
val env: JavacProcessingEnv,
val element: JavacMethodElement,
val executableType: ExecutableType
@@ -66,22 +67,57 @@
return executableType.hashCode()
}
- override fun getSuspendFunctionReturnType(): XType {
- // the continuation parameter is always the last parameter of a suspend function and it only
- // has one type parameter, e.g Continuation<? super T>
- val typeParam =
- MoreTypes.asDeclared(executableType.parameterTypes.last()).typeArguments.first()
- // kotlin generates ? extends Foo and we want Foo so get the extends bounds
- val bounded = typeParam.extendsBound() ?: typeParam
- return env.wrap<JavacType>(
- typeMirror = bounded,
- // use kotlin metadata here to get the real type information
- kotlinType = element.kotlinMetadata?.returnType,
- elementNullability = element.element.nullability
- )
- }
-
override fun toString(): String {
return executableType.toString()
}
+
+ private class NormalMethodType(
+ env: JavacProcessingEnv,
+ element: JavacMethodElement,
+ executableType: ExecutableType
+ ) : JavacMethodType(
+ env = env,
+ element = element,
+ executableType = executableType
+ )
+
+ private class SuspendMethodType(
+ env: JavacProcessingEnv,
+ element: JavacMethodElement,
+ executableType: ExecutableType
+ ) : JavacMethodType(
+ env = env,
+ element = element,
+ executableType = executableType
+ ),
+ XSuspendMethodType {
+ override fun getSuspendFunctionReturnType(): XType {
+ // the continuation parameter is always the last parameter of a suspend function and it
+ // only has one type parameter, e.g Continuation<? super T>
+ val typeParam =
+ MoreTypes.asDeclared(executableType.parameterTypes.last()).typeArguments.first()
+ // kotlin generates ? extends Foo and we want Foo so get the extends bounds
+ val bounded = typeParam.extendsBound() ?: typeParam
+ return env.wrap<JavacType>(
+ typeMirror = bounded,
+ // use kotlin metadata here to get the real type information
+ kotlinType = element.kotlinMetadata?.returnType,
+ elementNullability = element.element.nullability
+ )
+ }
+ }
+
+ companion object {
+ fun create(
+ env: JavacProcessingEnv,
+ element: JavacMethodElement,
+ executableType: ExecutableType
+ ): JavacMethodType {
+ return if (element.isSuspendFunction()) {
+ SuspendMethodType(env, element, executableType)
+ } else {
+ NormalMethodType(env, element, executableType)
+ }
+ }
+ }
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnv.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnv.kt
index 1061104..746a4be 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnv.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnv.kt
@@ -50,7 +50,7 @@
JavacProcessingEnvMessager(delegate)
}
- override val filer = delegate.filer
+ override val filer = JavacFiler(delegate.filer)
override val options: Map<String, String>
get() = delegate.options
@@ -98,9 +98,11 @@
check(it is JavacType)
it.typeMirror
}.toTypedArray()
- check(types.all {
- it is JavacType
- })
+ check(
+ types.all {
+ it is JavacType
+ }
+ )
return wrap<JavacDeclaredType>(
typeMirror = typeUtils.getDeclaredType(type.element, *args),
// type elements cannot have nullability hence we don't synthesize anything here
@@ -127,46 +129,49 @@
elementNullability: XNullability
): T {
return when (typeMirror.kind) {
- TypeKind.ARRAY -> if (kotlinType == null) {
- JavacArrayType(
- env = this,
- typeMirror = MoreTypes.asArray(typeMirror),
- nullability = elementNullability,
- knownComponentNullability = null
- )
- } else {
- JavacArrayType(
- env = this,
- typeMirror = MoreTypes.asArray(typeMirror),
- kotlinType = kotlinType
- )
- }
- TypeKind.DECLARED -> if (kotlinType == null) {
- JavacDeclaredType(
- env = this,
- typeMirror = MoreTypes.asDeclared(typeMirror),
- nullability = elementNullability
- )
- } else {
- JavacDeclaredType(
- env = this,
- typeMirror = MoreTypes.asDeclared(typeMirror),
- kotlinType = kotlinType
- )
- }
- else -> if (kotlinType == null) {
- DefaultJavacType(
- env = this,
- typeMirror = typeMirror,
- nullability = elementNullability
- )
- } else {
- DefaultJavacType(
- env = this,
- typeMirror = typeMirror,
- kotlinType = kotlinType
- )
- }
+ TypeKind.ARRAY ->
+ if (kotlinType == null) {
+ JavacArrayType(
+ env = this,
+ typeMirror = MoreTypes.asArray(typeMirror),
+ nullability = elementNullability,
+ knownComponentNullability = null
+ )
+ } else {
+ JavacArrayType(
+ env = this,
+ typeMirror = MoreTypes.asArray(typeMirror),
+ kotlinType = kotlinType
+ )
+ }
+ TypeKind.DECLARED ->
+ if (kotlinType == null) {
+ JavacDeclaredType(
+ env = this,
+ typeMirror = MoreTypes.asDeclared(typeMirror),
+ nullability = elementNullability
+ )
+ } else {
+ JavacDeclaredType(
+ env = this,
+ typeMirror = MoreTypes.asDeclared(typeMirror),
+ kotlinType = kotlinType
+ )
+ }
+ else ->
+ if (kotlinType == null) {
+ DefaultJavacType(
+ env = this,
+ typeMirror = typeMirror,
+ nullability = elementNullability
+ )
+ } else {
+ DefaultJavacType(
+ env = this,
+ typeMirror = typeMirror,
+ kotlinType = kotlinType
+ )
+ }
} as T
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnvMessager.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnvMessager.kt
index 8fdeba7..f5120fa 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnvMessager.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnvMessager.kt
@@ -79,9 +79,11 @@
else -> {
// Not sure how to nicely print the element, delegate to utils then.
append("In:\n")
- append(StringWriter().apply {
- elementUtils.printElements(this, element)
- }.toString())
+ append(
+ StringWriter().apply {
+ elementUtils.printElements(this, element)
+ }.toString()
+ )
}
}
}.toString()
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/TypeMirrorExt.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/TypeMirrorExt.kt
index a58890e..ca9f866 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/TypeMirrorExt.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/TypeMirrorExt.kt
@@ -21,9 +21,12 @@
import javax.lang.model.util.SimpleTypeVisitor7
internal fun TypeMirror.extendsBound(): TypeMirror? {
- return this.accept(object : SimpleTypeVisitor7<TypeMirror?, Void?>() {
- override fun visitWildcard(type: WildcardType, ignored: Void?): TypeMirror? {
- return type.extendsBound ?: type.superBound
- }
- }, null)
+ return this.accept(
+ object : SimpleTypeVisitor7<TypeMirror?, Void?>() {
+ override fun visitWildcard(type: WildcardType, ignored: Void?): TypeMirror? {
+ return type.extendsBound ?: type.superBound
+ }
+ },
+ null
+ )
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
index f9b0524..5e330f3 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
@@ -335,7 +335,8 @@
typeArguments = typeParameters.map {
it.asKmType()
},
- extendsBound = null),
+ extendsBound = null
+ ),
superType = superType
)
)
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElement.kt
index 963055f..963c20a 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElement.kt
@@ -31,9 +31,11 @@
) {
private val typeInfo: KmClassTypeInfo by lazy {
lateinit var result: KmClassTypeInfo
- classMetadata.accept(ClassAsKmTypeReader {
- result = it
- })
+ classMetadata.accept(
+ ClassAsKmTypeReader {
+ result = it
+ }
+ )
result
}
val kmType
@@ -47,9 +49,9 @@
private val ExecutableElement.descriptor: String
get() = descriptor()
- fun findPrimaryConstructorSignature() = constructorList.first {
+ fun findPrimaryConstructorSignature() = constructorList.firstOrNull {
it.isPrimary()
- }.descriptor
+ }?.descriptor
fun isObject(): Boolean = classMetadata.isObject()
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAnnotatedExt.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAnnotatedExt.kt
index f3fcd5c..85ecf9d 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAnnotatedExt.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAnnotatedExt.kt
@@ -18,10 +18,10 @@
import org.jetbrains.kotlin.ksp.symbol.KSAnnotated
-fun KSAnnotated.isJvmStatic() = annotations.any {
+internal fun KSAnnotated.isJvmStatic() = annotations.any {
it.annotationType.resolve()?.declaration?.qualifiedName?.asString() == "kotlin.jvm.JvmStatic"
}
-fun KSAnnotated.isJvmDefault() = annotations.any {
+internal fun KSAnnotated.isJvmDefault() = annotations.any {
it.annotationType.resolve()?.declaration?.qualifiedName?.asString() == "kotlin.jvm.JvmDefault"
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt
index 2ea9db7..92a8279 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAsMemberOf.kt
@@ -21,11 +21,13 @@
import org.jetbrains.kotlin.ksp.processing.Resolver
import org.jetbrains.kotlin.ksp.symbol.KSClassDeclaration
import org.jetbrains.kotlin.ksp.symbol.KSDeclaration
+import org.jetbrains.kotlin.ksp.symbol.KSFunctionDeclaration
import org.jetbrains.kotlin.ksp.symbol.KSName
import org.jetbrains.kotlin.ksp.symbol.KSPropertyDeclaration
import org.jetbrains.kotlin.ksp.symbol.KSType
import org.jetbrains.kotlin.ksp.symbol.KSTypeArgument
import org.jetbrains.kotlin.ksp.symbol.KSTypeParameter
+import org.jetbrains.kotlin.ksp.symbol.KSVariableParameter
import org.jetbrains.kotlin.ksp.symbol.Nullability
/**
@@ -42,6 +44,27 @@
return myType.asMemberOf(resolver, this, ksType)
}
+internal fun KSVariableParameter.typeAsMemberOf(
+ resolver: Resolver,
+ functionDeclaration: KSFunctionDeclaration,
+ ksType: KSType
+): KSType {
+ val myType: KSType = checkNotNull(type?.requireType()) {
+ "Cannot find type of method parameter: $this"
+ }
+ return myType.asMemberOf(resolver, functionDeclaration, ksType)
+}
+
+internal fun KSFunctionDeclaration.returnTypeAsMemberOf(
+ resolver: Resolver,
+ ksType: KSType
+): KSType {
+ val myType: KSType = checkNotNull(returnType?.requireType()) {
+ "Cannot resolve return type of $this"
+ }
+ return myType.asMemberOf(resolver, this, ksType)
+}
+
/**
* Returns `this` type as member of the [other] type.
*
@@ -110,9 +133,11 @@
if (this.arguments.isEmpty()) {
return this
}
- return replace(this.arguments.map {
- it.replaceFromMap(resolver, arguments)
- })
+ return replace(
+ this.arguments.map {
+ it.replaceFromMap(resolver, arguments)
+ }
+ )
}
private fun KSTypeArgument.makeNullable(resolver: Resolver): KSTypeArgument {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
new file mode 100644
index 0000000..36bb0de
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
@@ -0,0 +1,142 @@
+/*
+ * 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.XAnnotated
+import androidx.room.compiler.processing.XAnnotationBox
+import org.jetbrains.kotlin.ksp.symbol.AnnotationUseSiteTarget
+import org.jetbrains.kotlin.ksp.symbol.KSAnnotated
+import org.jetbrains.kotlin.ksp.symbol.KSAnnotation
+import kotlin.reflect.KClass
+
+internal sealed class KspAnnotated(
+ val env: KspProcessingEnv
+) : XAnnotated {
+ abstract fun annotations(): Sequence<KSAnnotation>
+
+ override fun <T : Annotation> toAnnotationBox(annotation: KClass<T>): XAnnotationBox<T>? {
+ return annotations().firstOrNull {
+ val qName = it.annotationType.resolve()?.declaration?.qualifiedName?.asString()
+ qName == annotation.qualifiedName
+ }?.let {
+ KspAnnotationBox(
+ env = env,
+ annotationClass = annotation.java,
+ annotation = it
+ )
+ }
+ }
+
+ override fun hasAnnotationWithPackage(pkg: String): Boolean {
+ return annotations().any {
+ it.annotationType.resolve()?.declaration?.qualifiedName?.getQualifier() == pkg
+ }
+ }
+
+ override fun hasAnnotation(annotation: KClass<out Annotation>): Boolean {
+ return annotations().any {
+ val qName = it.annotationType.resolve()?.declaration?.qualifiedName?.asString()
+ qName == annotation.qualifiedName
+ }
+ }
+
+ operator fun plus(other: KspAnnotated): XAnnotated = Combined(env, this, other)
+
+ private class KSAnnotatedDelegate(
+ env: KspProcessingEnv,
+ private val delegate: KSAnnotated,
+ private val useSiteFilter: UseSiteFilter
+ ) : KspAnnotated(env) {
+ override fun annotations(): Sequence<KSAnnotation> {
+ return delegate.annotations.asSequence().filter {
+ useSiteFilter.accept(it)
+ }
+ }
+ }
+
+ private class NotAnnotated(env: KspProcessingEnv) : KspAnnotated(env) {
+ override fun annotations(): Sequence<KSAnnotation> {
+ return emptySequence()
+ }
+ }
+
+ private class Combined(
+ env: KspProcessingEnv,
+ private val first: KspAnnotated,
+ private val second: KspAnnotated
+ ) : KspAnnotated(env) {
+ override fun annotations(): Sequence<KSAnnotation> {
+ return first.annotations() + second.annotations()
+ }
+ }
+
+ /**
+ * TODO: The implementation of UseSiteFilter is not 100% correct until
+ * https://github.com/google/ksp/issues/96 is fixed.
+ * https://kotlinlang.org/docs/reference/annotations.html
+ *
+ * More specifically, when a use site is not defined in an annotation, we need to find the
+ * declaration of the annotation and decide on the use site based on that.
+ * Unfortunately, due to KSP issue #96, we cannot yet read values from a `@Target` annotation
+ * which prevents implementing it correctly.
+ *
+ * Current implementation just approximates it which should work for Room.
+ */
+ interface UseSiteFilter {
+ fun accept(annotation: KSAnnotation): Boolean
+
+ private class Impl(
+ val acceptNull: Boolean,
+ val acceptedTarget: AnnotationUseSiteTarget
+ ) : UseSiteFilter {
+ override fun accept(annotation: KSAnnotation): Boolean {
+ val target = annotation.useSiteTarget
+ return if (target == null) {
+ acceptNull
+ } else {
+ acceptedTarget == target
+ }
+ }
+ }
+
+ companion object {
+ val FIELD: UseSiteFilter = Impl(true, AnnotationUseSiteTarget.FIELD)
+ val PROPERTY_GETTER: UseSiteFilter = Impl(false, AnnotationUseSiteTarget.GET)
+ val PROPERTY_SETTER: UseSiteFilter = Impl(false, AnnotationUseSiteTarget.SET)
+ val PROPERTY_SETTER_PARAMETER: UseSiteFilter =
+ Impl(false, AnnotationUseSiteTarget.SETPARAM)
+ val METHOD_PARAMETER: UseSiteFilter = Impl(true, AnnotationUseSiteTarget.PARAM)
+ val NO_USE_SITE = object : UseSiteFilter {
+ override fun accept(annotation: KSAnnotation): Boolean {
+ return annotation.useSiteTarget == null
+ }
+ }
+ }
+ }
+
+ companion object {
+ fun create(
+ env: KspProcessingEnv,
+ delegate: KSAnnotated?,
+ filter: UseSiteFilter
+ ): KspAnnotated {
+ return delegate?.let {
+ KSAnnotatedDelegate(env, it, filter)
+ } ?: NotAnnotated(env)
+ }
+ }
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt
new file mode 100644
index 0000000..9465cf3
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt
@@ -0,0 +1,97 @@
+/*
+ * 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.XAnnotationBox
+import androidx.room.compiler.processing.XType
+import org.jetbrains.kotlin.ksp.symbol.KSAnnotation
+import org.jetbrains.kotlin.ksp.symbol.KSType
+import java.lang.reflect.Proxy
+
+@Suppress("UNCHECKED_CAST")
+internal class KspAnnotationBox<T : Annotation>(
+ private val env: KspProcessingEnv,
+ private val annotationClass: Class<T>,
+ private val annotation: KSAnnotation
+) : XAnnotationBox<T> {
+ override fun getAsType(methodName: String): XType? {
+ val value = getFieldValue<KSType>(methodName)
+ return value?.let(env::wrap)
+ }
+
+ override fun getAsTypeList(methodName: String): List<XType> {
+ val values = getFieldValue<List<KSType>>(methodName) ?: return emptyList()
+ return values.map(env::wrap)
+ }
+
+ override fun <R : Annotation> getAsAnnotationBox(methodName: String): XAnnotationBox<R> {
+ val value = getFieldValue<KSAnnotation>(methodName) ?: error("cannot get annotation")
+ val annotationType = annotationClass.methods.first {
+ it.name == methodName
+ }.returnType as Class<R>
+ return KspAnnotationBox(
+ env = env,
+ annotationClass = annotationType,
+ annotation = value
+ )
+ }
+
+ private inline fun <reified R> getFieldValue(methodName: String): R? {
+ val value = annotation.arguments.firstOrNull {
+ it.name?.asString() == methodName
+ }?.value ?: return null
+ return value as R?
+ }
+
+ override fun <R : Annotation> getAsAnnotationBoxArray(
+ methodName: String
+ ): Array<XAnnotationBox<R>> {
+ val values = getFieldValue<ArrayList<*>>(methodName) ?: return emptyArray()
+ val annotationType = annotationClass.methods.first {
+ it.name == methodName
+ }.returnType.componentType as Class<R>
+ return values.map {
+ KspAnnotationBox<R>(
+ env = env,
+ annotationClass = annotationType,
+ annotation = it as KSAnnotation
+ )
+ }.toTypedArray()
+ }
+
+ private val valueProxy: T = Proxy.newProxyInstance(
+ KspAnnotationBox::class.java.classLoader,
+ arrayOf(annotationClass)
+ ) { _, method, _ ->
+ val fieldValue = getFieldValue(method.name) ?: method.defaultValue
+ // java gives arrays, kotlin gives array list (sometimes?) so fix it up
+ when {
+ fieldValue == null -> null
+ method.returnType.isArray && (fieldValue is ArrayList<*>) -> {
+ val componentType = method.returnType.componentType!!
+ val result =
+ java.lang.reflect.Array.newInstance(componentType, fieldValue.size) as Array<*>
+ fieldValue.toArray(result)
+ result
+ }
+ else -> fieldValue
+ }
+ } as T
+
+ override val value: T
+ get() = valueProxy
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspArrayType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspArrayType.kt
index d578c20..df89b7f 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspArrayType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspArrayType.kt
@@ -27,7 +27,8 @@
ksType: KSType
) : KspType(
env, ksType
-), XArrayType {
+),
+ XArrayType {
override val componentType: XType by lazy {
typeArguments.first()
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspConstructorElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspConstructorElement.kt
index 88e58f0..f6e4350 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspConstructorElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspConstructorElement.kt
@@ -27,4 +27,5 @@
env = env,
containing = containing,
declaration = declaration
-), XConstructorElement
+),
+ XConstructorElement
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspElement.kt
index 258342a..076c82e 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspElement.kt
@@ -16,7 +16,6 @@
package androidx.room.compiler.processing.ksp
-import androidx.room.compiler.processing.XAnnotationBox
import androidx.room.compiler.processing.XElement
import androidx.room.compiler.processing.XEquality
import org.jetbrains.kotlin.ksp.symbol.KSAnnotated
@@ -24,7 +23,6 @@
import org.jetbrains.kotlin.ksp.symbol.KSFunctionDeclaration
import org.jetbrains.kotlin.ksp.symbol.KSPropertyDeclaration
import java.util.Locale
-import kotlin.reflect.KClass
internal abstract class KspElement(
protected val env: KspProcessingEnv,
@@ -32,26 +30,15 @@
) : XElement, XEquality {
override fun kindName(): String {
return when (declaration) {
- is KSClassDeclaration -> (declaration as KSClassDeclaration).classKind.name
- .toLowerCase(Locale.US)
+ is KSClassDeclaration ->
+ (declaration as KSClassDeclaration).classKind.name
+ .toLowerCase(Locale.US)
is KSPropertyDeclaration -> "property"
is KSFunctionDeclaration -> "function"
else -> declaration::class.simpleName ?: "unknown"
}
}
- override fun <T : Annotation> toAnnotationBox(annotation: KClass<T>): XAnnotationBox<T>? {
- TODO("Not yet implemented")
- }
-
- override fun hasAnnotationWithPackage(pkg: String): Boolean {
- TODO("Not yet implemented")
- }
-
- override fun hasAnnotation(annotation: KClass<out Annotation>): Boolean {
- TODO("Not yet implemented")
- }
-
override fun equals(other: Any?): Boolean {
return XEquality.equals(this, other)
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableElement.kt
index 7c95149..bba8064 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableElement.kt
@@ -16,20 +16,29 @@
package androidx.room.compiler.processing.ksp
+import androidx.room.compiler.processing.XAnnotated
import androidx.room.compiler.processing.XExecutableElement
import androidx.room.compiler.processing.XExecutableParameterElement
import androidx.room.compiler.processing.XHasModifiers
import androidx.room.compiler.processing.XTypeElement
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE
import org.jetbrains.kotlin.ksp.symbol.KSFunctionDeclaration
-internal open class KspExecutableElement(
+internal abstract class KspExecutableElement(
env: KspProcessingEnv,
val containing: KspTypeElement,
override val declaration: KSFunctionDeclaration
) : KspElement(
env = env,
declaration = declaration
-), XExecutableElement, XHasModifiers by KspHasModifiers(declaration) {
+),
+ XExecutableElement,
+ XHasModifiers by KspHasModifiers(declaration),
+ XAnnotated by KspAnnotated.create(
+ env = env,
+ delegate = declaration,
+ filter = NO_USE_SITE
+ ) {
override val equalityItems: Array<out Any?> by lazy {
arrayOf(containing, declaration)
@@ -39,13 +48,15 @@
declaration.requireEnclosingTypeElement(env)
}
- override val parameters: List<XExecutableParameterElement>
- get() = TODO(
- """
- implement parameters. need to be careful w/ suspend functions as they need to fake
- an additional parameter to look like java
- """.trimIndent()
- )
+ override val parameters: List<XExecutableParameterElement> by lazy {
+ declaration.parameters.map {
+ KspExecutableParameterElement(
+ env = env,
+ method = this,
+ parameter = it
+ )
+ }
+ }
override fun isVarArgs(): Boolean {
return declaration.parameters.any {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
new file mode 100644
index 0000000..0e98d94
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
@@ -0,0 +1,72 @@
+/*
+ * 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.XAnnotated
+import androidx.room.compiler.processing.XDeclaredType
+import androidx.room.compiler.processing.XEquality
+import androidx.room.compiler.processing.XExecutableParameterElement
+import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.METHOD_PARAMETER
+import org.jetbrains.kotlin.ksp.symbol.KSVariableParameter
+
+internal class KspExecutableParameterElement(
+ val env: KspProcessingEnv,
+ val method: KspExecutableElement,
+ val parameter: KSVariableParameter
+) : XExecutableParameterElement,
+ XEquality,
+ XAnnotated by KspAnnotated.create(env, parameter, METHOD_PARAMETER) {
+
+ override val equalityItems: Array<out Any?>
+ get() = arrayOf(method, parameter)
+
+ override val name: String
+ get() = parameter.name?.asString() ?: "_no_param_name"
+
+ override val type: XType by lazy {
+ parameter.typeAsMemberOf(
+ resolver = env.resolver,
+ functionDeclaration = method.declaration,
+ ksType = method.containing.declaration.asStarProjectedType()
+ ).let(env::wrap)
+ }
+
+ override fun asMemberOf(other: XDeclaredType): XType {
+ if (method.containing.type.isSameType(other)) {
+ return type
+ }
+ check(other is KspType)
+ return parameter.typeAsMemberOf(
+ resolver = env.resolver,
+ functionDeclaration = method.declaration,
+ ksType = other.ksType
+ ).let(env::wrap)
+ }
+
+ override fun kindName(): String {
+ return "function parameter"
+ }
+
+ override fun equals(other: Any?): Boolean {
+ return XEquality.equals(this, other)
+ }
+
+ override fun hashCode(): Int {
+ return XEquality.hashCode(equalityItems)
+ }
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
index 0a1d582..449b29e 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
@@ -16,18 +16,23 @@
package androidx.room.compiler.processing.ksp
+import androidx.room.compiler.processing.XAnnotated
import androidx.room.compiler.processing.XDeclaredType
import androidx.room.compiler.processing.XFieldElement
import androidx.room.compiler.processing.XHasModifiers
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.FIELD
import org.jetbrains.kotlin.ksp.symbol.KSPropertyDeclaration
internal class KspFieldElement(
env: KspProcessingEnv,
override val declaration: KSPropertyDeclaration,
val containing: KspTypeElement
-) : KspElement(env, declaration), XFieldElement, XHasModifiers by KspHasModifiers(declaration) {
+) : KspElement(env, declaration),
+ XFieldElement,
+ XHasModifiers by KspHasModifiers(declaration),
+ XAnnotated by KspAnnotated.create(env, declaration, FIELD) {
override val equalityItems: Array<out Any?> by lazy {
arrayOf(declaration, containing)
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
new file mode 100644
index 0000000..e75da68
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.XFiler
+import com.squareup.javapoet.JavaFile
+import org.jetbrains.kotlin.ksp.processing.CodeGenerator
+
+internal class KspFiler(
+ private val delegate: CodeGenerator
+) : XFiler {
+ override fun write(javaFile: JavaFile) {
+ delegate.createNewFile(
+ packageName = javaFile.packageName,
+ fileName = javaFile.typeSpec.name,
+ extensionName = "java"
+ ).use { outputStream ->
+ outputStream.bufferedWriter(Charsets.UTF_8).use {
+ javaFile.writeTo(it)
+ }
+ }
+ }
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
index 74d352b..fae37ac 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
@@ -17,14 +17,20 @@
package androidx.room.compiler.processing.ksp
import androidx.room.compiler.processing.XDeclaredType
+import androidx.room.compiler.processing.XExecutableParameterElement
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XMethodType
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
+import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticContinuationParameterElement
+import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
+import org.jetbrains.kotlin.ksp.symbol.ClassKind
+import org.jetbrains.kotlin.ksp.symbol.KSClassDeclaration
import org.jetbrains.kotlin.ksp.symbol.KSFunctionDeclaration
import org.jetbrains.kotlin.ksp.symbol.Modifier
+import org.jetbrains.kotlin.ksp.symbol.Origin
-internal class KspMethodElement(
+internal sealed class KspMethodElement(
env: KspProcessingEnv,
containing: KspTypeElement,
declaration: KSFunctionDeclaration
@@ -32,50 +38,137 @@
env = env,
containing = containing,
declaration = declaration
-), XMethodElement {
+),
+ XMethodElement {
override val name: String by lazy {
declaration.simpleName.asString()
}
- override val returnType: XType
- get() = TODO(
- """
- Implement return type.
- Need to handle suspend functions where their signature is different as long as we
- generate java code.
- """.trimIndent()
+ override val executableType: XMethodType by lazy {
+ KspMethodType.create(
+ env = env,
+ origin = this,
+ containing = this.containing.type
)
-
- override val executableType: XMethodType
- get() = TODO("Not yet implemented")
+ }
override fun isJavaDefault(): Boolean {
return declaration.modifiers.contains(Modifier.JAVA_DEFAULT) || declaration.isJvmDefault()
}
override fun asMemberOf(other: XDeclaredType): XMethodType {
- TODO("Not yet implemented")
+ check(other is KspType)
+ return KspMethodType.create(
+ env = env,
+ origin = this,
+ containing = other
+ )
}
override fun hasKotlinDefaultImpl(): Boolean {
- TODO("Not yet implemented")
- }
-
- override fun isSuspendFunction(): Boolean {
- return declaration.modifiers.contains(Modifier.SUSPEND)
+ // see https://github.com/google/ksp/issues/32
+ val parentDeclaration = declaration.parentDeclaration
+ // if parent declaration is an interface and we are not marked as an abstract method,
+ // we should have a default implementation
+ return parentDeclaration is KSClassDeclaration &&
+ parentDeclaration.classKind == ClassKind.INTERFACE &&
+ !declaration.isAbstract
}
override fun overrides(other: XMethodElement, owner: XTypeElement): Boolean {
- return other is KspMethodElement && declaration.overrides(other.declaration)
+ if (other is KspMethodElement) {
+ return try {
+ declaration.overrides(other.declaration)
+ } catch (castException: ClassCastException) {
+ // TODO remove the try catch once that bug is fixed.
+ // see https://github.com/google/ksp/issues/94
+ false
+ }
+ }
+ // TODO https://github.com/google/ksp/issues/93
+ // remove this custom implementation when KSP supports this out of the box
+ // if our declaration is coming from java, it can override property getters/setters as well
+ val checkForJavaToKotlinOverride = other.isOverrideableIgnoringContainer() &&
+ (declaration.origin == Origin.JAVA || declaration.origin == Origin.CLASS)
+ return if (checkForJavaToKotlinOverride && name == other.name) {
+ when (other) {
+ is KspSyntheticPropertyMethodElement.Getter -> {
+ return parameters.isEmpty() &&
+ asMemberOf(owner.type).returnType.isSameType(
+ other.asMemberOf(owner.type).returnType
+ )
+ }
+ is KspSyntheticPropertyMethodElement.Setter -> {
+ return parameters.size == 1 &&
+ parameters.first().asMemberOf(owner.type).isSameType(
+ other.parameters.first().asMemberOf(owner.type)
+ )
+ }
+ else -> false
+ }
+ } else {
+ false
+ }
}
- override fun copyTo(newContainer: XTypeElement): XMethodElement {
+ override fun copyTo(newContainer: XTypeElement): KspMethodElement {
check(newContainer is KspTypeElement)
- return KspMethodElement(
+ return create(
env = env,
containing = newContainer,
declaration = declaration
)
}
+
+ private class KspNormalMethodElement(
+ env: KspProcessingEnv,
+ containing: KspTypeElement,
+ declaration: KSFunctionDeclaration
+ ) : KspMethodElement(
+ env, containing, declaration
+ ) {
+ override val returnType: XType by lazy {
+ env.wrap(
+ checkNotNull(declaration.returnType) {
+ "return type on a method declaration cannot be null"
+ }
+ )
+ }
+ override fun isSuspendFunction() = false
+ }
+
+ private class KspSuspendMethodElement(
+ env: KspProcessingEnv,
+ containing: KspTypeElement,
+ declaration: KSFunctionDeclaration
+ ) : KspMethodElement(
+ env, containing, declaration
+ ) {
+ override fun isSuspendFunction() = true
+
+ override val returnType: XType by lazy {
+ env.wrap(env.resolver.builtIns.anyType.makeNullable())
+ }
+
+ override val parameters: List<XExecutableParameterElement>
+ get() = super.parameters + KspSyntheticContinuationParameterElement(
+ env = env,
+ containing = this
+ )
+ }
+
+ companion object {
+ fun create(
+ env: KspProcessingEnv,
+ containing: KspTypeElement,
+ declaration: KSFunctionDeclaration
+ ): KspMethodElement {
+ return if (declaration.modifiers.contains(Modifier.SUSPEND)) {
+ KspSuspendMethodElement(env, containing, declaration)
+ } else {
+ KspNormalMethodElement(env, containing, declaration)
+ }
+ }
+ }
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
new file mode 100644
index 0000000..15a1487
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodType.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.XMethodType
+import androidx.room.compiler.processing.XSuspendMethodType
+import androidx.room.compiler.processing.XType
+import com.squareup.javapoet.TypeVariableName
+
+internal sealed class KspMethodType(
+ val env: KspProcessingEnv,
+ val origin: KspMethodElement,
+ val containing: KspType
+) : XMethodType {
+ override val parameterTypes: List<XType> by lazy {
+ origin.parameters.map {
+ it.asMemberOf(containing)
+ }
+ }
+
+ override val typeVariableNames: List<TypeVariableName> by lazy {
+ origin.declaration.typeParameters.map {
+ TypeVariableName.get(
+ it.name.asString(),
+ *(
+ it.bounds.map {
+ it.typeName()
+ }.toTypedArray()
+ )
+ )
+ }
+ }
+
+ private class KspNormalMethodType(
+ env: KspProcessingEnv,
+ origin: KspMethodElement,
+ containing: KspType
+ ) : KspMethodType(env, origin, containing) {
+ override val returnType: XType by lazy {
+ env.wrap(
+ origin.declaration.returnTypeAsMemberOf(
+ resolver = env.resolver,
+ ksType = containing.ksType
+ )
+ )
+ }
+ }
+
+ private class KspSuspendMethodType(
+ env: KspProcessingEnv,
+ origin: KspMethodElement,
+ containing: KspType
+ ) : KspMethodType(env, origin, containing), XSuspendMethodType {
+ override val returnType: XType
+ // suspend functions always return Any?, no need to call asMemberOf
+ get() = origin.returnType
+
+ override fun getSuspendFunctionReturnType(): XType {
+ return env.wrap(
+ origin.declaration.returnTypeAsMemberOf(
+ resolver = env.resolver,
+ ksType = containing.ksType
+ )
+ )
+ }
+ }
+
+ companion object {
+ fun create(
+ env: KspProcessingEnv,
+ origin: KspMethodElement,
+ containing: KspType
+ ) = if (origin.isSuspendFunction()) {
+ KspSuspendMethodType(env, origin, containing)
+ } else {
+ KspNormalMethodType(env, origin, containing)
+ }
+ }
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
index 24ec0b3..9137b71 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
@@ -17,6 +17,7 @@
package androidx.room.compiler.processing.ksp
import androidx.room.compiler.processing.XArrayType
+import androidx.room.compiler.processing.XFiler
import androidx.room.compiler.processing.XDeclaredType
import androidx.room.compiler.processing.XMessager
import androidx.room.compiler.processing.XProcessingEnv
@@ -30,14 +31,14 @@
import org.jetbrains.kotlin.ksp.symbol.KSType
import org.jetbrains.kotlin.ksp.symbol.KSTypeReference
import org.jetbrains.kotlin.ksp.symbol.Variance
-import javax.annotation.processing.Filer
internal class KspProcessingEnv(
override val options: Map<String, String>,
- private val codeGenerator: CodeGenerator,
+ codeGenerator: CodeGenerator,
private val logger: KSPLogger,
val resolver: Resolver
) : XProcessingEnv {
+
private val typeElementStore =
XTypeElementStore { qName ->
resolver.getClassDeclarationByName(
@@ -53,8 +54,7 @@
override val messager: XMessager
get() = TODO("Not yet implemented")
- override val filer: Filer
- get() = TODO("Not yet implemented")
+ override val filer: XFiler = KspFiler(codeGenerator)
val commonTypes = CommonTypes(resolver)
@@ -80,10 +80,12 @@
check(type is KspType)
val arrayType = resolver.requireClass(KOTLIN_ARRAY_Q_NAME)
val ksType = arrayType.asType(
- listOf(resolver.getTypeArgument(
- type.ksType.createTypeReference(),
- Variance.INVARIANT
- ))
+ listOf(
+ resolver.getTypeArgument(
+ type.ksType.createTypeReference(),
+ Variance.INVARIANT
+ )
+ )
)
return KspArrayType(
env = this,
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
index 85ab73d..1fecce7 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
@@ -62,10 +62,11 @@
}
private val _typeElement by lazy {
- check(ksType.declaration is KSClassDeclaration) { """
+ check(ksType.declaration is KSClassDeclaration) {
+ """
Unexpected case where ksType's declaration is not a KSClassDeclaration.
Please file a bug.
- """.trimIndent()
+ """.trimIndent()
}
env.wrapClassDeclaration(ksType.declaration as KSClassDeclaration)
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
index 959d0eb..e9c5e76 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
@@ -16,12 +16,15 @@
package androidx.room.compiler.processing.ksp
+import androidx.room.compiler.processing.XAnnotated
import androidx.room.compiler.processing.XConstructorElement
import androidx.room.compiler.processing.XFieldElement
import androidx.room.compiler.processing.XHasModifiers
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE
+import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticConstructorForJava
import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
import com.squareup.javapoet.ClassName
import org.jetbrains.kotlin.ksp.getAllSuperTypes
@@ -30,13 +33,18 @@
import org.jetbrains.kotlin.ksp.isOpen
import org.jetbrains.kotlin.ksp.symbol.ClassKind
import org.jetbrains.kotlin.ksp.symbol.KSClassDeclaration
+import org.jetbrains.kotlin.ksp.symbol.KSFunctionDeclaration
import org.jetbrains.kotlin.ksp.symbol.KSPropertyDeclaration
import org.jetbrains.kotlin.ksp.symbol.Modifier
+import org.jetbrains.kotlin.ksp.symbol.Origin
internal class KspTypeElement(
env: KspProcessingEnv,
override val declaration: KSClassDeclaration
-) : KspElement(env, declaration), XTypeElement, XHasModifiers by KspHasModifiers(declaration) {
+) : KspElement(env, declaration),
+ XTypeElement,
+ XHasModifiers by KspHasModifiers(declaration),
+ XAnnotated by KspAnnotated.create(env, declaration, NO_USE_SITE) {
override val name: String by lazy {
declaration.simpleName.asString()
@@ -176,7 +184,18 @@
}
override fun findPrimaryConstructor(): XConstructorElement? {
- TODO("Not yet implemented")
+ val primary = if (declaration.declaredConstructors().isEmpty() && !isInterface()) {
+ declaration.primaryConstructor
+ } else {
+ declaration.getNonSyntheticPrimaryConstructor()
+ }
+ return primary?.let {
+ KspConstructorElement(
+ env = env,
+ containing = this,
+ declaration = it
+ )
+ }
}
private val _declaredMethods by lazy {
@@ -185,7 +204,7 @@
// filter out constructors
it.simpleName.asString() != name
}.map {
- KspMethodElement(
+ KspMethodElement.create(
env = env,
containing = this,
declaration = it
@@ -207,25 +226,36 @@
}
override fun getConstructors(): List<XConstructorElement> {
- val constructors = declaration.getDeclaredFunctions()
- .filter {
- it.simpleName.asString() == name
- }.toMutableList()
- declaration.primaryConstructor?.let { primary ->
- // workaround for https://github.com/android/kotlin/issues/136
- // TODO remove once that bug is fixed
- if (primary.simpleName.asString() != "<init>") {
- constructors.add(primary)
- }
+ val constructors = declaration.declaredConstructors().toMutableList()
+ val primary = if (constructors.isEmpty() && !isInterface()) {
+ declaration.primaryConstructor
+ } else {
+ declaration.getNonSyntheticPrimaryConstructor()
}
+ primary?.let(constructors::add)
- return constructors.map {
+ val elements: List<XConstructorElement> = constructors.map {
KspConstructorElement(
env = env,
containing = this,
declaration = it
)
}
+ return if (elements.isEmpty() &&
+ declaration.origin == Origin.JAVA &&
+ !isInterface()
+ ) {
+ // workaround for https://github.com/google/ksp/issues/98
+ // TODO remove if KSP support this
+ listOf(
+ KspSyntheticConstructorForJava(
+ env = env,
+ origin = this
+ )
+ )
+ } else {
+ elements
+ }
}
override fun getSuperInterfaceElements(): List<XTypeElement> {
@@ -238,4 +268,20 @@
env.wrapClassDeclaration(it)
}
}
+
+ private fun KSClassDeclaration.getNonSyntheticPrimaryConstructor(): KSFunctionDeclaration? {
+ val primary = declaration.primaryConstructor
+ // workaround for https://github.com/android/kotlin/issues/136
+ // TODO remove once that bug is fixed
+ return if (primary?.simpleName?.asString() != "<init>") {
+ primary
+ } else {
+ null
+ }
+ }
+
+ private fun KSClassDeclaration.declaredConstructors() = this.getDeclaredFunctions()
+ .filter {
+ it.simpleName == this.simpleName
+ }.distinct() // workaround for: https://github.com/google/ksp/issues/99
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt
index 9e53d6d..d490a38 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt
@@ -25,3 +25,5 @@
internal fun Resolver.requireClass(qName: String) = checkNotNull(findClass(qName)) {
"cannot find class $qName"
}
+
+internal fun Resolver.requireContinuationClass() = requireClass("kotlin.coroutines.Continuation")
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticConstructorForJava.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticConstructorForJava.kt
new file mode 100644
index 0000000..88e24de
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticConstructorForJava.kt
@@ -0,0 +1,68 @@
+/*
+ * 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.synthetic
+
+import androidx.room.compiler.processing.XAnnotated
+import androidx.room.compiler.processing.XConstructorElement
+import androidx.room.compiler.processing.XExecutableParameterElement
+import androidx.room.compiler.processing.XTypeElement
+import androidx.room.compiler.processing.ksp.KspAnnotated
+import androidx.room.compiler.processing.ksp.KspProcessingEnv
+import androidx.room.compiler.processing.ksp.KspTypeElement
+
+/**
+ * KSP does not create any constructor for java classes that do not have explicit constructor so
+ * we synthesize one.
+ *
+ * see: https://github.com/google/ksp/issues/98
+ */
+internal class KspSyntheticConstructorForJava(
+ val env: KspProcessingEnv,
+ val origin: KspTypeElement
+) : XConstructorElement,
+ XAnnotated by KspAnnotated.create(
+ env = env,
+ delegate = null, // there is no way to annotate this synthetic in kotlin
+ filter = KspAnnotated.UseSiteFilter.NO_USE_SITE
+ ) {
+
+ override val enclosingTypeElement: XTypeElement
+ get() = origin
+
+ override val parameters: List<XExecutableParameterElement>
+ get() = emptyList()
+
+ override fun isVarArgs() = false
+
+ override fun isPublic() = origin.isPublic()
+
+ override fun isProtected() = origin.isProtected()
+
+ override fun isAbstract() = false
+
+ override fun isPrivate() = origin.isPrivate()
+
+ override fun isStatic() = false
+
+ override fun isTransient() = false
+
+ override fun isFinal() = origin.isFinal()
+
+ override fun kindName(): String {
+ return "synthetic java constructor"
+ }
+}
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
new file mode 100644
index 0000000..fef7915
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
@@ -0,0 +1,100 @@
+/*
+ * 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.synthetic
+
+import androidx.room.compiler.processing.XAnnotated
+import androidx.room.compiler.processing.XDeclaredType
+import androidx.room.compiler.processing.XEquality
+import androidx.room.compiler.processing.XExecutableParameterElement
+import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.ksp.KspAnnotated
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE
+import androidx.room.compiler.processing.ksp.KspExecutableElement
+import androidx.room.compiler.processing.ksp.KspProcessingEnv
+import androidx.room.compiler.processing.ksp.KspType
+import androidx.room.compiler.processing.ksp.requireContinuationClass
+import androidx.room.compiler.processing.ksp.returnTypeAsMemberOf
+import androidx.room.compiler.processing.ksp.swapResolvedType
+import org.jetbrains.kotlin.ksp.symbol.Variance
+
+/**
+ * XProcessing adds an additional argument to each suspend function for the continiuation because
+ * this is what KAPT generates and Room needs it as long as it generates java code.
+ */
+internal class KspSyntheticContinuationParameterElement(
+ private val env: KspProcessingEnv,
+ private val containing: KspExecutableElement
+) : XExecutableParameterElement,
+ XEquality,
+ XAnnotated by KspAnnotated.create(
+ env = env,
+ delegate = null, // does not matter, this is synthetic and has no annotations.
+ filter = NO_USE_SITE
+ ) {
+
+ override val name: String
+ get() = "_syntheticContinuation"
+
+ override val equalityItems: Array<out Any?> by lazy {
+ arrayOf("continuation", containing)
+ }
+
+ override val type: XType by lazy {
+ val continuation = env.resolver.requireContinuationClass()
+ val contType = continuation.asType(
+ listOf(
+ env.resolver.getTypeArgument(
+ checkNotNull(containing.declaration.returnType) {
+ "cannot find return type for $this"
+ },
+ Variance.CONTRAVARIANT
+ )
+ )
+ )
+ env.wrap(contType)
+ }
+
+ override fun asMemberOf(other: XDeclaredType): XType {
+ check(other is KspType)
+ val continuation = env.resolver.requireContinuationClass()
+ val asMember = containing.declaration.returnTypeAsMemberOf(
+ resolver = env.resolver,
+ ksType = other.ksType
+ )
+ val returnTypeRef = checkNotNull(containing.declaration.returnType) {
+ "cannot find return type reference for $this"
+ }
+ val returnTypeAsTypeArgument = env.resolver.getTypeArgument(
+ returnTypeRef.swapResolvedType(asMember),
+ Variance.CONTRAVARIANT
+ )
+ val contType = continuation.asType(listOf(returnTypeAsTypeArgument))
+ return env.wrap(contType)
+ }
+
+ override fun kindName(): String {
+ return "synthetic continuation parameter"
+ }
+
+ override fun equals(other: Any?): Boolean {
+ return XEquality.equals(this, other)
+ }
+
+ override fun hashCode(): Int {
+ return XEquality.hashCode(equalityItems)
+ }
+}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
index 26327f1..c17e2d3 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
@@ -16,21 +16,25 @@
package androidx.room.compiler.processing.ksp.synthetic
-import androidx.room.compiler.processing.XAnnotationBox
+import androidx.room.compiler.processing.XAnnotated
import androidx.room.compiler.processing.XDeclaredType
+import androidx.room.compiler.processing.XEquality
import androidx.room.compiler.processing.XExecutableParameterElement
import androidx.room.compiler.processing.XHasModifiers
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XMethodType
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
-import androidx.room.compiler.processing.ksp.KspElement
+import androidx.room.compiler.processing.ksp.KspAnnotated
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.PROPERTY_GETTER
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.PROPERTY_SETTER
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.PROPERTY_SETTER_PARAMETER
import androidx.room.compiler.processing.ksp.KspFieldElement
import androidx.room.compiler.processing.ksp.KspHasModifiers
import androidx.room.compiler.processing.ksp.KspProcessingEnv
import androidx.room.compiler.processing.ksp.KspTypeElement
import java.util.Locale
-import kotlin.reflect.KClass
/**
* Kotlin properties don't have getters/setters in KSP. As Room expects Java code, we synthesize
@@ -38,16 +42,16 @@
*
* @see KspSyntheticPropertyMethodElement.Getter
* @see KspSyntheticPropertyMethodElement.Setter
+ * @see KspSyntheticPropertyMethodType
*/
internal sealed class KspSyntheticPropertyMethodElement(
- env: KspProcessingEnv,
+ val env: KspProcessingEnv,
val field: KspFieldElement
-) : KspElement(
- env = env,
- declaration = field.declaration
-), XMethodElement, XHasModifiers by KspHasModifiers(
- field.declaration
-) {
+) : XMethodElement,
+ XEquality,
+ XHasModifiers by KspHasModifiers(
+ field.declaration
+ ) {
// NOTE: modifiers of the property are not necessarily my modifiers.
// that being said, it only matters if it is private in which case KAPT does not generate the
// synthetic hence we don't either.
@@ -62,11 +66,26 @@
final override fun isVarArgs() = false
- final override val executableType: XMethodType
- get() = TODO()
+ final override val executableType: XMethodType by lazy {
+ KspSyntheticPropertyMethodType.create(
+ element = this,
+ container = field.containing.type
+ )
+ }
final override fun asMemberOf(other: XDeclaredType): XMethodType {
- TODO()
+ return KspSyntheticPropertyMethodType.create(
+ element = this,
+ container = other
+ )
+ }
+
+ override fun equals(other: Any?): Boolean {
+ return XEquality.equals(this, other)
+ }
+
+ override fun hashCode(): Int {
+ return XEquality.hashCode(equalityItems)
}
internal class Getter(
@@ -75,7 +94,16 @@
) : KspSyntheticPropertyMethodElement(
env = env,
field = field
- ) {
+ ),
+ XAnnotated by KspAnnotated.create(
+ env = env,
+ delegate = field.declaration.getter,
+ filter = NO_USE_SITE
+ ) + KspAnnotated.create(
+ env = env,
+ delegate = field.declaration,
+ filter = PROPERTY_GETTER
+ ) {
override val equalityItems: Array<out Any?> by lazy {
arrayOf(field, "getter")
}
@@ -97,6 +125,10 @@
override val parameters: List<XExecutableParameterElement>
get() = emptyList()
+ override fun kindName(): String {
+ return "synthetic property getter"
+ }
+
override fun overrides(other: XMethodElement, owner: XTypeElement): Boolean {
return other is Getter &&
field.declaration.overrides(other.field.declaration)
@@ -117,7 +149,16 @@
) : KspSyntheticPropertyMethodElement(
env = env,
field = field
- ) {
+ ),
+ XAnnotated by KspAnnotated.create(
+ env = env,
+ delegate = field.declaration.setter,
+ filter = NO_USE_SITE
+ ) + KspAnnotated.create(
+ env = env,
+ delegate = field.declaration,
+ filter = PROPERTY_SETTER
+ ) {
override val equalityItems: Array<out Any?> by lazy {
arrayOf(field, "setter")
}
@@ -141,11 +182,16 @@
override val parameters: List<XExecutableParameterElement> by lazy {
listOf(
SyntheticExecutableParameterElement(
- this
+ env = env,
+ origin = this
)
)
}
+ override fun kindName(): String {
+ return "synthetic property getter"
+ }
+
override fun overrides(other: XMethodElement, owner: XTypeElement): Boolean {
return other is Setter &&
field.declaration.overrides(other.field.declaration)
@@ -160,8 +206,18 @@
}
private class SyntheticExecutableParameterElement(
+ env: KspProcessingEnv,
private val origin: Setter
- ) : XExecutableParameterElement {
+ ) : XExecutableParameterElement,
+ XAnnotated by KspAnnotated.create(
+ env = env,
+ delegate = origin.field.declaration,
+ filter = PROPERTY_SETTER_PARAMETER
+ ) + KspAnnotated.create(
+ env = env,
+ delegate = origin.field.declaration.setter?.parameter,
+ filter = NO_USE_SITE
+ ) {
override val name: String
get() = origin.name
override val type: XType
@@ -174,20 +230,6 @@
override fun kindName(): String {
return "method parameter"
}
-
- override fun <T : Annotation> toAnnotationBox(
- annotation: KClass<T>
- ): XAnnotationBox<T>? {
- TODO("Not yet implemented")
- }
-
- override fun hasAnnotationWithPackage(pkg: String): Boolean {
- TODO("Not yet implemented")
- }
-
- override fun hasAnnotation(annotation: KClass<out Annotation>): Boolean {
- TODO("Not yet implemented")
- }
}
}
}
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt
new file mode 100644
index 0000000..0480aea
--- /dev/null
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodType.kt
@@ -0,0 +1,84 @@
+/*
+ * 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.synthetic
+
+import androidx.room.compiler.processing.XDeclaredType
+import androidx.room.compiler.processing.XMethodType
+import androidx.room.compiler.processing.XType
+import com.squareup.javapoet.TypeVariableName
+
+/**
+ * @see KspSyntheticPropertyMethodElement
+ */
+internal sealed class KspSyntheticPropertyMethodType(
+ val origin: KspSyntheticPropertyMethodElement,
+ val containing: XDeclaredType
+) : XMethodType {
+
+ override val parameterTypes: List<XType> by lazy {
+ origin.parameters.map {
+ it.asMemberOf(containing)
+ }
+ }
+
+ override val typeVariableNames: List<TypeVariableName>
+ get() = emptyList()
+
+ companion object {
+ fun create(
+ element: KspSyntheticPropertyMethodElement,
+ container: XDeclaredType
+ ): XMethodType {
+ return when (element) {
+ is KspSyntheticPropertyMethodElement.Getter ->
+ Getter(
+ origin = element,
+ containingType = container
+ )
+ is KspSyntheticPropertyMethodElement.Setter ->
+ Setter(
+ origin = element,
+ containingType = container
+ )
+ }
+ }
+ }
+
+ private class Getter(
+ origin: KspSyntheticPropertyMethodElement.Getter,
+ containingType: XDeclaredType
+ ) : KspSyntheticPropertyMethodType(
+ origin = origin,
+ containing = containingType
+ ) {
+ override val returnType: XType by lazy {
+ origin.field.asMemberOf(containingType)
+ }
+ }
+
+ private class Setter(
+ origin: KspSyntheticPropertyMethodElement.Setter,
+ containingType: XDeclaredType
+ ) : KspSyntheticPropertyMethodType(
+ origin = origin,
+ containing = containingType
+ ) {
+ override val returnType: XType
+ // setters always return Unit, no need to get it as type of
+ get() = origin.returnType
+ }
+}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/JavacTestProcessorTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/JavacTestProcessorTest.kt
index 77a5524..59412d4 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/JavacTestProcessorTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/JavacTestProcessorTest.kt
@@ -28,13 +28,14 @@
@Test
fun testGetAnnotations() {
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
import androidx.room.compiler.processing.testcode.OtherAnnotation;
@OtherAnnotation(value="xx")
class Baz {
}
- """.trimIndent()
+ """.trimIndent()
)
val invoked = AtomicBoolean(false)
val testProcessor = object : JavacTestProcessor() {
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/KotlinMetadataTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/KotlinMetadataTest.kt
index 8860ab3..046b3b5 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/KotlinMetadataTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/KotlinMetadataTest.kt
@@ -29,9 +29,10 @@
@Test
fun readWithMetadata() {
val source = Source.kotlin(
- "Dummy.kt", """
+ "Dummy.kt",
+ """
class Dummy
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
sources = listOf(source)
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/MethodSpecHelperTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/MethodSpecHelperTest.kt
index fe82178..d0850f7 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/MethodSpecHelperTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/MethodSpecHelperTest.kt
@@ -39,7 +39,8 @@
fun overrides() {
// check our override impl matches javapoet
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
import androidx.room.compiler.processing.testcode.OtherAnnotation;
@@ -70,7 +71,7 @@
protected void throwsException() throws Exception {
}
}
- """.trimIndent()
+ """.trimIndent()
)
// first build golden image with Java processor so we can use JavaPoet's API
val golden = buildMethodsViaJavaPoet(source)
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
index 3d8a483..cb4ae75 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
@@ -19,8 +19,13 @@
import androidx.room.compiler.processing.testcode.MainAnnotation
import androidx.room.compiler.processing.testcode.OtherAnnotation
import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.getField
+import androidx.room.compiler.processing.util.getMethod
+import androidx.room.compiler.processing.util.getParameter
import androidx.room.compiler.processing.util.runProcessorTest
+import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -28,15 +33,17 @@
@RunWith(JUnit4::class)
class XAnnotationBoxTest {
@Test
- fun readSimpleAnotationValue() {
+ fun readSimpleAnnotationValue() {
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
@SuppressWarnings({"warning1", "warning 2"})
public class Baz {
}
- """.trimIndent()
+ """.trimIndent()
)
+ // TODO add KSP once https://github.com/google/ksp/issues/96 is fixed.
runProcessorTest(
sources = listOf(source)
) {
@@ -54,7 +61,8 @@
@Test
fun typeReference() {
val mySource = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
import androidx.room.compiler.processing.testcode.MainAnnotation;
import androidx.room.compiler.processing.testcode.OtherAnnotation;
@@ -72,13 +80,12 @@
)
public class Baz {
}
- """.trimIndent()
+ """.trimIndent()
)
- val targetName = "foo.bar.Baz"
runProcessorTest(
listOf(mySource)
) {
- val element = it.processingEnv.requireTypeElement(targetName)
+ val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
element.toAnnotationBox(MainAnnotation::class)!!.let { annotation ->
assertThat(
annotation.getAsTypeList("typeList")
@@ -106,4 +113,238 @@
}
}
}
+
+ @Test
+ fun readSimpleAnnotationValue_kotlin() {
+ val source = Source.kotlin(
+ "Foo.kt",
+ """
+ @SuppressWarnings("warning1", "warning 2")
+ class Subject {
+ }
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(
+ sources = listOf(source)
+ ) {
+ val element = it.processingEnv.requireTypeElement("Subject")
+ val annotationBox = element.toAnnotationBox(SuppressWarnings::class)
+ assertThat(annotationBox).isNotNull()
+ assertThat(
+ annotationBox!!.value.value
+ ).isEqualTo(
+ arrayOf("warning1", "warning 2")
+ )
+ }
+ }
+
+ @Test
+ fun typeReference_kotlin() {
+ val mySource = Source.kotlin(
+ "Foo.kt",
+ """
+ import androidx.room.compiler.processing.testcode.MainAnnotation
+ import androidx.room.compiler.processing.testcode.OtherAnnotation
+
+ @MainAnnotation(
+ typeList = [String::class, Int::class],
+ singleType = Long::class,
+ intMethod = 3,
+ otherAnnotationArray = [
+ OtherAnnotation(
+ value = "other list 1"
+ ),
+ OtherAnnotation(
+ value = "other list 2"
+ )
+ ],
+ singleOtherAnnotation = OtherAnnotation("other single")
+ )
+ public class Subject {
+ }
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(
+ listOf(mySource)
+ ) { invocation ->
+ val element = invocation.processingEnv.requireTypeElement("Subject")
+ element.toAnnotationBox(MainAnnotation::class)!!.let { annotation ->
+ assertThat(
+ annotation.getAsTypeList("typeList")
+ ).containsExactly(
+ invocation.processingEnv.requireType(invocation.types.string),
+ invocation.processingEnv.requireType(invocation.types.int)
+ )
+ assertThat(
+ annotation.getAsType("singleType")
+ ).isEqualTo(
+ invocation.processingEnv.requireType(invocation.types.long)
+ )
+
+ assertThat(annotation.value.intMethod).isEqualTo(3)
+ annotation.getAsAnnotationBox<OtherAnnotation>("singleOtherAnnotation")
+ .let { other ->
+ assertThat(other.value.value).isEqualTo("other single")
+ }
+ annotation.getAsAnnotationBoxArray<OtherAnnotation>("otherAnnotationArray")
+ .let { boxArray ->
+ assertThat(boxArray).hasLength(2)
+ assertThat(boxArray[0].value.value).isEqualTo("other list 1")
+ assertThat(boxArray[1].value.value).isEqualTo("other list 2")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun propertyAnnotations() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ import androidx.room.compiler.processing.testcode.OtherAnnotation
+ class Subject {
+ @SuppressWarnings("onProp1")
+ var prop1:Int = TODO()
+
+ @get:SuppressWarnings("onGetter2")
+ @set:SuppressWarnings("onSetter2")
+ @field:SuppressWarnings("onField2")
+ @setparam:SuppressWarnings("onSetterParam2")
+ var prop2:Int = TODO()
+
+ @get:SuppressWarnings("onGetter3")
+ @set:SuppressWarnings("onSetter3")
+ @setparam:SuppressWarnings("onSetterParam3")
+ var prop3:Int
+ @OtherAnnotation("_onGetter3")
+ get() = 3
+
+ @OtherAnnotation("_onSetter3")
+ set(@OtherAnnotation("_onSetterParam3") value) = Unit
+ }
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ val subject = invocation.processingEnv.requireTypeElement("Subject")
+
+ subject.getField("prop1").assertHasSuppressWithValue("onProp1")
+ subject.getMethod("getProp1").assertDoesNotHaveAnnotation()
+ subject.getMethod("setProp1").assertDoesNotHaveAnnotation()
+ subject.getMethod("setProp1").parameters.first().assertDoesNotHaveAnnotation()
+
+ subject.getField("prop2").assertHasSuppressWithValue("onField2")
+ subject.getMethod("getProp2").assertHasSuppressWithValue("onGetter2")
+ subject.getMethod("setProp2").assertHasSuppressWithValue("onSetter2")
+ subject.getMethod("setProp2").parameters.first().assertHasSuppressWithValue(
+ "onSetterParam2"
+ )
+
+ subject.getMethod("getProp3").assertHasSuppressWithValue("onGetter3")
+ subject.getMethod("setProp3").assertHasSuppressWithValue("onSetter3")
+ subject.getMethod("setProp3").parameters.first().assertHasSuppressWithValue(
+ "onSetterParam3"
+ )
+
+ assertThat(
+ subject.getMethod("getProp3").getOtherAnnotationValue()
+ ).isEqualTo("_onGetter3")
+ assertThat(
+ subject.getMethod("setProp3").getOtherAnnotationValue()
+ ).isEqualTo("_onSetter3")
+ val otherAnnotationValue =
+ subject.getMethod("setProp3").parameters.first().getOtherAnnotationValue()
+ assertThat(
+ otherAnnotationValue
+ ).isEqualTo("_onSetterParam3")
+ }
+ }
+
+ @Test
+ fun methodAnnotations() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ import androidx.room.compiler.processing.testcode.OtherAnnotation
+ class Subject {
+ fun noAnnotations(x:Int): Unit = TODO()
+ @SuppressWarnings("onMethod")
+ fun methodAnnotation(
+ @SuppressWarnings("onParam") annotated:Int,
+ notAnnotated:Int
+ ): Unit = TODO()
+ }
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ val subject = invocation.processingEnv.requireTypeElement("Subject")
+ subject.getMethod("noAnnotations").let { method ->
+ method.assertDoesNotHaveAnnotation()
+ method.getParameter("x").assertDoesNotHaveAnnotation()
+ }
+ subject.getMethod("methodAnnotation").let { method ->
+ method.assertHasSuppressWithValue("onMethod")
+ method.getParameter("annotated").assertHasSuppressWithValue("onParam")
+ method.getParameter("notAnnotated").assertDoesNotHaveAnnotation()
+ }
+ }
+ }
+
+ @Test
+ fun constructorParameterAnnotations() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ @SuppressWarnings("onClass")
+ data class Subject(
+ @field:SuppressWarnings("onField")
+ @param:SuppressWarnings("onConstructorParam")
+ @get:SuppressWarnings("onGetter")
+ @set:SuppressWarnings("onSetter")
+ var x:Int
+ )
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ val subject = invocation.processingEnv.requireTypeElement("Subject")
+ subject.assertHasSuppressWithValue("onClass")
+ val constructor = subject.getConstructors().single()
+ constructor.getParameter("x").assertHasSuppressWithValue("onConstructorParam")
+ subject.getMethod("getX").assertHasSuppressWithValue("onGetter")
+ subject.getMethod("setX").assertHasSuppressWithValue("onSetter")
+ subject.getField("x").assertHasSuppressWithValue("onField")
+ }
+ }
+
+ // helper function to read what we need
+ private fun XAnnotated.getSuppressValues(): Array<String>? {
+ return this.toAnnotationBox(SuppressWarnings::class)?.value?.value
+ }
+
+ private fun XAnnotated.assertHasSuppressWithValue(vararg expected: String) {
+ assertWithMessage("has suppress annotation $this")
+ .that(this.hasAnnotation(SuppressWarnings::class))
+ .isTrue()
+ assertWithMessage("$this")
+ .that(this.hasAnnotationWithPackage(SuppressWarnings::class.java.packageName))
+ .isTrue()
+ assertWithMessage("$this")
+ .that(getSuppressValues())
+ .isEqualTo(expected)
+ }
+
+ private fun XAnnotated.assertDoesNotHaveAnnotation() {
+ assertWithMessage("$this")
+ .that(this.hasAnnotation(SuppressWarnings::class))
+ .isFalse()
+ assertWithMessage("$this")
+ .that(this.hasAnnotationWithPackage(SuppressWarnings::class.java.packageName))
+ .isFalse()
+ assertWithMessage("$this")
+ .that(this.getSuppressValues())
+ .isNull()
+ }
+
+ private fun XAnnotated.getOtherAnnotationValue(): String? {
+ return this.toAnnotationBox(OtherAnnotation::class)?.value?.value
+ }
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XArrayTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XArrayTypeTest.kt
index 8dec922..e892e96 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XArrayTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XArrayTypeTest.kt
@@ -29,12 +29,13 @@
@Test
fun java() {
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
class Baz {
String[] param;
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTestIncludingKsp(
sources = listOf(source)
@@ -73,13 +74,14 @@
@Test
fun kotlin() {
val source = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
package foo.bar
class Baz {
val nonNull:Array<String> = TODO()
val nullable:Array<String?> = TODO()
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTestIncludingKsp(
sources = listOf(source)
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt
index 813e531..1eb4626 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt
@@ -37,7 +37,8 @@
runProcessorTest(
listOf(
Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
public abstract class Baz {
private int privateField;
@@ -55,7 +56,7 @@
abstract void abstractMethod();
static void staticMethod() {}
}
- """.trimIndent()
+ """.trimIndent()
)
)
) {
@@ -116,7 +117,8 @@
@Test
fun typeParams() {
val genericBase = Source.java(
- "foo.bar.Base", """
+ "foo.bar.Base",
+ """
package foo.bar;
public class Base<T> {
protected T returnT() {
@@ -135,7 +137,8 @@
""".trimIndent()
)
val boundedChild = Source.java(
- "foo.bar.Child", """
+ "foo.bar.Child",
+ """
package foo.bar;
public class Child extends Base<String> {
}
@@ -182,7 +185,8 @@
@Test
fun annotationAvailability() {
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
import org.junit.*;
import org.junit.runner.*;
@@ -197,7 +201,7 @@
@org.junit.Test
void testMethod() {}
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
listOf(source)
@@ -239,11 +243,12 @@
@Test
fun nonType() {
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
class Baz {
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
listOf(source)
@@ -257,7 +262,8 @@
@Test
fun isSomething() {
val subject = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
class Baz {
int field;
@@ -265,7 +271,7 @@
void method() {}
static interface Inner {}
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
sources = listOf(subject)
@@ -296,12 +302,13 @@
@Test
fun notATypeElement() {
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
class Baz {
public static int x;
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
listOf(source)
@@ -320,7 +327,8 @@
@Test
fun nullability() {
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
import androidx.annotation.*;
@@ -333,7 +341,7 @@
@Nullable
public static List<String> nullableAnnotated;
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
sources = listOf(source)
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
index 33a65a5..f342eed 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
@@ -16,13 +16,16 @@
package androidx.room.compiler.processing
+import androidx.room.compiler.processing.util.KotlinTypeNames
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.getDeclaredMethod
import androidx.room.compiler.processing.util.getMethod
import androidx.room.compiler.processing.util.getParameter
-import androidx.room.compiler.processing.util.runProcessorTest
+import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
-import com.squareup.javapoet.ClassName
+import com.squareup.javapoet.ParameterizedTypeName
+import com.squareup.javapoet.WildcardTypeName
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -31,10 +34,11 @@
class XExecutableElementTest {
@Test
fun basic() {
- runProcessorTest(
- listOf(
+ runProcessorTestIncludingKsp(
+ sources = listOf(
Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
public class Baz {
private void foo() {}
@@ -42,7 +46,7 @@
return "";
}
}
- """.trimIndent()
+ """.trimIndent()
)
)
) {
@@ -53,33 +57,35 @@
assertThat(method.isOverrideableIgnoringContainer()).isFalse()
assertThat(method.parameters).isEmpty()
val returnType = method.returnType
- assertThat(returnType.isVoid()).isTrue()
+ // check both as in KSP, it will show up as Unit
+ assertThat(returnType.isVoid() || returnType.isKotlinUnit()).isTrue()
assertThat(returnType.defaultValue()).isEqualTo("null")
}
element.getDeclaredMethod("bar").let { method ->
assertThat(method.isOverrideableIgnoringContainer()).isTrue()
assertThat(method.parameters).hasSize(1)
- val stringTypeName = ClassName.get("java.lang", "String")
method.getParameter("param1").let { param ->
assertThat(param.type.isArray()).isTrue()
assertThat(param.type.asArray().componentType.typeName)
- .isEqualTo(stringTypeName)
+ .isEqualTo(it.types.string)
}
- assertThat(method.returnType.typeName).isEqualTo(stringTypeName)
+ assertThat(method.returnType.typeName).isEqualTo(it.types.string)
}
}
}
+
@Test
fun isVarArgs() {
val subject = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
interface Baz {
void method(String... inputs);
}
- """.trimIndent()
+ """.trimIndent()
)
- runProcessorTest(
+ runProcessorTestIncludingKsp(
sources = listOf(subject)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -90,7 +96,8 @@
@Test
fun kotlinDefaultImpl() {
val subject = Source.kotlin(
- "Baz.kt", """
+ "Baz.kt",
+ """
package foo.bar;
import java.util.List;
interface Baz {
@@ -105,9 +112,9 @@
return param1.first();
}
}
- """.trimIndent()
+ """.trimIndent()
)
- runProcessorTest(
+ runProcessorTestIncludingKsp(
sources = listOf(subject)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -138,4 +145,266 @@
}
}
}
+
+ @Test
+ fun suspendMethod() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ class Subject {
+ suspend fun noArg():Unit = TODO()
+ suspend fun intReturn(): Int = TODO()
+ suspend fun twoParams(param1:String, param2:Int): Pair<String, Int> = TODO()
+ }
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(
+ sources = listOf(src)
+ ) { invocation ->
+ val subject = invocation.processingEnv.requireTypeElement("Subject")
+ subject.getMethod("noArg").let { method ->
+ assertThat(method.parameters).hasSize(1)
+ assertThat(method.isSuspendFunction()).isTrue()
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.objectOrAny)
+ assertThat(method.returnType.nullability).isEqualTo(XNullability.NULLABLE)
+ method.executableType.parameterTypes.last().let { cont ->
+ assertThat(cont.typeName).isEqualTo(
+ ParameterizedTypeName.get(
+ KotlinTypeNames.CONTINUATION_CLASS_NAME,
+ WildcardTypeName.supertypeOf(KotlinTypeNames.UNIT_CLASS_NAME)
+ )
+ )
+ assertThat(cont.nullability).isEqualTo(XNullability.NONNULL)
+ }
+ }
+ subject.getMethod("intReturn").let { method ->
+ assertThat(method.parameters).hasSize(1)
+ assertThat(method.parameters.last().type.typeName).isEqualTo(
+ ParameterizedTypeName.get(
+ KotlinTypeNames.CONTINUATION_CLASS_NAME,
+ WildcardTypeName.supertypeOf(invocation.types.boxedInt)
+ )
+ )
+ assertThat(method.isSuspendFunction()).isTrue()
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.objectOrAny)
+ method.executableType.parameterTypes.last().let { cont ->
+ assertThat(cont.typeName).isEqualTo(
+ ParameterizedTypeName.get(
+ KotlinTypeNames.CONTINUATION_CLASS_NAME,
+ WildcardTypeName.supertypeOf(invocation.types.boxedInt)
+ )
+ )
+ }
+ }
+ subject.getMethod("twoParams").let { method ->
+ assertThat(method.parameters).hasSize(3)
+ assertThat(method.parameters[0].type.typeName).isEqualTo(
+ invocation.types.string
+ )
+ assertThat(method.parameters[1].type.typeName).isEqualTo(
+ invocation.types.int
+ )
+ assertThat(method.isSuspendFunction()).isTrue()
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.objectOrAny)
+ method.executableType.parameterTypes.last().let { cont ->
+ assertThat(cont.typeName).isEqualTo(
+ ParameterizedTypeName.get(
+ KotlinTypeNames.CONTINUATION_CLASS_NAME,
+ WildcardTypeName.supertypeOf(
+ ParameterizedTypeName.get(
+ KotlinTypeNames.PAIR_CLASS_NAME,
+ invocation.types.string,
+ invocation.types.boxedInt
+ )
+ )
+ )
+ )
+ }
+ }
+ }
+ }
+
+ @Test
+ fun kotlinProperties() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ data class MyDataClass(val x:String, var y:String, private val z:String) {
+ val prop1: String = ""
+ var prop2: String = ""
+ var prop3: String = TODO()
+ private set
+ get() = TODO()
+ private val prop4:String = ""
+ }
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ val klass = invocation.processingEnv.requireTypeElement("MyDataClass")
+ val methodNames = klass.getAllMethods().map {
+ it.name
+ }
+ assertThat(methodNames).containsNoneIn(
+ listOf(
+ "setX", "setProp3", "setZ", "setProp4", "getProp4"
+ )
+ )
+ listOf("getX", "getProp1", "getProp2", "getProp3").forEach {
+ klass.getMethod(it).let { method ->
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.string)
+ assertThat(method.parameters).isEmpty()
+ }
+ }
+ listOf("setY", "setProp2").forEach {
+ klass.getMethod(it).let { method ->
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.voidOrUnit)
+ assertThat(method.parameters.first().type.typeName).isEqualTo(
+ invocation.types.string
+ )
+ }
+ }
+ }
+ }
+
+ @Test
+ fun parametersAsMemberOf() {
+ val source = Source.kotlin(
+ "Foo.kt",
+ """
+ open class Base<T> {
+ fun foo(t:T, nullableT:T?): List<T?> = TODO()
+ }
+ class Subject : Base<String>()
+ class NullableSubject: Base<String?>()
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(sources = listOf(source)) { invocation ->
+ val base = invocation.processingEnv.requireTypeElement("Base")
+ val subject = invocation.processingEnv.requireType("Subject")
+ .asDeclaredType()
+ val nullableSubject = invocation.processingEnv.requireType("NullableSubject")
+ .asDeclaredType()
+ val method = base.getMethod("foo")
+ method.getParameter("t").let { param ->
+ param.asMemberOf(subject).let {
+ assertThat(it.typeName).isEqualTo(invocation.types.string)
+ assertThat(it.nullability).isEqualTo(XNullability.NONNULL)
+ }
+ param.asMemberOf(nullableSubject).let {
+ assertThat(it.typeName).isEqualTo(invocation.types.string)
+ if (invocation.isKsp) {
+ // kapt implementation is unable to read this properly
+ assertThat(it.nullability).isEqualTo(XNullability.NULLABLE)
+ }
+ }
+ }
+ method.getParameter("nullableT").let { param ->
+ param.asMemberOf(subject).let {
+ assertThat(it.typeName).isEqualTo(invocation.types.string)
+ assertThat(it.nullability).isEqualTo(XNullability.NULLABLE)
+ }
+ param.asMemberOf(nullableSubject).let {
+ assertThat(it.typeName).isEqualTo(invocation.types.string)
+ assertThat(it.nullability).isEqualTo(XNullability.NULLABLE)
+ }
+ }
+ }
+ }
+
+ @Test
+ fun kotlinPropertyOverrides() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ interface MyInterface {
+ val x:Int
+ var y:Int
+ }
+ class MyImpl : MyInterface {
+ override var x: Int = 1
+ override var y: Int = 1
+ }
+ """.trimIndent()
+ )
+ val javaSrc = Source.java(
+ "JavaImpl",
+ """
+ class JavaImpl implements MyInterface {
+ public int getX() {
+ return 1;
+ }
+ public int getY() {
+ return 1;
+ }
+ public void setY(int value) {
+ }
+ }
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(sources = listOf(src, javaSrc)) { invocation ->
+ val base = invocation.processingEnv.requireTypeElement("MyInterface")
+ val impl = invocation.processingEnv.requireTypeElement("MyImpl")
+ val javaImpl = invocation.processingEnv.requireTypeElement("JavaImpl")
+
+ fun overrides(
+ owner: XTypeElement,
+ ownerMethodName: String,
+ base: XTypeElement,
+ baseMethodName: String = ownerMethodName
+ ): Boolean {
+ val overridee = owner.getMethod(ownerMethodName)
+ val overridden = base.getMethod(baseMethodName)
+ return overridee.overrides(
+ overridden, owner
+ )
+ }
+ listOf(impl, javaImpl).forEach { subject ->
+ listOf("getY", "getX", "setY").forEach { methodName ->
+ Truth.assertWithMessage("${subject.className}:$methodName").that(
+ overrides(
+ owner = subject,
+ ownerMethodName = methodName,
+ base = base
+ )
+ ).isTrue()
+ }
+
+ Truth.assertWithMessage(subject.className.canonicalName()).that(
+ overrides(
+ owner = subject,
+ ownerMethodName = "getY",
+ base = base,
+ baseMethodName = "getX"
+ )
+ ).isFalse()
+
+ Truth.assertWithMessage(subject.className.canonicalName()).that(
+ overrides(
+ owner = subject,
+ ownerMethodName = "getY",
+ base = subject,
+ baseMethodName = "getX"
+ )
+ ).isFalse()
+
+ Truth.assertWithMessage(subject.className.canonicalName()).that(
+ overrides(
+ owner = base,
+ ownerMethodName = "getX",
+ base = subject,
+ baseMethodName = "getX"
+ )
+ ).isFalse()
+
+ Truth.assertWithMessage(subject.className.canonicalName()).that(
+ overrides(
+ owner = subject,
+ ownerMethodName = "setY",
+ base = base,
+ baseMethodName = "getY"
+ )
+ ).isFalse()
+ }
+ }
+ }
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt
new file mode 100644
index 0000000..91c4181
--- /dev/null
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt
@@ -0,0 +1,250 @@
+/*
+ * 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
+
+import androidx.room.compiler.processing.util.KotlinTypeNames
+import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.getMethod
+import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import com.google.common.truth.Truth.assertThat
+import com.squareup.javapoet.ParameterizedTypeName
+import com.squareup.javapoet.WildcardTypeName
+import org.junit.Test
+
+class XExecutableTypeTest {
+ @Test
+ fun inheritanceResolution() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ interface MyInterface<T> {
+ fun getT(): T
+ fun setT(t:T): Unit
+ suspend fun suspendGetT(): T
+ suspend fun suspendSetT(t:T): Unit
+ }
+ abstract class Subject : MyInterface<String>
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(
+ sources = listOf(src)
+ ) { invocation ->
+ val myInterface = invocation.processingEnv.requireTypeElement("MyInterface")
+
+ // helper method to get executable types both from sub class and also as direct child of
+ // the given type
+ fun checkMethods(
+ methodName: String,
+ vararg subjects: XTypeElement,
+ callback: (XMethodType) -> Unit
+ ) {
+ assertThat(subjects).isNotEmpty()
+ subjects.forEach {
+ callback(myInterface.getMethod(methodName).asMemberOf(it.type))
+ callback(it.getMethod(methodName).executableType)
+ }
+ }
+
+ val subject = invocation.processingEnv.requireTypeElement("Subject")
+ checkMethods("getT", subject) { type ->
+ assertThat(type.parameterTypes).isEmpty()
+ assertThat(type.returnType.typeName).isEqualTo(invocation.types.string)
+ }
+ checkMethods("setT", subject) { type ->
+ assertThat(type.parameterTypes).containsExactly(
+ invocation.processingEnv.requireType(invocation.types.string)
+ )
+ assertThat(type.returnType.typeName).isEqualTo(invocation.types.voidOrUnit)
+ }
+ checkMethods("suspendGetT", subject) { type ->
+ assertThat(type.parameterTypes.first().typeName).isEqualTo(
+ ParameterizedTypeName.get(
+ KotlinTypeNames.CONTINUATION_CLASS_NAME,
+ WildcardTypeName.supertypeOf(invocation.types.string)
+ )
+ )
+ assertThat(type.returnType.typeName).isEqualTo(invocation.types.objectOrAny)
+ }
+ checkMethods("suspendSetT", subject) { type ->
+ assertThat(type.parameterTypes.first().typeName).isEqualTo(
+ invocation.types.string
+ )
+ assertThat(type.parameterTypes[1].typeName).isEqualTo(
+ ParameterizedTypeName.get(
+ KotlinTypeNames.CONTINUATION_CLASS_NAME,
+ WildcardTypeName.supertypeOf(KotlinTypeNames.UNIT_CLASS_NAME)
+ )
+ )
+ assertThat(type.returnType.typeName).isEqualTo(invocation.types.objectOrAny)
+ }
+ }
+ }
+
+ @Test
+ fun kotlinPropertyInheritance() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ interface MyInterface<T> {
+ val immutableT: T
+ var mutableT: T?
+ val list: List<T>
+ val nullableList: List<T?>
+ }
+ abstract class Subject : MyInterface<String>
+ abstract class NullableSubject: MyInterface<String?>
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ val myInterface = invocation.processingEnv.requireTypeElement("MyInterface")
+
+ // helper method to get executable types both from sub class and also as direct child of
+ // the given type
+ fun checkMethods(
+ methodName: String,
+ vararg subjects: XTypeElement,
+ callback: (XMethodType) -> Unit
+ ) {
+ assertThat(subjects).isNotEmpty()
+ subjects.forEach {
+ callback(myInterface.getMethod(methodName).asMemberOf(it.type))
+ callback(it.getMethod(methodName).executableType)
+ }
+ }
+
+ val subject = invocation.processingEnv.requireTypeElement("Subject")
+ checkMethods("getImmutableT", subject) { method ->
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.string)
+ if (invocation.isKsp) {
+ // we don't get proper nullable here for kapt
+ // partially related to b/169629272
+ assertThat(method.returnType.nullability).isEqualTo(XNullability.NONNULL)
+ }
+
+ assertThat(method.parameterTypes).isEmpty()
+ assertThat(method.typeVariableNames).isEmpty()
+ }
+ checkMethods("getMutableT", subject) { method ->
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.string)
+ if (invocation.isKsp) {
+ // we don't get proper nullable here for kapt
+ // partially related to b/169629272
+ assertThat(method.returnType.nullability).isEqualTo(XNullability.NULLABLE)
+ }
+ assertThat(method.parameterTypes).isEmpty()
+ assertThat(method.typeVariableNames).isEmpty()
+ }
+ checkMethods("setMutableT", subject) { method ->
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.voidOrUnit)
+ assertThat(method.parameterTypes.first().nullability)
+ .isEqualTo(XNullability.NULLABLE)
+ assertThat(method.parameterTypes.first().typeName)
+ .isEqualTo(invocation.types.string)
+ assertThat(method.typeVariableNames).isEmpty()
+ }
+ checkMethods("getList", subject) { method ->
+ assertThat(method.returnType.typeName).isEqualTo(
+ ParameterizedTypeName.get(
+ invocation.types.list,
+ invocation.types.string
+ )
+ )
+ assertThat(method.returnType.nullability).isEqualTo(
+ XNullability.NONNULL
+ )
+ if (invocation.isKsp) {
+ // kapt cannot read type parameter nullability yet
+ assertThat(
+ method.returnType.asDeclaredType().typeArguments.first().nullability
+ ).isEqualTo(
+ XNullability.NONNULL
+ )
+ }
+ }
+
+ val nullableSubject = invocation.processingEnv.requireTypeElement("NullableSubject")
+ // check that nullability is inferred from type parameters as well
+ checkMethods("getImmutableT", nullableSubject) { method ->
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.string)
+ if (invocation.isKsp) {
+ // we don't get proper nullable here for kapt
+ // partially related to b/169629272
+ assertThat(method.returnType.nullability).isEqualTo(XNullability.NULLABLE)
+ }
+ assertThat(method.parameterTypes).isEmpty()
+ assertThat(method.typeVariableNames).isEmpty()
+ }
+
+ checkMethods("getMutableT", nullableSubject) { method ->
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.string)
+ if (invocation.isKsp) {
+ // we don't get proper nullable here for kapt
+ // partially related to b/169629272
+ assertThat(method.returnType.nullability).isEqualTo(XNullability.NULLABLE)
+ }
+ assertThat(method.parameterTypes).isEmpty()
+ assertThat(method.typeVariableNames).isEmpty()
+ }
+
+ checkMethods("setMutableT", nullableSubject) { method ->
+ assertThat(method.returnType.typeName).isEqualTo(invocation.types.voidOrUnit)
+ assertThat(method.parameterTypes.first().nullability)
+ .isEqualTo(XNullability.NULLABLE)
+ assertThat(method.parameterTypes.first().typeName)
+ .isEqualTo(invocation.types.string)
+ assertThat(method.typeVariableNames).isEmpty()
+ }
+
+ checkMethods("getList", nullableSubject) { method ->
+ assertThat(method.returnType.typeName).isEqualTo(
+ ParameterizedTypeName.get(
+ invocation.types.list,
+ invocation.types.string
+ )
+ )
+ assertThat(method.returnType.nullability).isEqualTo(
+ XNullability.NONNULL
+ )
+ if (invocation.isKsp) {
+ assertThat(
+ method.returnType.asDeclaredType().typeArguments.first().nullability
+ ).isEqualTo(
+ XNullability.NULLABLE
+ )
+ }
+ }
+ checkMethods("getNullableList", subject, nullableSubject) { method ->
+ assertThat(method.returnType.typeName).isEqualTo(
+ ParameterizedTypeName.get(
+ invocation.types.list,
+ invocation.types.string
+ )
+ )
+ assertThat(method.returnType.nullability).isEqualTo(
+ XNullability.NONNULL
+ )
+ if (invocation.isKsp) {
+ assertThat(
+ method.returnType.asDeclaredType().typeArguments.first().nullability
+ ).isEqualTo(
+ XNullability.NULLABLE
+ )
+ }
+ }
+ }
+ }
+}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt
index 2881023..46b1037 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt
@@ -37,7 +37,8 @@
@Test
fun elementInferredNullability() {
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
import androidx.annotation.*;
@@ -63,7 +64,7 @@
return "";
}
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
sources = listOf(source)
@@ -129,7 +130,8 @@
@Test
fun kotlinNullability() {
val source = Source.kotlin(
- "Baz.kt", """
+ "Baz.kt",
+ """
package foo.bar;
import androidx.annotation.*;
@@ -157,7 +159,7 @@
) {
}
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
sources = listOf(source)
@@ -181,8 +183,10 @@
element.getMethod("suspendNullableReturn").let { method ->
// kotlin adds @Nullable annotation for suspend methods' javac signature
assertThat(method.returnType.nullability).isEqualTo(NULLABLE)
- assertThat(method.executableType.returnType.nullability).isEqualTo(NULLABLE)
- assertThat(method.executableType.getSuspendFunctionReturnType().nullability)
+ val executableType = method.executableType
+ check(executableType.isSuspendFunction())
+ assertThat(executableType.returnType.nullability).isEqualTo(NULLABLE)
+ assertThat(executableType.getSuspendFunctionReturnType().nullability)
.isEqualTo(NULLABLE)
}
element.getMethod("genericWithNullableTypeArgReturn").let { method ->
@@ -195,14 +199,16 @@
}
}
element.getMethod("suspendGenericWithNullableTypeArgReturn").let { method ->
- method.executableType.getSuspendFunctionReturnType().let { type ->
+ val executableType = method.executableType
+ check(executableType.isSuspendFunction())
+ executableType.getSuspendFunctionReturnType().let { type ->
assertThat(type.nullability).isEqualTo(NONNULL)
assertThat(type.asDeclaredType().typeArguments[0].nullability)
.isEqualTo(NONNULL)
assertThat(type.asDeclaredType().typeArguments[1].nullability)
.isEqualTo(NULLABLE)
}
- listOf(method.returnType, method.executableType.returnType).forEach { type ->
+ listOf(method.returnType, executableType.returnType).forEach { type ->
// kotlin suspend functions return nullable in jvm stub
assertThat(type.nullability).isEqualTo(NULLABLE)
assertThat(type.asDeclaredType().typeArguments).isEmpty()
@@ -215,8 +221,10 @@
element.getMethod("suspendNonNullReturn").let { method ->
// suspend methods return nullable in java declarations
assertThat(method.returnType.nullability).isEqualTo(NULLABLE)
- assertThat(method.executableType.returnType.nullability).isEqualTo(NULLABLE)
- assertThat(method.executableType.getSuspendFunctionReturnType().nullability)
+ val executableType = method.executableType
+ check(executableType.isSuspendFunction())
+ assertThat(executableType.returnType.nullability).isEqualTo(NULLABLE)
+ assertThat(executableType.getSuspendFunctionReturnType().nullability)
.isEqualTo(NONNULL)
}
element.getMethod("methodParams").let { method ->
@@ -224,15 +232,17 @@
.isEqualTo(NONNULL)
assertThat(method.getParameter("nullable").type.nullability)
.isEqualTo(NULLABLE)
- assertThat(method.parameters.filter {
- it.type.isDeclared() && it.type.asDeclaredType().typeArguments.isNotEmpty()
- }.map {
- Triple(
- first = it.name,
- second = it.type.nullability,
- third = it.type.asDeclaredType().typeArguments.single().nullability
- )
- }).containsExactly(
+ assertThat(
+ method.parameters.filter {
+ it.type.isDeclared() && it.type.asDeclaredType().typeArguments.isNotEmpty()
+ }.map {
+ Triple(
+ first = it.name,
+ second = it.type.nullability,
+ third = it.type.asDeclaredType().typeArguments.single().nullability
+ )
+ }
+ ).containsExactly(
Triple("nullableGenericWithNonNullType", NULLABLE, NONNULL),
Triple("nullableGenericWithNullableType", NULLABLE, NULLABLE),
Triple("nonNullGenericWithNonNullType", NONNULL, NONNULL),
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
index a2ca3d0..6c8efc0 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
@@ -17,26 +17,32 @@
package androidx.room.compiler.processing
import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.TestInvocation
import androidx.room.compiler.processing.util.runProcessorTest
+import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.ClassName
+import com.squareup.javapoet.JavaFile
import com.squareup.javapoet.TypeName
+import com.squareup.javapoet.TypeSpec
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import javax.lang.model.element.Modifier
@RunWith(JUnit4::class)
class XProcessingEnvTest {
@Test
fun getElement() {
- runProcessorTest(
+ runProcessorTestIncludingKsp(
listOf(
Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
public class Baz {
}
- """.trimIndent()
+ """.trimIndent()
)
)
) {
@@ -91,10 +97,11 @@
@Test
fun basic() {
- runProcessorTest(
+ runProcessorTestIncludingKsp(
listOf(
Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
public class Baz {
private void foo() {}
@@ -102,7 +109,7 @@
return 3;
}
}
- """.trimIndent()
+ """.trimIndent()
)
)
) {
@@ -111,22 +118,24 @@
assertThat(element.name).isEqualTo("Baz")
assertThat(element.asDeclaredType().typeName)
.isEqualTo(ClassName.get("foo.bar", "Baz"))
+ assertThat(element.findPrimaryConstructor()).isNull()
assertThat(element.getConstructors()).hasSize(1)
assertThat(element.getDeclaredMethods()).hasSize(2)
assertThat(element.kindName()).isEqualTo("class")
assertThat(element.isInterface()).isFalse()
- assertThat(element.superType?.typeName).isEqualTo(TypeName.OBJECT)
+ assertThat(element.superType?.typeName).isEqualTo(it.types.objectOrAny)
}
}
@Test
fun getPrimitives() {
val source = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
class Baz {
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
listOf(source)
@@ -141,14 +150,17 @@
@Test
fun nestedType() {
- val src = Source.java("foo.bar.Outer", """
+ val src = Source.java(
+ "foo.bar.Outer",
+ """
package foo.bar;
public class Outer {
public static class Inner {
}
}
- """.trimIndent())
- runProcessorTest(sources = listOf(src)) {
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(sources = listOf(src)) {
it.processingEnv.requireTypeElement("foo.bar.Outer.Inner").let {
val className = it.className
assertThat(className.packageName()).isEqualTo("foo.bar")
@@ -158,6 +170,50 @@
}
}
+ @Test
+ fun generateCode() {
+ val javaSrc = Source.java(
+ "foo.bar.AccessGenerated",
+ """
+ package foo.bar;
+ public class AccessGenerated {
+ ToBeGenerated x;
+ }
+ """.trimIndent()
+ )
+ val kotlinSrc = Source.kotlin(
+ "AccessGenerated.kt",
+ """
+ package foo.bar;
+ public class AccessGenerated(x: ToBeGenerated)
+ """.trimIndent()
+ )
+ listOf(javaSrc, kotlinSrc).forEach { src ->
+ fun runTest(block: (TestInvocation) -> Unit) {
+ // KSP does not support generated code access in java sources yet
+ // TODO remove this check once the bug is fixed.
+ // https://github.com/google/ksp/issues/119
+ if (src === javaSrc) {
+ runProcessorTest(sources = listOf(src), block)
+ } else {
+ runProcessorTestIncludingKsp(sources = listOf(src), block)
+ }
+ }
+ runTest { invocation ->
+ val className = ClassName.get("foo.bar", "ToBeGenerated")
+ if (invocation.processingEnv.findTypeElement(className) == null) {
+ // generate only if it doesn't exist to handle multi-round
+ val spec = TypeSpec.classBuilder(className)
+ .addModifiers(Modifier.PUBLIC)
+ .build()
+ JavaFile.builder(className.packageName(), spec)
+ .build()
+ .writeTo(invocation.processingEnv.filer)
+ }
+ }
+ }
+ }
+
companion object {
val PRIMITIVE_TYPES = mapOf(
TypeName.BOOLEAN.toString() to TypeName.BOOLEAN,
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt
index fb0a810..facdd453 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt
@@ -61,7 +61,8 @@
}
}
val main = JavaFileObjects.forSourceString(
- "foo.bar.Main", """
+ "foo.bar.Main",
+ """
package foo.bar;
import androidx.room.compiler.processing.testcode.*;
@MainAnnotation(
@@ -72,16 +73,17 @@
)
class Main {
}
- """.trimIndent()
+ """.trimIndent()
)
val other = JavaFileObjects.forSourceString(
- "foo.bar.Other", """
+ "foo.bar.Other",
+ """
package foo.bar;
import androidx.room.compiler.processing.testcode.*;
@OtherAnnotation("x")
class Other {
}
- """.trimIndent()
+ """.trimIndent()
)
assertAbout(
JavaSourcesSubjectFactory.javaSources()
@@ -112,9 +114,11 @@
elementsByAnnotation[MainAnnotation::class]?.forEach {
val className = ClassName.get(it.packageName, "${it.name}_Impl")
val spec = TypeSpec.classBuilder(className)
- .addAnnotation(AnnotationSpec.builder(OtherAnnotation::class.java).apply {
- addMember("value", "\"foo\"")
- }.build())
+ .addAnnotation(
+ AnnotationSpec.builder(OtherAnnotation::class.java).apply {
+ addMember("value", "\"foo\"")
+ }.build()
+ )
.build()
JavaFile.builder(className.packageName(), spec)
.build()
@@ -131,7 +135,8 @@
}
}
val main = JavaFileObjects.forSourceString(
- "foo.bar.Main", """
+ "foo.bar.Main",
+ """
package foo.bar;
import androidx.room.compiler.processing.testcode.*;
@MainAnnotation(
@@ -142,7 +147,7 @@
)
class Main {
}
- """.trimIndent()
+ """.trimIndent()
)
assertAbout(
JavaSourcesSubjectFactory.javaSources()
@@ -187,9 +192,11 @@
elementsByAnnotation[MainAnnotation::class]?.forEach {
val className = ClassName.get(it.packageName, "${it.name}_Impl")
val spec = TypeSpec.classBuilder(className)
- .addAnnotation(AnnotationSpec.builder(OtherAnnotation::class.java).apply {
- addMember("value", "\"foo\"")
- }.build())
+ .addAnnotation(
+ AnnotationSpec.builder(OtherAnnotation::class.java).apply {
+ addMember("value", "\"foo\"")
+ }.build()
+ )
.build()
JavaFile.builder(className.packageName(), spec)
.build()
@@ -203,7 +210,8 @@
}
}
val main = JavaFileObjects.forSourceString(
- "foo.bar.Main", """
+ "foo.bar.Main",
+ """
package foo.bar;
import androidx.room.compiler.processing.testcode.*;
@MainAnnotation(
@@ -214,7 +222,7 @@
)
class Main {
}
- """.trimIndent()
+ """.trimIndent()
)
assertAbout(
JavaSourcesSubjectFactory.javaSources()
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
index 9ef6eea..9c74318 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
@@ -36,14 +36,15 @@
@Test
fun declaredTypeArguments() {
val parent = Source.java(
- "foo.bar.Parent", """
+ "foo.bar.Parent",
+ """
package foo.bar;
import java.io.InputStream;
import java.util.Set;
class Parent<InputStreamType extends InputStream> {
public void wildcardParam(Set<?> param1) {}
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
sources = listOf(parent)
@@ -116,12 +117,13 @@
@Test
fun sameType() {
val subject = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
interface Baz {
void method(String... inputs);
}
- """.trimIndent()
+ """.trimIndent()
)
runProcessorTest(
sources = listOf(subject)
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtilsTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtilsTest.kt
index 0534136..8a3c47f 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtilsTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/JvmDescriptorUtilsTest.kt
@@ -238,7 +238,8 @@
@Describe
DataClass method2() { return null; }
}
- """.toJFO("androidx.room.test.DummyClass"), extraJfo
+ """.toJFO("androidx.room.test.DummyClass"),
+ extraJfo
) { descriptors ->
assertThat(descriptors).isEqualTo(
setOf(
@@ -284,7 +285,8 @@
@Describe
DataClass.StaticInnerData method4() { return null; }
}
- """.toJFO("androidx.room.test.DummyClass"), extraJfo
+ """.toJFO("androidx.room.test.DummyClass"),
+ extraJfo
) { descriptors ->
assertThat(descriptors).isEqualTo(
setOf(
@@ -323,7 +325,8 @@
@Describe
void method4(int... array) { }
}
- """.toJFO("androidx.room.test.DummyClass"), extraJfo
+ """.toJFO("androidx.room.test.DummyClass"),
+ extraJfo
) { descriptors ->
assertThat(descriptors).isEqualTo(
setOf(
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt
index 6f3b3bf..87b4c7b 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt
@@ -33,7 +33,9 @@
@Test
fun constructorParameters() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
class Subject() {
constructor(
nullableString: String?,
@@ -41,7 +43,8 @@
nonNullInt: Int,
vararg nonNullVarArgs: Int ): this()
}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { processingEnv ->
val (testClassElement, metadataElement) = getMetadataElement(
processingEnv,
@@ -60,9 +63,11 @@
}
metadataElement.getConstructorMetadata(fourArgConstructor).let { constructor ->
assertThat(constructor?.isPrimary()).isFalse()
- assertThat(constructor?.parameters?.map {
- it.name to it.isNullable()
- }).containsExactly(
+ assertThat(
+ constructor?.parameters?.map {
+ it.name to it.isNullable()
+ }
+ ).containsExactly(
"nullableString" to true,
"nonNullBoolean" to false,
"nonNullInt" to false,
@@ -75,7 +80,9 @@
@Test
fun getParameterNames() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
class Subject {
fun functionWithParams(
nullableString: String?,
@@ -90,7 +97,8 @@
vararg nullableVarargs : Int?) {
}
}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { processingEnv ->
val (testClassElement, metadataElement) = getMetadataElement(
processingEnv,
@@ -131,11 +139,14 @@
@Test
fun findPrimaryConstructorSignature() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
class Subject(val constructorParam: String) {
constructor() : this("anything")
}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { invocation ->
val (testClassElement, metadataElement) = getMetadataElement(
invocation,
@@ -155,7 +166,9 @@
@Test
fun isSuspendFunction() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
class Subject(val constructorParam: String) {
constructor() : this("anything")
fun emptyFunction() {}
@@ -166,15 +179,18 @@
fun suspendFunctionWithParams(suspendParam1: String) {
}
}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { invocation ->
val (testClassElement, metadataElement) = getMetadataElement(
invocation,
"Subject"
)
- assertThat(testClassElement.getDeclaredMethods().map {
- it.simpleName.toString() to metadataElement.getFunctionMetadata(it)?.isSuspend()
- }).containsExactly(
+ assertThat(
+ testClassElement.getDeclaredMethods().map {
+ it.simpleName.toString() to metadataElement.getFunctionMetadata(it)?.isSuspend()
+ }
+ ).containsExactly(
"emptyFunction" to false,
"suspendFunction" to true,
"functionWithParams" to false,
@@ -186,11 +202,14 @@
@Test
fun isObject() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
class KotlinClass
interface KotlinInterface
object AnObject
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { invocation ->
val (_, objectTypeMetadata) = getMetadataElement(invocation, "AnObject")
assertThat(objectTypeMetadata.isObject()).isTrue()
@@ -203,12 +222,15 @@
@Test
fun methods_genericReturnTypeNullability() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
interface Subject {
fun nonNullList() : List<Any>
fun nullableList() : List<Any?>
}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { invocation ->
val (testDaoElement, testDaoMetadata) = getMetadataElement(
invocation,
@@ -229,7 +251,9 @@
@Test
fun properties() {
- val src = Source.kotlin("Properties.kt", """
+ val src = Source.kotlin(
+ "Properties.kt",
+ """
class Properties {
val nonNull:String = ""
val nullable:String? = null
@@ -237,7 +261,8 @@
val nonNullTypeArgument:List<Int> = emptyList()
val multipleTypeArguments:Map<String, Any?> = emptyMap()
}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { invocation ->
val (_, testMetadata) = getMetadataElement(
invocation,
@@ -281,7 +306,9 @@
@Test
fun genericParameterNullability() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
class Subject(
nonNullGenericWithNonNullParam : List<Int>,
nonNullGenericWithNullableParam : List<Int?>,
@@ -295,20 +322,23 @@
nullableGenericWithNonNullParam : List<Int>?
) {}
}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { invocation ->
val (testDaoElement, testDaoMetadata) = getMetadataElement(
invocation,
"Subject"
)
fun assertParams(params: List<KmValueParameter>?) {
- assertThat(params?.map {
- Triple(
- it.name,
- it.isNullable(),
- it.type.typeArguments.first().isNullable()
- )
- }).containsExactly(
+ assertThat(
+ params?.map {
+ Triple(
+ it.name,
+ it.isNullable(),
+ it.type.typeArguments.first().isNullable()
+ )
+ }
+ ).containsExactly(
Triple("nonNullGenericWithNonNullParam", false, false),
Triple("nonNullGenericWithNullableParam", false, true),
Triple("nullableGenericWithNullableParam", true, true),
@@ -330,14 +360,17 @@
@Test
fun kotlinArrayKmType() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
interface Subject {
val nullableArrayWithNonNullComponent : Array<Int>?
val nullableArrayWithNullableComponent : Array<Int?>?
val nonNullArrayWithNonNullComponent : Array<Int>
val nonNullArrayWithNullableComponent : Array<Int?>
}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { invocation ->
val (_, metadata) = getMetadataElement(
invocation,
@@ -366,7 +399,9 @@
@Test
fun kotlinClassMetadataToKmType() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
class Simple {
}
class TwoArgGeneric<Arg1, Arg2>{
@@ -378,7 +413,8 @@
}
abstract class WithSuperType : Map<String, Int?> {}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { invocation ->
val (_, simple) = getMetadataElement(invocation, "Simple")
assertThat(simple.kmType.isNullable()).isFalse()
@@ -403,13 +439,16 @@
@Test
fun erasure() {
- val src = Source.kotlin("Subject.kt", """
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
object Subject {
val simple : String = "foo"
val nullableGeneric: List<Int>? = TODO()
val nonNullGeneric: List<Int> = TODO()
}
- """.trimIndent())
+ """.trimIndent()
+ )
simpleRun(listOf(src)) { invocation ->
val (_, subject) = getMetadataElement(invocation, "Subject")
subject.getPropertyMetadata("simple")!!.type.erasure().let {
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSAsMemberOfTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSAsMemberOfTest.kt
index b727e3d..90816ee 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSAsMemberOfTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSAsMemberOfTest.kt
@@ -36,7 +36,8 @@
@Test
fun asMemberOfInheritance() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
open class BaseClass<T, R>(val genericProp : T) {
val listOfGeneric : List<T> = TODO()
val mapOfStringToGeneric2 : Map<String, R> = TODO()
@@ -45,7 +46,7 @@
class SubClass(x : Int) : BaseClass<Int, List<String>>(x) {
val subClassProp : String = "abc"
}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
@@ -85,7 +86,8 @@
@Test
fun asMemberOfNullabilityResolution() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
open class MyInterface<T> {
val inheritedProp: T = TODO()
var nullableProp: T? = TODO()
@@ -94,7 +96,7 @@
}
abstract class NonNullSubject : MyInterface<String>()
abstract class NullableSubject: MyInterface<String?>()
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val myInterface = invocation.requireClass("MyInterface")
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt
index 06ad1de..9797393 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt
@@ -39,7 +39,8 @@
@Test
fun kotlinTypeName() {
val subjectSrc = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
package foo.bar;
import kotlin.collections.*
class Baz {
@@ -50,7 +51,7 @@
class Nested {
}
}
- """.trimIndent()
+ """.trimIndent()
)
runTest(subjectSrc) { resolver ->
val subject = resolver.requireClass("foo.bar.Baz")
@@ -81,7 +82,8 @@
@Test
fun javaTypeName() {
val subjectSrc = Source.java(
- "Baz", """
+ "Baz",
+ """
import java.util.List;
class Baz {
int intField;
@@ -91,7 +93,7 @@
static class Nested {
}
}
- """.trimIndent()
+ """.trimIndent()
)
runTest(subjectSrc) { resolver ->
val subject = resolver.requireClass("Baz")
@@ -116,14 +118,15 @@
@Test
fun kotlinErrorType() {
val subjectSrc = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
import kotlin.collections.*
class Foo {
val errorField : DoesNotExist = TODO()
val listOfError : List<DoesNotExist> = TODO()
val mutableMapOfDontExist : MutableMap<String, DoesNotExist> = TODO()
}
- """.trimIndent()
+ """.trimIndent()
)
runTest(subjectSrc, succeed = false) { resolver ->
val subject = resolver.requireClass("Foo")
@@ -153,7 +156,8 @@
@Test
fun kaptGoldenTest() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
class MyType
class MyGeneric<T>
class Subject {
@@ -169,7 +173,7 @@
fun method7(): MyGeneric<MyType> = TODO()
fun method8(): MyGeneric<*> = TODO()
}
- """.trimIndent()
+ """.trimIndent()
)
// methodName -> returnType, ...paramTypes
val golden = mutableMapOf<String, List<TypeName>>()
@@ -181,9 +185,9 @@
val subject = env.delegate.elementUtils.getTypeElement("Subject")
ElementFilter.methodsIn(subject.enclosedElements).map { method ->
val types = listOf(method.returnType.safeTypeName()) +
- method.parameters.map {
- it.asType().safeTypeName()
- }
+ method.parameters.map {
+ it.asType().safeTypeName()
+ }
golden[method.simpleName.toString()] = types
}
}
@@ -196,9 +200,9 @@
val subject = env.resolver.requireClass("Subject")
subject.getDeclaredFunctions().forEach { method ->
val types = listOf(method.returnType.typeName()) +
- method.parameters.map {
- it.type.typeName()
- }
+ method.parameters.map {
+ it.type.typeName()
+ }
kspResults[method.simpleName.asString()] = types
}
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt
index 8960503..382e5b9 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt
@@ -31,11 +31,12 @@
@Test
fun simple() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
class Foo {
val intField: Int = 0
}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val fooElement = invocation.processingEnv.requireTypeElement("Foo")
@@ -51,13 +52,14 @@
@Test
fun asMemberOf() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
open class Base<T, R> {
val t : T = TODO()
val listOfR : List<R> = TODO()
}
class Sub1 : Base<Int, String>()
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val sub = invocation.processingEnv.requireTypeElement("Sub1")
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
index aee68b6..4619424 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
@@ -26,6 +26,8 @@
import androidx.room.compiler.processing.util.getField
import androidx.room.compiler.processing.util.getMethod
import androidx.room.compiler.processing.util.runKspTest
+import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.ParameterizedTypeName
@@ -38,15 +40,17 @@
@Test
fun qualifiedNames() {
val src1 = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
class TopLevel
- """.trimIndent()
+ """.trimIndent()
)
val src2 = Source.kotlin(
- "Bar.kt", """
+ "Bar.kt",
+ """
package foo.bar
class InFooBar
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
sources = listOf(src1, src2),
@@ -80,13 +84,14 @@
@Test
fun typeAndSuperType() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
package foo.bar;
class Baz : MyInterface, AbstractClass() {
}
abstract class AbstractClass {}
interface MyInterface {}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
invocation.processingEnv.requireTypeElement("foo.bar.Baz").let {
@@ -121,12 +126,13 @@
@Test
fun nestedClassName() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
package foo.bar;
class Outer {
class Inner
}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
invocation.processingEnv.requireTypeElement("foo.bar.Outer").let {
@@ -147,14 +153,15 @@
@Test
fun modifiers() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
open class OpenClass
abstract class AbstractClass
object MyObject
interface MyInterface
class Final
private class PrivateClass
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
fun getModifiers(element: XTypeElement): Set<String> {
@@ -192,10 +199,11 @@
@Test
fun kindName() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
class MyClass
interface MyInterface
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
invocation.processingEnv.requireTypeElement("MyClass").let {
@@ -210,12 +218,13 @@
@Test
fun fieldBasic() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
open class BaseClass<T>(val genericProp : T)
class SubClass(x : Int) : BaseClass<Int>(x) {
val subClassProp : String = "abc"
}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val baseClass = invocation.processingEnv.requireTypeElement("BaseClass")
@@ -234,14 +243,15 @@
@Test
fun fieldsOverride() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
open class BaseClass(
open val value : List<Int>
)
class SubClass(
override val value : MutableList<Int>
) : BaseClass(value)
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val baseClass = invocation.processingEnv.requireTypeElement("BaseClass")
@@ -264,7 +274,8 @@
@Test
fun declaredAndInstanceMethods() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
open class Base(x:Int) {
open fun baseFun(): Int = TODO()
suspend fun suspendFun(): Int = TODO()
@@ -288,16 +299,18 @@
fun staticFun(): Int = TODO()
}
}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val base = invocation.processingEnv.requireTypeElement("Base")
assertThat(base.getDeclaredMethods().names()).containsExactly(
- "baseFun", "suspendFun", "privateBaseFun", "staticBaseFun")
+ "baseFun", "suspendFun", "privateBaseFun", "staticBaseFun"
+ )
val sub = invocation.processingEnv.requireTypeElement("SubClass")
assertThat(sub.getDeclaredMethods().names()).containsExactly(
- "baseFun", "subFun", "privateSubFun", "staticFun")
+ "baseFun", "subFun", "privateSubFun", "staticFun"
+ )
assertThat(sub.getAllNonPrivateInstanceMethods().names()).containsExactly(
"baseFun", "suspendFun", "subFun"
)
@@ -307,7 +320,8 @@
@Test
fun allMethods() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
open class Base(x:Int) {
constructor(x:Int, y:Int): this(x) {
}
@@ -339,7 +353,7 @@
fun subCompanionMethod(): Int = TODO()
}
}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val klass = invocation.processingEnv.requireTypeElement("SubClass")
@@ -352,7 +366,9 @@
@Test
fun gettersSetters() {
- val src = Source.kotlin("Foo.kt", """
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
open class JustGetter(val x:Int) {
private val invisible:Int = TODO()
private var invisibleMutable:Int = TODO()
@@ -361,7 +377,8 @@
private val subInvisible:Int = TODO()
private var subInvisibleMutable:Int = TODO()
}
- """.trimIndent())
+ """.trimIndent()
+ )
runKspTest(sources = listOf(src), succeed = true) { invocation ->
invocation.processingEnv.requireTypeElement("JustGetter").let { base ->
assertThat(base.getDeclaredMethods().names()).containsExactly(
@@ -390,7 +407,9 @@
@Test
fun gettersSetters_companion() {
- val src = Source.kotlin("Foo.kt", """
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
open class CompanionSubject {
companion object {
@JvmStatic
@@ -401,7 +420,8 @@
}
}
class SubClass : CompanionSubject()
- """.trimIndent())
+ """.trimIndent()
+ )
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val subject = invocation.processingEnv.requireTypeElement("CompanionSubject")
assertThat(subject.getDeclaredMethods().names()).containsExactly(
@@ -421,14 +441,17 @@
@Test
fun gettersSetters_interface() {
- val src = Source.kotlin("Foo.kt", """
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
interface JustGetter {
val x:Int
}
interface GetterSetter : JustGetter {
var y:Int
}
- """.trimIndent())
+ """.trimIndent()
+ )
runKspTest(sources = listOf(src), succeed = true) { invocation ->
invocation.processingEnv.requireTypeElement("JustGetter").let { base ->
assertThat(base.getDeclaredMethods().names()).containsExactly(
@@ -458,8 +481,10 @@
@Test
fun constructors() {
val src = Source.kotlin(
- "Foo.kt", """
+ "Foo.kt",
+ """
interface MyInterface
+ class NoExplicitConstructor
open class Base(x:Int)
open class ExplicitConstructor {
constructor(x:Int)
@@ -472,36 +497,66 @@
constructor(list:List<String>): this()
constructor(list:List<String>, x:Int): this()
}
- """.trimIndent()
+ abstract class AbstractNoExplicit
+ abstract class AbstractExplicit(x:Int)
+ """.trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
- val constructorCounts = listOf(
- "MyInterface", "Base", "ExplicitConstructor", "BaseWithSecondary", "Sub",
- "SubWith3Constructors"
- ).map {
+ runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ val subjects = listOf(
+ "MyInterface", "NoExplicitConstructor", "Base", "ExplicitConstructor",
+ "BaseWithSecondary", "Sub", "SubWith3Constructors",
+ "AbstractNoExplicit", "AbstractExplicit"
+ )
+ val constructorCounts = subjects.map {
it to invocation.processingEnv.requireTypeElement(it).getConstructors().size
}
assertThat(constructorCounts)
.containsExactly(
"MyInterface" to 0,
+ "NoExplicitConstructor" to 1,
"Base" to 1,
"ExplicitConstructor" to 1,
"BaseWithSecondary" to 2,
"Sub" to 1,
- "SubWith3Constructors" to 3
+ "SubWith3Constructors" to 3,
+ "AbstractNoExplicit" to 1,
+ "AbstractExplicit" to 1
+ )
+
+ val primaryConstructorParameterNames = subjects.map {
+ it to invocation.processingEnv.requireTypeElement(it)
+ .findPrimaryConstructor()
+ ?.parameters?.map {
+ it.name
+ }
+ }
+ assertThat(primaryConstructorParameterNames)
+ .containsExactly(
+ "MyInterface" to null,
+ "NoExplicitConstructor" to emptyList<String>(),
+ "Base" to listOf("x"),
+ "ExplicitConstructor" to null,
+ "BaseWithSecondary" to listOf("x"),
+ "Sub" to listOf("x"),
+ "SubWith3Constructors" to emptyList<String>(),
+ "AbstractNoExplicit" to emptyList<String>(),
+ "AbstractExplicit" to listOf("x")
)
}
}
@Test
fun jvmDefault() {
- val src = Source.kotlin("Foo.kt", """
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
interface MyInterface {
fun notJvmDefault()
@JvmDefault
fun jvmDefault()
}
- """.trimIndent())
+ """.trimIndent()
+ )
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val subject = invocation.processingEnv.requireTypeElement("MyInterface")
assertThat(subject.getMethod("notJvmDefault").isJavaDefault()).isFalse()
@@ -509,6 +564,76 @@
}
}
+ @Test
+ fun constructors_java() {
+ val src = Source.java(
+ "Source",
+ """
+ import java.util.List;
+ interface MyInterface {}
+ class NoExplicitConstructor{}
+ class Base {
+ Base(int x){}
+ }
+ class ExplicitConstructor {
+ ExplicitConstructor(int x){}
+ }
+ class BaseWithSecondary {
+ BaseWithSecondary(int x){}
+ BaseWithSecondary(String y){}
+ }
+ class Sub extends Base {
+ Sub(int x) {
+ super(x);
+ }
+ }
+ class SubWith3Constructors extends BaseWithSecondary {
+ SubWith3Constructors() {
+ super(3);
+ }
+ SubWith3Constructors(List<String> list) {
+ super(3);
+ }
+ SubWith3Constructors(List<String> list, int x) {
+ super(3);
+ }
+ }
+ abstract class AbstractNoExplicit {}
+ abstract class AbstractExplicit {
+ AbstractExplicit(int x) {}
+ }
+ """.trimIndent()
+ )
+ runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ val subjects = listOf(
+ "MyInterface", "NoExplicitConstructor", "Base", "ExplicitConstructor",
+ "BaseWithSecondary", "Sub", "SubWith3Constructors",
+ "AbstractNoExplicit", "AbstractExplicit"
+ )
+ val constructorCounts = subjects.map {
+ it to invocation.processingEnv.requireTypeElement(it).getConstructors().size
+ }
+ assertThat(constructorCounts)
+ .containsExactly(
+ "MyInterface" to 0,
+ "NoExplicitConstructor" to 1,
+ "Base" to 1,
+ "ExplicitConstructor" to 1,
+ "BaseWithSecondary" to 2,
+ "Sub" to 1,
+ "SubWith3Constructors" to 3,
+ "AbstractNoExplicit" to 1,
+ "AbstractExplicit" to 1
+ )
+
+ subjects.forEach {
+ Truth.assertWithMessage(it)
+ .that(invocation.processingEnv.requireTypeElement(it).findPrimaryConstructor())
+ .isNull()
+ }
+ }
+ }
+
private fun List<XMethodElement>.names() = map {
it.name
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
index e5e3b0a..08c9de1 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
@@ -36,13 +36,14 @@
@Test
fun assignability() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
package foo.bar;
class Baz : AbstractClass(), MyInterface {
}
abstract class AbstractClass {}
interface MyInterface {}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(listOf(src), succeed = true) {
val subject = it.processingEnv.requireType("foo.bar.Baz")
@@ -75,11 +76,12 @@
@Test
fun errorType() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
package foo.bar;
val errorType : IDontExist = TODO()
val listOfErrorType : List<IDontExist> = TODO()
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -106,11 +108,12 @@
@Test
fun typeArguments() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
package foo.bar;
val listOfNullableStrings : List<String?> = TODO()
val listOfInts : List<Int> = TODO()
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -153,7 +156,8 @@
@Test
fun equality() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
package foo.bar;
val listOfNullableStrings : List<String?> = TODO()
val listOfNullableStrings_2 : List<String?> = TODO()
@@ -161,7 +165,7 @@
val listOfNonNullStrings_2 : List<String> = TODO()
val nullableString : String? = TODO()
val nonNullString : String = TODO()
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -197,13 +201,14 @@
@Test
fun rawType() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
package foo.bar;
val simple : Int = 0
val list : List<String> = TODO()
val map : Map<String, String> = TODO()
val listOfMaps : List<Map<String, String>> = TODO()
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -234,13 +239,14 @@
@Test
fun noneType() {
val src = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
public class Baz {
void voidMethod() {
}
}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(sources = listOf(src), succeed = true) { invocation ->
val resolver = (invocation.processingEnv as KspProcessingEnv).resolver
@@ -257,7 +263,8 @@
@Test
fun isTypeChecks() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
val intProp : Int = 0
val nullableIntProp : Int? = null
val longProp : Long = 0
@@ -266,7 +273,7 @@
val nullableByteProp :Byte? = null
val errorProp : IDontExist = TODO()
val nullableErrorProp : IDontExist? = TODO()
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -299,7 +306,8 @@
@Test
fun defaultValue() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
val intProp : Int = 3 // kotlin default value is unrelated, will be ignored
val nullableIntProp : Int? = null
val longProp : Long = 3
@@ -310,7 +318,7 @@
val errorProp : IDontExist = TODO()
val nullableErrorProp : IDontExist? = TODO()
val stringProp : String = "abc"
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -336,12 +344,13 @@
@Test
fun isTypeOf() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
val intProp : Int = 3
val longProp : Long = 3
val stringProp : String = "abc"
val listProp : List<String> = TODO()
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -383,7 +392,8 @@
@Test
fun isSameType() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
val intProp : Int = 3
val intProp2 : Int = 4
val longProp : Long = 0L
@@ -392,7 +402,7 @@
val listOfStrings2 : List<String> = TODO()
val listOfInts : List<Int> = TODO()
val listOfNullableStrings : List<String?> = TODO()
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -418,12 +428,13 @@
@Test
fun extendsBounds() {
val src = Source.kotlin(
- "foo.kt", """
+ "foo.kt",
+ """
open class Foo;
class Bar<T : Foo> {
}
class Bar_NullableFoo<T : Foo?>
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -453,14 +464,15 @@
@Test
fun wildcardJava() {
val src = Source.java(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
import java.util.List;
public class Baz {
private void wildcardMethod(List<? extends Number> list) {
}
}
- """.trimIndent()
+ """.trimIndent()
)
runKspTest(
listOf(src),
@@ -486,9 +498,11 @@
val prop = file.declarations.first {
it.simpleName.asString() == name
} as KSPropertyDeclaration
- return checkNotNull(prop.type?.let {
- wrap(it)
- }) {
+ return checkNotNull(
+ prop.type?.let {
+ wrap(it)
+ }
+ ) {
"cannot find type for $name"
}
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/KotlinTypeNames.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/KotlinTypeNames.kt
index 32d77be..6b4198d 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/KotlinTypeNames.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/KotlinTypeNames.kt
@@ -22,9 +22,11 @@
val ANY_CLASS_NAME = ClassName.get("kotlin", "Any")
val UNIT_CLASS_NAME = ClassName.get("kotlin", "Unit")
val INT_CLASS_NAME = ClassName.get("kotlin", "Int")
+ val LONG_CLASS_NAME = ClassName.get("kotlin", "Long")
val STRING_CLASS_NAME = ClassName.get("kotlin", "String")
val LIST_CLASS_NAME = ClassName.get("kotlin.collections", "List")
val MUTABLELIST_CLASS_NAME = ClassName.get("kotlin.collections", "MutableList")
val MAP_CLASS_NAME = ClassName.get("kotlin.collections", "Map")
val PAIR_CLASS_NAME = ClassName.get(Pair::class.java)
+ val CONTINUATION_CLASS_NAME = ClassName.get("kotlin.coroutines", "Continuation")
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
index 57848c9..5db3d82 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
@@ -103,10 +103,13 @@
val sources = if (sources.isEmpty()) {
// synthesize a source to trigger compilation
listOf(
- Source.java("foo.bar.SyntheticSource", """
+ Source.java(
+ "foo.bar.SyntheticSource",
+ """
package foo.bar;
public class SyntheticSource {}
- """.trimIndent())
+ """.trimIndent()
+ )
)
} else {
sources
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/TestInvocation.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/TestInvocation.kt
index 9398adf..d6778c1 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/TestInvocation.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/util/TestInvocation.kt
@@ -25,6 +25,8 @@
class TestInvocation(
val processingEnv: XProcessingEnv
) {
+ val isKsp = processingEnv is KspProcessingEnv
+
val kspResolver: Resolver
get() = (processingEnv as KspProcessingEnv).resolver
@@ -35,7 +37,9 @@
voidOrUnit = KotlinTypeNames.UNIT_CLASS_NAME,
objectOrAny = KotlinTypeNames.ANY_CLASS_NAME,
boxedInt = KotlinTypeNames.INT_CLASS_NAME,
- int = KotlinTypeNames.INT_CLASS_NAME
+ int = KotlinTypeNames.INT_CLASS_NAME,
+ long = KotlinTypeNames.LONG_CLASS_NAME,
+ list = KotlinTypeNames.LIST_CLASS_NAME
)
} else {
Types(
@@ -43,7 +47,9 @@
voidOrUnit = TypeName.VOID,
objectOrAny = TypeName.OBJECT,
boxedInt = TypeName.INT.box(),
- int = TypeName.INT
+ int = TypeName.INT,
+ long = TypeName.LONG,
+ list = ClassName.get("java.util", "List")
)
}
}
@@ -57,6 +63,8 @@
val voidOrUnit: TypeName,
val objectOrAny: ClassName,
val boxedInt: TypeName,
- val int: TypeName
+ val int: TypeName,
+ val long: TypeName,
+ val list: ClassName
)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt
index a3dc81f..3babfd8 100644
--- a/room/compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt
@@ -33,22 +33,22 @@
val W = "\$W"
val KClass<*>.typeName: ClassName
- get() = ClassName.get(this.java)
+ get() = ClassName.get(this.java)
val KClass<*>.arrayTypeName: ArrayTypeName
- get() = ArrayTypeName.of(typeName)
+ get() = ArrayTypeName.of(typeName)
object SupportDbTypeNames {
val DB: ClassName = ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteDatabase")
val SQLITE_STMT: ClassName =
- ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteStatement")
+ ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteStatement")
val SQLITE_OPEN_HELPER: ClassName =
- ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteOpenHelper")
+ ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteOpenHelper")
val SQLITE_OPEN_HELPER_CALLBACK: ClassName =
- ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteOpenHelper.Callback")
+ ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteOpenHelper.Callback")
val SQLITE_OPEN_HELPER_CONFIG: ClassName =
- ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteOpenHelper.Configuration")
+ ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteOpenHelper.Configuration")
val QUERY: ClassName =
- ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteQuery")
+ ClassName.get("$SQLITE_PACKAGE.db", "SupportSQLiteQuery")
}
object RoomTypeNames {
@@ -57,58 +57,60 @@
val ROOM_DB_KT: ClassName = ClassName.get(ROOM_PACKAGE, "RoomDatabaseKt")
val ROOM_DB_CONFIG: ClassName = ClassName.get(ROOM_PACKAGE, "DatabaseConfiguration")
val INSERTION_ADAPTER: ClassName =
- ClassName.get(ROOM_PACKAGE, "EntityInsertionAdapter")
+ ClassName.get(ROOM_PACKAGE, "EntityInsertionAdapter")
val DELETE_OR_UPDATE_ADAPTER: ClassName =
- ClassName.get(ROOM_PACKAGE, "EntityDeletionOrUpdateAdapter")
+ ClassName.get(ROOM_PACKAGE, "EntityDeletionOrUpdateAdapter")
val SHARED_SQLITE_STMT: ClassName =
- ClassName.get(ROOM_PACKAGE, "SharedSQLiteStatement")
+ ClassName.get(ROOM_PACKAGE, "SharedSQLiteStatement")
val INVALIDATION_TRACKER: ClassName =
- ClassName.get(ROOM_PACKAGE, "InvalidationTracker")
+ ClassName.get(ROOM_PACKAGE, "InvalidationTracker")
val INVALIDATION_OBSERVER: ClassName =
- ClassName.get("$ROOM_PACKAGE.InvalidationTracker", "Observer")
+ ClassName.get("$ROOM_PACKAGE.InvalidationTracker", "Observer")
val ROOM_SQL_QUERY: ClassName =
- ClassName.get(ROOM_PACKAGE, "RoomSQLiteQuery")
+ ClassName.get(ROOM_PACKAGE, "RoomSQLiteQuery")
val OPEN_HELPER: ClassName =
- ClassName.get(ROOM_PACKAGE, "RoomOpenHelper")
+ ClassName.get(ROOM_PACKAGE, "RoomOpenHelper")
val OPEN_HELPER_DELEGATE: ClassName =
- ClassName.get(ROOM_PACKAGE, "RoomOpenHelper.Delegate")
+ ClassName.get(ROOM_PACKAGE, "RoomOpenHelper.Delegate")
val OPEN_HELPER_VALIDATION_RESULT: ClassName =
- ClassName.get(ROOM_PACKAGE, "RoomOpenHelper.ValidationResult")
+ ClassName.get(ROOM_PACKAGE, "RoomOpenHelper.ValidationResult")
val TABLE_INFO: ClassName =
- ClassName.get("$ROOM_PACKAGE.util", "TableInfo")
+ ClassName.get("$ROOM_PACKAGE.util", "TableInfo")
val TABLE_INFO_COLUMN: ClassName =
- ClassName.get("$ROOM_PACKAGE.util", "TableInfo.Column")
+ ClassName.get("$ROOM_PACKAGE.util", "TableInfo.Column")
val TABLE_INFO_FOREIGN_KEY: ClassName =
- ClassName.get("$ROOM_PACKAGE.util", "TableInfo.ForeignKey")
+ ClassName.get("$ROOM_PACKAGE.util", "TableInfo.ForeignKey")
val TABLE_INFO_INDEX: ClassName =
- ClassName.get("$ROOM_PACKAGE.util", "TableInfo.Index")
+ ClassName.get("$ROOM_PACKAGE.util", "TableInfo.Index")
val FTS_TABLE_INFO: ClassName =
- ClassName.get("$ROOM_PACKAGE.util", "FtsTableInfo")
+ ClassName.get("$ROOM_PACKAGE.util", "FtsTableInfo")
val VIEW_INFO: ClassName =
- ClassName.get("$ROOM_PACKAGE.util", "ViewInfo")
+ ClassName.get("$ROOM_PACKAGE.util", "ViewInfo")
val LIMIT_OFFSET_DATA_SOURCE: ClassName =
- ClassName.get("$ROOM_PACKAGE.paging", "LimitOffsetDataSource")
+ ClassName.get("$ROOM_PACKAGE.paging", "LimitOffsetDataSource")
val DB_UTIL: ClassName =
- ClassName.get("$ROOM_PACKAGE.util", "DBUtil")
+ ClassName.get("$ROOM_PACKAGE.util", "DBUtil")
val CURSOR_UTIL: ClassName =
- ClassName.get("$ROOM_PACKAGE.util", "CursorUtil")
+ ClassName.get("$ROOM_PACKAGE.util", "CursorUtil")
}
object PagingTypeNames {
val DATA_SOURCE: ClassName =
- ClassName.get(PAGING_PACKAGE, "DataSource")
+ ClassName.get(PAGING_PACKAGE, "DataSource")
val POSITIONAL_DATA_SOURCE: ClassName =
- ClassName.get(PAGING_PACKAGE, "PositionalDataSource")
+ ClassName.get(PAGING_PACKAGE, "PositionalDataSource")
val DATA_SOURCE_FACTORY: ClassName =
- ClassName.get(PAGING_PACKAGE, "DataSource", "Factory")
+ ClassName.get(PAGING_PACKAGE, "DataSource", "Factory")
val PAGING_SOURCE: ClassName =
- ClassName.get(PAGING_PACKAGE, "PagingSource")
+ ClassName.get(PAGING_PACKAGE, "PagingSource")
}
object LifecyclesTypeNames {
val LIVE_DATA: ClassName = ClassName.get(LIFECYCLE_PACKAGE, "LiveData")
- val COMPUTABLE_LIVE_DATA: ClassName = ClassName.get(LIFECYCLE_PACKAGE,
- "ComputableLiveData")
+ val COMPUTABLE_LIVE_DATA: ClassName = ClassName.get(
+ LIFECYCLE_PACKAGE,
+ "ComputableLiveData"
+ )
}
object AndroidTypeNames {
@@ -207,13 +209,15 @@
callBody: MethodSpec.Builder.() -> Unit
) = TypeSpec.anonymousClassBuilder("").apply {
superclass(ParameterizedTypeName.get(Callable::class.typeName, parameterTypeName))
- addMethod(MethodSpec.methodBuilder("call").apply {
- returns(parameterTypeName)
- addException(Exception::class.typeName)
- addModifiers(Modifier.PUBLIC)
- addAnnotation(Override::class.java)
- callBody()
- }.build())
+ addMethod(
+ MethodSpec.methodBuilder("call").apply {
+ returns(parameterTypeName)
+ addException(Exception::class.typeName)
+ addModifiers(Modifier.PUBLIC)
+ addAnnotation(Override::class.java)
+ callBody()
+ }.build()
+ )
}
fun Function1TypeSpecBuilder(
@@ -229,11 +233,13 @@
returnTypeName
)
)
- addMethod(MethodSpec.methodBuilder("invoke").apply {
- addParameter(parameterTypeName, parameterName)
- returns(returnTypeName)
- addModifiers(Modifier.PUBLIC)
- addAnnotation(Override::class.java)
- callBody()
- }.build())
+ addMethod(
+ MethodSpec.methodBuilder("invoke").apply {
+ addParameter(parameterTypeName, parameterName)
+ returns(returnTypeName)
+ addModifiers(Modifier.PUBLIC)
+ addAnnotation(Override::class.java)
+ callBody()
+ }.build()
+ )
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/string_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/string_ext.kt
index 2d537f0..7ef60c4 100644
--- a/room/compiler/src/main/kotlin/androidx/room/ext/string_ext.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/string_ext.kt
@@ -45,8 +45,8 @@
private val javaCharRegex = "[^a-zA-Z0-9]".toRegex()
fun String.stripNonJava(): String {
return this.split(javaCharRegex)
- .map(String::trim)
- .joinToCamelCaseAsVar()
+ .map(String::trim)
+ .joinToCamelCaseAsVar()
}
// TODO: Replace this with the function from the Kotlin stdlib once the API becomes stable
diff --git a/room/compiler/src/main/kotlin/androidx/room/log/RLog.kt b/room/compiler/src/main/kotlin/androidx/room/log/RLog.kt
index b7575e6..d18778e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/log/RLog.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/log/RLog.kt
@@ -78,9 +78,12 @@
class CollectingMessager : XMessager {
private val messages = mutableMapOf<Diagnostic.Kind, MutableList<Pair<String, XElement?>>>()
override fun printMessage(kind: Diagnostic.Kind, msg: String, element: XElement?) {
- messages.getOrPut(kind, {
- arrayListOf()
- }).add(Pair(msg, element))
+ messages.getOrPut(
+ kind,
+ {
+ arrayListOf()
+ }
+ ).add(Pair(msg, element))
}
fun hasErrors() = messages.containsKey(ERROR)
diff --git a/room/compiler/src/main/kotlin/androidx/room/parser/ParserErrors.kt b/room/compiler/src/main/kotlin/androidx/room/parser/ParserErrors.kt
index 4b07a62..68c2c8c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/parser/ParserErrors.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/parser/ParserErrors.kt
@@ -18,16 +18,16 @@
object ParserErrors {
val ANONYMOUS_BIND_ARGUMENT = "Room does not support ? as bind parameters. You must use" +
- " named bind arguments (e..g :argName)"
+ " named bind arguments (e..g :argName)"
val NOT_ONE_QUERY = "Must have exactly 1 query in the value of @Query or @DatabaseView"
fun invalidQueryType(type: QueryType): String {
return "$type query type is not supported yet. You can use:" +
- QueryType.SUPPORTED.joinToString(", ") { it.name }
+ QueryType.SUPPORTED.joinToString(", ") { it.name }
}
fun cannotUseVariableIndices(name: String, position: Int) = "Cannot use variable indices." +
- " Use named parameters instead (e.g. WHERE name LIKE :nameArg and lastName LIKE " +
- ":lastName). Problem: $name at $position"
+ " Use named parameters instead (e.g. WHERE name LIKE :nameArg and lastName LIKE " +
+ ":lastName). Problem: $name at $position"
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt b/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt
index 3dff9a7..2eb1e3c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/parser/SqlParser.kt
@@ -146,7 +146,8 @@
syntaxErrors = syntaxErrors,
runtimeQueryPlaceholder = false
)
- })
+ }
+ )
fun isValidIdentifier(input: String): Boolean =
input.isNotBlank() && INVALID_IDENTIFIER_CHARS.none { input.contains(it) }
@@ -204,12 +205,12 @@
}
private fun withBoxedTypes(env: XProcessingEnv, vararg primitives: TypeName):
- List<XType> {
- return primitives.flatMap {
- val primitiveType = env.requireType(it)
- listOf(primitiveType, primitiveType.boxed())
+ List<XType> {
+ return primitives.flatMap {
+ val primitiveType = env.requireType(it)
+ listOf(primitiveType, primitiveType.boxed())
+ }
}
- }
companion object {
fun fromAnnotationValue(value: Int?): SQLTypeAffinity? {
diff --git a/room/compiler/src/main/kotlin/androidx/room/parser/expansion/ExpandableSqlParser.kt b/room/compiler/src/main/kotlin/androidx/room/parser/expansion/ExpandableSqlParser.kt
index 1905c6f..6e5b317 100644
--- a/room/compiler/src/main/kotlin/androidx/room/parser/expansion/ExpandableSqlParser.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/parser/expansion/ExpandableSqlParser.kt
@@ -92,7 +92,8 @@
}
c.table_name() != null -> {
addProjectionSection(
- c, ExpandableSection.Projection.Table(
+ c,
+ ExpandableSection.Projection.Table(
c.table_name().text.trim('`'),
original.substring(c.start.startIndex, c.stop.stopIndex + 1)
)
@@ -197,7 +198,7 @@
private val RuleContext.isCoreSelect: Boolean
get() {
return this is SQLiteParser.Select_or_valuesContext &&
- ancestors().none { it is SQLiteParser.Select_or_valuesContext }
+ ancestors().none { it is SQLiteParser.Select_or_valuesContext }
}
class ExpandableSqlParser {
diff --git a/room/compiler/src/main/kotlin/androidx/room/parser/expansion/ProjectionExpander.kt b/room/compiler/src/main/kotlin/androidx/room/parser/expansion/ProjectionExpander.kt
index 0f3fa30..52a8504 100644
--- a/room/compiler/src/main/kotlin/androidx/room/parser/expansion/ProjectionExpander.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/parser/expansion/ProjectionExpander.kt
@@ -147,8 +147,8 @@
val table = tables.find { it.tableName == tableName }
pojo.fields.filter { field ->
field.parent == null &&
- field.columnName !in query.explicitColumns &&
- table?.columnNames?.contains(field.columnName) == true
+ field.columnName !in query.explicitColumns &&
+ table?.columnNames?.contains(field.columnName) == true
}.joinToString(", ") { field ->
"`${section.tableAlias}`.`${field.columnName}`"
}
@@ -173,7 +173,7 @@
// Try to find by the table name.
return pojo.embeddedFields.find {
it.prefix.isEmpty() &&
- findEntityOrView(it.pojo)?.tableName == tableAlias
+ findEntityOrView(it.pojo)?.tableName == tableAlias
}
}
@@ -185,22 +185,24 @@
resultInfo: QueryResultInfo?
): String {
val table = findEntityOrView(pojo)
- return (pojo.embeddedFields.flatMap {
- expandEmbeddedField(it, findEntityOrView(it.pojo), shallow, nameToAlias)
- } + pojo.fields.filter { field ->
- field.parent == null &&
+ return (
+ pojo.embeddedFields.flatMap {
+ expandEmbeddedField(it, findEntityOrView(it.pojo), shallow, nameToAlias)
+ } + pojo.fields.filter { field ->
+ field.parent == null &&
field.columnName !in ignoredColumnNames &&
(resultInfo == null || resultInfo.hasColumn(field.columnName))
- }.map { field ->
- if (table != null && table is Entity) {
- // Should not happen when defining a view
- val tableAlias = nameToAlias[table.tableName.toLowerCase(Locale.ENGLISH)]
- ?: table.tableName
- "`$tableAlias`.`${field.columnName}` AS `${field.columnName}`"
- } else {
- "`${field.columnName}`"
+ }.map { field ->
+ if (table != null && table is Entity) {
+ // Should not happen when defining a view
+ val tableAlias = nameToAlias[table.tableName.toLowerCase(Locale.ENGLISH)]
+ ?: table.tableName
+ "`$tableAlias`.`${field.columnName}` AS `${field.columnName}`"
+ } else {
+ "`${field.columnName}`"
+ }
}
- }).joinToString(", ")
+ ).joinToString(", ")
}
private fun QueryResultInfo.hasColumn(columnName: String): Boolean {
@@ -221,7 +223,7 @@
"`${embedded.prefix}${field.columnName}`"
} else {
"`${embedded.prefix}`.`${field.columnName}` " +
- "AS `${embedded.prefix}${field.columnName}`"
+ "AS `${embedded.prefix}${field.columnName}`"
}
}
} else {
@@ -241,7 +243,7 @@
) {
pojo.fields.map { field ->
"`${embedded.prefix}`.`${field.columnNameWithoutPrefix(embedded.prefix)}` " +
- "AS `${field.columnName}`"
+ "AS `${field.columnName}`"
}
} else {
pojo.fields.map { field ->
diff --git a/room/compiler/src/main/kotlin/androidx/room/preconditions/Checks.kt b/room/compiler/src/main/kotlin/androidx/room/preconditions/Checks.kt
index 2371d29..070e72a 100644
--- a/room/compiler/src/main/kotlin/androidx/room/preconditions/Checks.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/preconditions/Checks.kt
@@ -63,7 +63,7 @@
val failed = check(typeName !is TypeVariableName, element, errorMsg, args)
if (typeName is ParameterizedTypeName) {
val nestedFailure = typeName.typeArguments
- .any { notUnbound(it, element, errorMsg, args) }
+ .any { notUnbound(it, element, errorMsg, args) }
return !(failed || nestedFailure)
}
return !failed
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt b/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt
index b30f994..5bbeea0 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt
@@ -74,7 +74,7 @@
companion object {
val ARG_OPTIONS by lazy {
ProcessorOptions.values().map { it.argName } +
- BooleanProcessorOptions.values().map { it.argName }
+ BooleanProcessorOptions.values().map { it.argName }
}
}
@@ -86,12 +86,13 @@
}
constructor(processingEnv: XProcessingEnv) : this(
- processingEnv = processingEnv,
- logger = RLog(processingEnv.messager, emptySet(), null),
- typeConverters = CustomConverterProcessor.ProcessResult.EMPTY,
- inheritedAdapterStore = null,
- cache = Cache(null, LinkedHashSet(), emptySet()),
- canRewriteQueriesToDropUnusedColumns = false)
+ processingEnv = processingEnv,
+ logger = RLog(processingEnv.messager, emptySet(), null),
+ typeConverters = CustomConverterProcessor.ProcessResult.EMPTY,
+ inheritedAdapterStore = null,
+ cache = Cache(null, LinkedHashSet(), emptySet()),
+ canRewriteQueriesToDropUnusedColumns = false
+ )
class CommonTypes(val processingEnv: XProcessingEnv) {
val VOID: XType by lazy {
@@ -116,12 +117,14 @@
fun <T> collectLogs(handler: (Context) -> T): Pair<T, RLog.CollectingMessager> {
val collector = RLog.CollectingMessager()
- val subContext = Context(processingEnv = processingEnv,
- logger = RLog(collector, logger.suppressedWarnings, logger.defaultElement),
- typeConverters = this.typeConverters,
- inheritedAdapterStore = typeAdapterStore,
- cache = cache,
- canRewriteQueriesToDropUnusedColumns = canRewriteQueriesToDropUnusedColumns)
+ val subContext = Context(
+ processingEnv = processingEnv,
+ logger = RLog(collector, logger.suppressedWarnings, logger.defaultElement),
+ typeConverters = this.typeConverters,
+ inheritedAdapterStore = typeAdapterStore,
+ cache = cache,
+ canRewriteQueriesToDropUnusedColumns = canRewriteQueriesToDropUnusedColumns
+ )
subContext.databaseVerifier = databaseVerifier
val result = handler(subContext)
return Pair(result, collector)
@@ -141,14 +144,15 @@
forceSuppressedWarnings + suppressedWarnings + logger.suppressedWarnings
val subCache = Cache(cache, subTypeConverters.classes, subSuppressedWarnings)
val subCanRemoveUnusedColumns = canRewriteQueriesToDropUnusedColumns ||
- element.hasRemoveUnusedColumnsAnnotation()
+ element.hasRemoveUnusedColumnsAnnotation()
val subContext = Context(
- processingEnv = processingEnv,
- logger = RLog(logger.messager, subSuppressedWarnings, element),
- typeConverters = subTypeConverters,
- inheritedAdapterStore = if (canReUseAdapterStore) typeAdapterStore else null,
- cache = subCache,
- canRewriteQueriesToDropUnusedColumns = subCanRemoveUnusedColumns)
+ processingEnv = processingEnv,
+ logger = RLog(logger.messager, subSuppressedWarnings, element),
+ typeConverters = subTypeConverters,
+ inheritedAdapterStore = if (canReUseAdapterStore) typeAdapterStore else null,
+ cache = subCache,
+ canRewriteQueriesToDropUnusedColumns = subCanRemoveUnusedColumns
+ )
subContext.databaseVerifier = databaseVerifier
return subContext
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
index 1300b96..d8a4bc2 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/CustomConverterProcessor.kt
@@ -63,7 +63,8 @@
.values.forEach {
it.forEach { converter ->
context.logger.e(
- converter.method, ProcessorErrors
+ converter.method,
+ ProcessorErrors
.duplicateTypeConverters(it.minus(converter))
)
}
@@ -87,9 +88,10 @@
if (!isProvidedConverter) {
context.checker.check(
isKotlinObjectDeclaration || allStatic || constructors.isEmpty() ||
- constructors.any {
- it.parameters.isEmpty()
- }, element, TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR
+ constructors.any {
+ it.parameters.isEmpty()
+ },
+ element, TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR
)
}
return converterMethods.mapNotNull {
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
index e0ec460..848239d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
@@ -41,15 +41,21 @@
val context = baseContext.fork(element)
companion object {
- val PROCESSED_ANNOTATIONS = listOf(Insert::class, Delete::class, Query::class,
- Update::class, RawQuery::class)
+ val PROCESSED_ANNOTATIONS = listOf(
+ Insert::class, Delete::class, Query::class,
+ Update::class, RawQuery::class
+ )
}
fun process(): Dao {
- context.checker.hasAnnotation(element, androidx.room.Dao::class,
- ProcessorErrors.DAO_MUST_BE_ANNOTATED_WITH_DAO)
- context.checker.check(element.isAbstract() || element.isInterface(),
- element, ProcessorErrors.DAO_MUST_BE_AN_ABSTRACT_CLASS_OR_AN_INTERFACE)
+ context.checker.hasAnnotation(
+ element, androidx.room.Dao::class,
+ ProcessorErrors.DAO_MUST_BE_ANNOTATED_WITH_DAO
+ )
+ context.checker.check(
+ element.isAbstract() || element.isInterface(),
+ element, ProcessorErrors.DAO_MUST_BE_AN_ABSTRACT_CLASS_OR_AN_INTERFACE
+ )
val declaredType = element.asDeclaredType()
val allMethods = element.getAllMethods()
@@ -58,8 +64,8 @@
it.isAbstract() && !it.hasKotlinDefaultImpl()
}.groupBy { method ->
context.checker.check(
- PROCESSED_ANNOTATIONS.count { method.hasAnnotation(it) } <= 1, method,
- ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD
+ PROCESSED_ANNOTATIONS.count { method.hasAnnotation(it) } <= 1, method,
+ ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD
)
if (method.hasAnnotation(Query::class)) {
Query::class
@@ -77,7 +83,8 @@
}
val processorVerifier = if (element.hasAnnotation(SkipQueryVerification::class) ||
- element.hasAnnotation(RawQuery::class)) {
+ element.hasAnnotation(RawQuery::class)
+ ) {
null
} else {
dbVerifier
@@ -85,49 +92,54 @@
val queryMethods = methods[Query::class]?.map {
QueryMethodProcessor(
- baseContext = context,
- containing = declaredType,
- executableElement = it,
- dbVerifier = processorVerifier).process()
+ baseContext = context,
+ containing = declaredType,
+ executableElement = it,
+ dbVerifier = processorVerifier
+ ).process()
} ?: emptyList()
val rawQueryMethods = methods[RawQuery::class]?.map {
RawQueryMethodProcessor(
- baseContext = context,
- containing = declaredType,
- executableElement = it
+ baseContext = context,
+ containing = declaredType,
+ executableElement = it
).process()
} ?: emptyList()
val insertionMethods = methods[Insert::class]?.map {
InsertionMethodProcessor(
- baseContext = context,
- containing = declaredType,
- executableElement = it).process()
+ baseContext = context,
+ containing = declaredType,
+ executableElement = it
+ ).process()
} ?: emptyList()
val deletionMethods = methods[Delete::class]?.map {
DeletionMethodProcessor(
- baseContext = context,
- containing = declaredType,
- executableElement = it).process()
+ baseContext = context,
+ containing = declaredType,
+ executableElement = it
+ ).process()
} ?: emptyList()
val updateMethods = methods[Update::class]?.map {
UpdateMethodProcessor(
- baseContext = context,
- containing = declaredType,
- executableElement = it).process()
+ baseContext = context,
+ containing = declaredType,
+ executableElement = it
+ ).process()
} ?: emptyList()
val transactionMethods = allMethods.filter { member ->
member.hasAnnotation(Transaction::class) &&
- PROCESSED_ANNOTATIONS.none { member.hasAnnotation(it) }
+ PROCESSED_ANNOTATIONS.none { member.hasAnnotation(it) }
}.map {
TransactionMethodProcessor(
- baseContext = context,
- containing = declaredType,
- executableElement = it).process()
+ baseContext = context,
+ containing = declaredType,
+ executableElement = it
+ ).process()
}
// TODO (b/169950251): avoid going through the matching logic if the interface does not
@@ -160,7 +172,7 @@
val constructors = element.getConstructors()
val goodConstructor = constructors.firstOrNull {
it.parameters.size == 1 &&
- it.parameters[0].type.isAssignableFrom(dbType)
+ it.parameters[0].type.isAssignableFrom(dbType)
}
val constructorParamType = if (goodConstructor != null) {
goodConstructor.parameters[0].type.typeName
@@ -174,26 +186,34 @@
}
val type = declaredType.typeName
- context.checker.notUnbound(type, element,
- ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_DAO_CLASSES)
+ context.checker.notUnbound(
+ type, element,
+ ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_DAO_CLASSES
+ )
- return Dao(element = element,
- type = declaredType,
- queryMethods = queryMethods,
- rawQueryMethods = rawQueryMethods,
- insertionMethods = insertionMethods,
- deletionMethods = deletionMethods,
- updateMethods = updateMethods,
- transactionMethods = transactionMethods,
- delegatingMethods = delegatingMethods,
- kotlinDefaultMethodDelegates = kotlinDefaultMethodDelegates,
- constructorParamType = constructorParamType)
+ return Dao(
+ element = element,
+ type = declaredType,
+ queryMethods = queryMethods,
+ rawQueryMethods = rawQueryMethods,
+ insertionMethods = insertionMethods,
+ deletionMethods = deletionMethods,
+ updateMethods = updateMethods,
+ transactionMethods = transactionMethods,
+ delegatingMethods = delegatingMethods,
+ kotlinDefaultMethodDelegates = kotlinDefaultMethodDelegates,
+ constructorParamType = constructorParamType
+ )
}
private fun validateEmptyConstructor(constructors: List<XConstructorElement>) {
if (constructors.isNotEmpty() && constructors.all { it.parameters.isNotEmpty() }) {
- context.logger.e(element, ProcessorErrors.daoMustHaveMatchingConstructor(
- element.toString(), dbType.toString()))
+ context.logger.e(
+ element,
+ ProcessorErrors.daoMustHaveMatchingConstructor(
+ element.toString(), dbType.toString()
+ )
+ )
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
index 5c42523..cacbfba 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
@@ -41,7 +41,8 @@
val roomDatabaseType: XType by lazy {
context.processingEnv.requireType(
- RoomTypeNames.ROOM_DB.packageName() + "." + RoomTypeNames.ROOM_DB.simpleName())
+ RoomTypeNames.ROOM_DB.packageName() + "." + RoomTypeNames.ROOM_DB.simpleName()
+ )
}
fun process(): Database {
@@ -83,7 +84,7 @@
// remove methods that belong to room
val containing = it.enclosingTypeElement
containing.isType() &&
- containing.asDeclaredType().typeName == RoomTypeNames.ROOM_DB
+ containing.asDeclaredType().typeName == RoomTypeNames.ROOM_DB
}.map {
val executable = it.asMethodElement()
// TODO when we add support for non Dao return types (e.g. database), this code needs
@@ -100,14 +101,15 @@
val hasForeignKeys = entities.any { it.foreignKeys.isNotEmpty() }
val database = Database(
- version = dbAnnotation.value.version,
- element = element,
- type = element.type,
- entities = entities,
- views = views,
- daoMethods = daoMethods,
- exportSchema = dbAnnotation.value.exportSchema,
- enableForeignKeys = hasForeignKeys)
+ version = dbAnnotation.value.version,
+ element = element,
+ type = element.type,
+ entities = entities,
+ views = views,
+ daoMethods = daoMethods,
+ exportSchema = dbAnnotation.value.exportSchema,
+ enableForeignKeys = hasForeignKeys
+ )
return database
}
@@ -117,20 +119,27 @@
entity.foreignKeys.forEach foreignKeyLoop@{ foreignKey ->
val parent = byTableName[foreignKey.parentTable]
if (parent == null) {
- context.logger.e(element, ProcessorErrors
- .foreignKeyMissingParentEntityInDatabase(foreignKey.parentTable,
+ context.logger.e(
+ element,
+ ProcessorErrors
+ .foreignKeyMissingParentEntityInDatabase(
+ foreignKey.parentTable,
entity.element.qualifiedName
- ))
+ )
+ )
return@foreignKeyLoop
}
val parentFields = foreignKey.parentColumns.mapNotNull { columnName ->
val parentField = parent.findFieldByColumnName(columnName)
if (parentField == null) {
- context.logger.e(entity.element,
- ProcessorErrors.foreignKeyParentColumnDoesNotExist(
- parentEntity = parent.element.qualifiedName,
- missingColumn = columnName,
- allColumns = parent.columnNames))
+ context.logger.e(
+ entity.element,
+ ProcessorErrors.foreignKeyParentColumnDoesNotExist(
+ parentEntity = parent.element.qualifiedName,
+ missingColumn = columnName,
+ allColumns = parent.columnNames
+ )
+ )
}
parentField
}
@@ -139,13 +148,17 @@
}
// ensure that it is indexed in the parent
if (!parent.isUnique(foreignKey.parentColumns)) {
- context.logger.e(parent.element, ProcessorErrors
+ context.logger.e(
+ parent.element,
+ ProcessorErrors
.foreignKeyMissingIndexInParent(
- parentEntity = parent.element.qualifiedName,
- childEntity = entity.element.qualifiedName,
- parentColumns = foreignKey.parentColumns,
- childColumns = foreignKey.childFields
- .map { it.columnName }))
+ parentEntity = parent.element.qualifiedName,
+ childEntity = entity.element.qualifiedName,
+ parentColumns = foreignKey.parentColumns,
+ childColumns = foreignKey.childFields
+ .map { it.columnName }
+ )
+ )
return@foreignKeyLoop
}
}
@@ -154,20 +167,24 @@
private fun validateUniqueIndices(element: XTypeElement, entities: List<Entity>) {
entities
- .flatMap { entity ->
- // associate each index with its entity
- entity.indices.map { Pair(it.name, entity) }
+ .flatMap { entity ->
+ // associate each index with its entity
+ entity.indices.map { Pair(it.name, entity) }
+ }
+ .groupBy { it.first } // group by index name
+ .filter { it.value.size > 1 } // get the ones with duplicate names
+ .forEach {
+ // do not report duplicates from the same entity
+ if (it.value.distinctBy { it.second.typeName }.size > 1) {
+ context.logger.e(
+ element,
+ ProcessorErrors.duplicateIndexInDatabase(
+ it.key,
+ it.value.map { "${it.second.typeName} > ${it.first}" }
+ )
+ )
}
- .groupBy { it.first } // group by index name
- .filter { it.value.size > 1 } // get the ones with duplicate names
- .forEach {
- // do not report duplicates from the same entity
- if (it.value.distinctBy { it.second.typeName }.size > 1) {
- context.logger.e(element,
- ProcessorErrors.duplicateIndexInDatabase(it.key,
- it.value.map { "${it.second.typeName} > ${it.first}" }))
- }
- }
+ }
}
private fun validateUniqueDaoClasses(
@@ -177,17 +194,19 @@
) {
val entityTypeNames = entities.map { it.typeName }.toSet()
daoMethods.groupBy { it.dao.typeName }
- .forEach {
- if (it.value.size > 1) {
- val error = ProcessorErrors.duplicateDao(it.key, it.value.map { it.name })
- it.value.forEach { daoMethod ->
- context.logger.e(daoMethod.element,
- ProcessorErrors.DAO_METHOD_CONFLICTS_WITH_OTHERS)
- }
- // also report the full error for the database
- context.logger.e(dbElement, error)
+ .forEach {
+ if (it.value.size > 1) {
+ val error = ProcessorErrors.duplicateDao(it.key, it.value.map { it.name })
+ it.value.forEach { daoMethod ->
+ context.logger.e(
+ daoMethod.element,
+ ProcessorErrors.DAO_METHOD_CONFLICTS_WITH_OTHERS
+ )
}
+ // also report the full error for the database
+ context.logger.e(dbElement, error)
}
+ }
val check = fun(
element: XElement,
dao: Dao,
@@ -195,12 +214,14 @@
) {
typeName?.let {
if (!entityTypeNames.contains(typeName)) {
- context.logger.e(element,
- ProcessorErrors.shortcutEntityIsNotInDatabase(
- database = dbElement.qualifiedName,
- dao = dao.typeName.toString(),
- entity = typeName.toString()
- ))
+ context.logger.e(
+ element,
+ ProcessorErrors.shortcutEntityIsNotInDatabase(
+ database = dbElement.qualifiedName,
+ dao = dao.typeName.toString(),
+ entity = typeName.toString()
+ )
+ )
}
}
}
@@ -230,34 +251,38 @@
Triple(it.viewName.toLowerCase(Locale.US), it.typeName.toString(), it.element)
}
(entitiesInfo + viewsInfo)
- .groupBy { (name, _, _) -> name }
- .filter { it.value.size > 1 }
- .forEach { byName ->
- val error = ProcessorErrors.duplicateTableNames(byName.key,
- byName.value.map { (_, typeName, _) -> typeName })
- // report it for each of them and the database to make it easier
- // for the developer
- byName.value.forEach { (_, _, element) ->
- context.logger.e(element, error)
- }
- context.logger.e(dbElement, error)
+ .groupBy { (name, _, _) -> name }
+ .filter { it.value.size > 1 }
+ .forEach { byName ->
+ val error = ProcessorErrors.duplicateTableNames(
+ byName.key,
+ byName.value.map { (_, typeName, _) -> typeName }
+ )
+ // report it for each of them and the database to make it easier
+ // for the developer
+ byName.value.forEach { (_, _, element) ->
+ context.logger.e(element, error)
}
+ context.logger.e(dbElement, error)
+ }
}
private fun validateExternalContentFts(dbElement: XTypeElement, entities: List<Entity>) {
// Validate FTS external content entities are present in the same database.
entities.filterIsInstance(FtsEntity::class.java)
- .filterNot {
- it.ftsOptions.contentEntity == null ||
- entities.contains(it.ftsOptions.contentEntity)
- }
- .forEach {
- context.logger.e(dbElement,
- ProcessorErrors.missingExternalContentEntity(
- it.element.qualifiedName,
- it.ftsOptions.contentEntity!!.element.qualifiedName
- ))
- }
+ .filterNot {
+ it.ftsOptions.contentEntity == null ||
+ entities.contains(it.ftsOptions.contentEntity)
+ }
+ .forEach {
+ context.logger.e(
+ dbElement,
+ ProcessorErrors.missingExternalContentEntity(
+ it.element.qualifiedName,
+ it.ftsOptions.contentEntity!!.element.qualifiedName
+ )
+ )
+ }
}
private fun processEntities(
@@ -265,8 +290,10 @@
element: XTypeElement
): List<Entity> {
val entityList = dbAnnotation.getAsTypeList("entities")
- context.checker.check(entityList.isNotEmpty(), element,
- ProcessorErrors.DATABASE_ANNOTATION_MUST_HAVE_LIST_OF_ENTITIES)
+ context.checker.check(
+ entityList.isNotEmpty(), element,
+ ProcessorErrors.DATABASE_ANNOTATION_MUST_HAVE_LIST_OF_ENTITIES
+ )
return entityList.map {
EntityProcessor(context, it.asTypeElement()).process()
}
@@ -292,9 +319,12 @@
}
view.query.resultInfo = dbVerifier.analyze(view.query.original)
if (view.query.resultInfo?.error != null) {
- context.logger.e(viewElement,
+ context.logger.e(
+ viewElement,
DatabaseVerificationErrors.cannotVerifyQuery(
- view.query.resultInfo!!.error!!))
+ view.query.resultInfo!!.error!!
+ )
+ )
}
}
}
@@ -332,17 +362,21 @@
var countNewlyResolved = 0
// Separate out views that have all of their underlying tables resolved.
unresolvedViews
- .filter { view -> view.tables.all { isTable(it) } }
- .forEach { view ->
- resolvedViews[view.viewName] = view.tables
- unresolvedViews.remove(view)
- result.add(view)
- countNewlyResolved++
- }
+ .filter { view -> view.tables.all { isTable(it) } }
+ .forEach { view ->
+ resolvedViews[view.viewName] = view.tables
+ unresolvedViews.remove(view)
+ result.add(view)
+ countNewlyResolved++
+ }
// We couldn't resolve a single view in this step. It indicates circular reference.
if (countNewlyResolved == 0) {
- context.logger.e(element, ProcessorErrors.viewCircularReferenceDetected(
- unresolvedViews.map { it.viewName }))
+ context.logger.e(
+ element,
+ ProcessorErrors.viewCircularReferenceDetected(
+ unresolvedViews.map { it.viewName }
+ )
+ )
break
}
// We are done if we have resolved tables for all the views.
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseViewProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseViewProcessor.kt
index 6654144..0253959 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseViewProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DatabaseViewProcessor.kt
@@ -31,8 +31,10 @@
val context = baseContext.fork(element)
override fun process(): DatabaseView {
- context.checker.hasAnnotation(element, androidx.room.DatabaseView::class,
- ProcessorErrors.VIEW_MUST_BE_ANNOTATED_WITH_DATABASE_VIEW)
+ context.checker.hasAnnotation(
+ element, androidx.room.DatabaseView::class,
+ ProcessorErrors.VIEW_MUST_BE_ANNOTATED_WITH_DATABASE_VIEW
+ )
val annotationBox = element.toAnnotationBox(androidx.room.DatabaseView::class)
val viewName: String = if (annotationBox != null) {
@@ -42,37 +44,49 @@
}
val query: ParsedQuery = if (annotationBox != null) {
SqlParser.parse(annotationBox.value.value).also {
- context.checker.check(it.errors.isEmpty(), element,
- it.errors.joinToString("\n"))
- context.checker.check(it.type == QueryType.SELECT, element,
- ProcessorErrors.VIEW_QUERY_MUST_BE_SELECT)
- context.checker.check(it.bindSections.isEmpty(), element,
- ProcessorErrors.VIEW_QUERY_CANNOT_TAKE_ARGUMENTS)
+ context.checker.check(
+ it.errors.isEmpty(), element,
+ it.errors.joinToString("\n")
+ )
+ context.checker.check(
+ it.type == QueryType.SELECT, element,
+ ProcessorErrors.VIEW_QUERY_MUST_BE_SELECT
+ )
+ context.checker.check(
+ it.bindSections.isEmpty(), element,
+ ProcessorErrors.VIEW_QUERY_CANNOT_TAKE_ARGUMENTS
+ )
}
} else {
ParsedQuery.MISSING
}
- context.checker.notBlank(viewName, element,
- ProcessorErrors.VIEW_NAME_CANNOT_BE_EMPTY)
- context.checker.check(!viewName.startsWith("sqlite_", true), element,
- ProcessorErrors.VIEW_NAME_CANNOT_START_WITH_SQLITE)
+ context.checker.notBlank(
+ viewName, element,
+ ProcessorErrors.VIEW_NAME_CANNOT_BE_EMPTY
+ )
+ context.checker.check(
+ !viewName.startsWith("sqlite_", true), element,
+ ProcessorErrors.VIEW_NAME_CANNOT_START_WITH_SQLITE
+ )
val pojo = PojoProcessor.createFor(
- context = context,
- element = element,
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null,
- referenceStack = referenceStack).process()
+ context = context,
+ element = element,
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null,
+ referenceStack = referenceStack
+ ).process()
return DatabaseView(
- element = element,
- viewName = viewName,
- query = query,
- type = pojo.type,
- fields = pojo.fields,
- embeddedFields = pojo.embeddedFields,
- constructor = pojo.constructor)
+ element = element,
+ viewName = viewName,
+ query = query,
+ type = pojo.type,
+ fields = pojo.fields,
+ embeddedFields = pojo.embeddedFields,
+ constructor = pojo.constructor
+ )
}
companion object {
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/DeletionMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/DeletionMethodProcessor.kt
index 395c10a..d285693 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/DeletionMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/DeletionMethodProcessor.kt
@@ -37,9 +37,9 @@
val methodBinder = delegate.findDeleteOrUpdateMethodBinder(returnType)
context.checker.check(
- methodBinder.adapter != null,
- executableElement,
- ProcessorErrors.CANNOT_FIND_DELETE_RESULT_ADAPTER
+ methodBinder.adapter != null,
+ executableElement,
+ ProcessorErrors.CANNOT_FIND_DELETE_RESULT_ADAPTER
)
val (entities, params) = delegate.extractParams(
@@ -49,11 +49,11 @@
)
return DeletionMethod(
- element = delegate.executableElement,
- name = delegate.executableElement.name,
- entities = entities,
- parameters = params,
- methodBinder = methodBinder
+ element = delegate.executableElement,
+ name = delegate.executableElement.name,
+ entities = entities,
+ parameters = params,
+ methodBinder = methodBinder
)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt
index de0ba64..51956a5 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/EntityOrViewProcessor.kt
@@ -41,11 +41,12 @@
context.logger.e(element, ProcessorErrors.NOT_ENTITY_OR_VIEW)
// Parse this as a Pojo in case there are more errors.
PojoProcessor.createFor(
- context = context,
- element = element,
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null,
- referenceStack = referenceStack).process()
+ context = context,
+ element = element,
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null,
+ referenceStack = referenceStack
+ ).process()
return object : EntityOrView {
override val fields: Fields = Fields()
override val tableName: String
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/EntityProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/EntityProcessor.kt
index d6d9a17..9a9998e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/EntityProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/EntityProcessor.kt
@@ -60,21 +60,22 @@
fun extractForeignKeys(annotation: XAnnotationBox<Entity>): List<ForeignKeyInput> {
return annotation.getAsAnnotationBoxArray<ForeignKey>("foreignKeys")
- .mapNotNull { annotationBox ->
- val foreignKey = annotationBox.value
- val parent = annotationBox.getAsType("entity")
- if (parent != null) {
- ForeignKeyInput(
+ .mapNotNull { annotationBox ->
+ val foreignKey = annotationBox.value
+ val parent = annotationBox.getAsType("entity")
+ if (parent != null) {
+ ForeignKeyInput(
parent = parent,
parentColumns = foreignKey.parentColumns.asList(),
childColumns = foreignKey.childColumns.asList(),
onDelete = ForeignKeyAction.fromAnnotationValue(foreignKey.onDelete),
onUpdate = ForeignKeyAction.fromAnnotationValue(foreignKey.onUpdate),
- deferred = foreignKey.deferred)
- } else {
- null
+ deferred = foreignKey.deferred
+ )
+ } else {
+ null
+ }
}
- }
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/FieldProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/FieldProcessor.kt
index 96ea9db..291bd76 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/FieldProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/FieldProcessor.kt
@@ -51,10 +51,14 @@
null
}
- context.checker.notBlank(columnName, element,
- ProcessorErrors.COLUMN_NAME_CANNOT_BE_EMPTY)
- context.checker.notUnbound(type, element,
- ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_ENTITY_FIELDS)
+ context.checker.notBlank(
+ columnName, element,
+ ProcessorErrors.COLUMN_NAME_CANNOT_BE_EMPTY
+ )
+ context.checker.notUnbound(
+ type, element,
+ ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_ENTITY_FIELDS
+ )
val adapter = context.typeAdapterStore.findColumnTypeAdapter(member, affinity)
val adapterAffinity = adapter?.typeAffinity ?: affinity
@@ -86,14 +90,14 @@
}
BindingScope.BIND_TO_STMT -> {
field.statementBinder = context.typeAdapterStore
- .findStatementValueBinder(field.type, field.affinity)
+ .findStatementValueBinder(field.type, field.affinity)
if (field.statementBinder == null) {
onBindingError(field, ProcessorErrors.CANNOT_FIND_STMT_BINDER)
}
}
BindingScope.READ_FROM_CURSOR -> {
field.cursorValueReader = context.typeAdapterStore
- .findCursorValueReader(field.type, field.affinity)
+ .findCursorValueReader(field.type, field.affinity)
if (field.cursorValueReader == null) {
onBindingError(field, ProcessorErrors.CANNOT_FIND_CURSOR_READER)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/FtsTableEntityProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/FtsTableEntityProcessor.kt
index 7971604..a79d82e1 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/FtsTableEntityProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/FtsTableEntityProcessor.kt
@@ -53,26 +53,33 @@
}
private fun doProcess(): FtsEntity {
- context.checker.hasAnnotation(element, androidx.room.Entity::class,
- ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY)
+ context.checker.hasAnnotation(
+ element, androidx.room.Entity::class,
+ ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY
+ )
val entityAnnotation = element.toAnnotationBox(androidx.room.Entity::class)
val tableName: String
if (entityAnnotation != null) {
tableName = extractTableName(element, entityAnnotation.value)
- context.checker.check(extractIndices(entityAnnotation, tableName).isEmpty(),
- element, ProcessorErrors.INDICES_IN_FTS_ENTITY)
- context.checker.check(extractForeignKeys(entityAnnotation).isEmpty(),
- element, ProcessorErrors.FOREIGN_KEYS_IN_FTS_ENTITY)
+ context.checker.check(
+ extractIndices(entityAnnotation, tableName).isEmpty(),
+ element, ProcessorErrors.INDICES_IN_FTS_ENTITY
+ )
+ context.checker.check(
+ extractForeignKeys(entityAnnotation).isEmpty(),
+ element, ProcessorErrors.FOREIGN_KEYS_IN_FTS_ENTITY
+ )
} else {
tableName = element.name
}
val pojo = PojoProcessor.createFor(
- context = context,
- element = element,
- bindingScope = FieldProcessor.BindingScope.TWO_WAY,
- parent = null,
- referenceStack = referenceStack).process()
+ context = context,
+ element = element,
+ bindingScope = FieldProcessor.BindingScope.TWO_WAY,
+ parent = null,
+ referenceStack = referenceStack
+ ).process()
context.checker.check(pojo.relations.isEmpty(), element, ProcessorErrors.RELATION_IN_ENTITY)
@@ -96,23 +103,28 @@
findAndValidateLanguageId(pojo.fields, ftsOptions.languageIdColumnName)
val missingNotIndexed = ftsOptions.notIndexedColumns - pojo.columnNames
- context.checker.check(missingNotIndexed.isEmpty(), element,
- ProcessorErrors.missingNotIndexedField(missingNotIndexed))
+ context.checker.check(
+ missingNotIndexed.isEmpty(), element,
+ ProcessorErrors.missingNotIndexedField(missingNotIndexed)
+ )
- context.checker.check(ftsOptions.prefixSizes.all { it > 0 },
- element, ProcessorErrors.INVALID_FTS_ENTITY_PREFIX_SIZES)
+ context.checker.check(
+ ftsOptions.prefixSizes.all { it > 0 },
+ element, ProcessorErrors.INVALID_FTS_ENTITY_PREFIX_SIZES
+ )
val entity = FtsEntity(
- element = element,
- tableName = tableName,
- type = pojo.type,
- fields = pojo.fields,
- embeddedFields = pojo.embeddedFields,
- primaryKey = primaryKey,
- constructor = pojo.constructor,
- ftsVersion = ftsVersion,
- ftsOptions = ftsOptions,
- shadowTableName = shadowTableName)
+ element = element,
+ tableName = tableName,
+ type = pojo.type,
+ fields = pojo.fields,
+ embeddedFields = pojo.embeddedFields,
+ primaryKey = primaryKey,
+ constructor = pojo.constructor,
+ ftsVersion = ftsVersion,
+ ftsOptions = ftsOptions,
+ shadowTableName = shadowTableName
+ )
validateExternalContentEntity(entity)
@@ -128,19 +140,21 @@
matchInfo = MatchInfo.FTS4,
notIndexedColumns = emptyList(),
prefixSizes = emptyList(),
- preferredOrder = Order.ASC)
+ preferredOrder = Order.ASC
+ )
private fun getFts4Options(annotation: XAnnotationBox<Fts4>): FtsOptions {
val contentEntity: Entity? = getContentEntity(annotation.getAsType("contentEntity"))
return FtsOptions(
- tokenizer = annotation.value.tokenizer,
- tokenizerArgs = annotation.value.tokenizerArgs.asList(),
- contentEntity = contentEntity,
- languageIdColumnName = annotation.value.languageId,
- matchInfo = annotation.value.matchInfo,
- notIndexedColumns = annotation.value.notIndexed.asList(),
- prefixSizes = annotation.value.prefix.asList(),
- preferredOrder = annotation.value.order)
+ tokenizer = annotation.value.tokenizer,
+ tokenizerArgs = annotation.value.tokenizerArgs.asList(),
+ contentEntity = contentEntity,
+ languageIdColumnName = annotation.value.languageId,
+ matchInfo = annotation.value.matchInfo,
+ notIndexedColumns = annotation.value.notIndexed.asList(),
+ prefixSizes = annotation.value.prefix.asList(),
+ preferredOrder = annotation.value.order
+ )
}
private fun getContentEntity(entityType: XType?): Entity? {
@@ -155,8 +169,10 @@
}
val contentEntityElement = entityType.asTypeElement()
if (!contentEntityElement.hasAnnotation(androidx.room.Entity::class)) {
- context.logger.e(contentEntityElement,
- ProcessorErrors.externalContentNotAnEntity(contentEntityElement.toString()))
+ context.logger.e(
+ contentEntityElement,
+ ProcessorErrors.externalContentNotAnEntity(contentEntityElement.toString())
+ )
return null
}
return EntityProcessor(context, contentEntityElement, referenceStack).process()
@@ -168,24 +184,30 @@
): PrimaryKey {
val keysFromEntityAnnotation =
entityAnnotation?.value?.primaryKeys?.mapNotNull { pkColumnName ->
- val field = fields.firstOrNull { it.columnName == pkColumnName }
- context.checker.check(field != null, element,
- ProcessorErrors.primaryKeyColumnDoesNotExist(pkColumnName,
- fields.map { it.columnName }))
- field?.let { pkField ->
- PrimaryKey(
- declaredIn = pkField.element.enclosingTypeElement,
- fields = Fields(pkField),
- autoGenerateId = true)
- }
- } ?: emptyList()
+ val field = fields.firstOrNull { it.columnName == pkColumnName }
+ context.checker.check(
+ field != null, element,
+ ProcessorErrors.primaryKeyColumnDoesNotExist(
+ pkColumnName,
+ fields.map { it.columnName }
+ )
+ )
+ field?.let { pkField ->
+ PrimaryKey(
+ declaredIn = pkField.element.enclosingTypeElement,
+ fields = Fields(pkField),
+ autoGenerateId = true
+ )
+ }
+ } ?: emptyList()
val keysFromPrimaryKeyAnnotations = fields.mapNotNull { field ->
if (field.element.hasAnnotation(androidx.room.PrimaryKey::class)) {
PrimaryKey(
- declaredIn = field.element.enclosingTypeElement,
- fields = Fields(field),
- autoGenerateId = true)
+ declaredIn = field.element.enclosingTypeElement,
+ fields = Fields(field),
+ autoGenerateId = true
+ )
} else {
null
}
@@ -193,20 +215,28 @@
val primaryKeys = keysFromEntityAnnotation + keysFromPrimaryKeyAnnotations
if (primaryKeys.isEmpty()) {
fields.firstOrNull { it.columnName == "rowid" }?.let {
- context.checker.check(it.element.hasAnnotation(androidx.room.PrimaryKey::class),
- it.element, ProcessorErrors.MISSING_PRIMARY_KEYS_ANNOTATION_IN_ROW_ID)
+ context.checker.check(
+ it.element.hasAnnotation(androidx.room.PrimaryKey::class),
+ it.element, ProcessorErrors.MISSING_PRIMARY_KEYS_ANNOTATION_IN_ROW_ID
+ )
}
return PrimaryKey.MISSING
}
- context.checker.check(primaryKeys.size == 1, element,
- ProcessorErrors.TOO_MANY_PRIMARY_KEYS_IN_FTS_ENTITY)
+ context.checker.check(
+ primaryKeys.size == 1, element,
+ ProcessorErrors.TOO_MANY_PRIMARY_KEYS_IN_FTS_ENTITY
+ )
val primaryKey = primaryKeys.first()
- context.checker.check(primaryKey.columnNames.first() == "rowid",
- primaryKey.declaredIn ?: element,
- ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_NAME)
- context.checker.check(primaryKey.fields.first().affinity == SQLTypeAffinity.INTEGER,
- primaryKey.declaredIn ?: element,
- ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_AFFINITY)
+ context.checker.check(
+ primaryKey.columnNames.first() == "rowid",
+ primaryKey.declaredIn ?: element,
+ ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_NAME
+ )
+ context.checker.check(
+ primaryKey.fields.first().affinity == SQLTypeAffinity.INTEGER,
+ primaryKey.declaredIn ?: element,
+ ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_AFFINITY
+ )
return primaryKey
}
@@ -220,10 +250,13 @@
ftsEntity.nonHiddenFields.filterNot {
contentEntity.fields.any { contentField -> contentField.columnName == it.columnName }
}.forEach {
- context.logger.e(it.element, ProcessorErrors.missingFtsContentField(
- element.qualifiedName, it.columnName,
- contentEntity.element.qualifiedName
- ))
+ context.logger.e(
+ it.element,
+ ProcessorErrors.missingFtsContentField(
+ element.qualifiedName, it.columnName,
+ contentEntity.element.qualifiedName
+ )
+ )
}
}
@@ -241,8 +274,10 @@
return LanguageId.MISSING
}
- context.checker.check(languageIdField.affinity == SQLTypeAffinity.INTEGER,
- languageIdField.element, ProcessorErrors.INVALID_FTS_ENTITY_LANGUAGE_ID_AFFINITY)
+ context.checker.check(
+ languageIdField.affinity == SQLTypeAffinity.INTEGER,
+ languageIdField.element, ProcessorErrors.INVALID_FTS_ENTITY_LANGUAGE_ID_AFFINITY
+ )
return LanguageId(languageIdField.element, languageIdField)
}
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/InsertionMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/InsertionMethodProcessor.kt
index 72dd2d0..f996bd4 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/InsertionMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/InsertionMethodProcessor.kt
@@ -34,17 +34,23 @@
val context = baseContext.fork(executableElement)
fun process(): InsertionMethod {
val delegate = ShortcutMethodProcessor(context, containing, executableElement)
- val annotation = delegate.extractAnnotation(Insert::class,
- ProcessorErrors.MISSING_INSERT_ANNOTATION)
+ val annotation = delegate.extractAnnotation(
+ Insert::class,
+ ProcessorErrors.MISSING_INSERT_ANNOTATION
+ )
val onConflict = annotation?.value?.onConflict ?: OnConflictProcessor.INVALID_ON_CONFLICT
- context.checker.check(onConflict in REPLACE..IGNORE,
- executableElement, ProcessorErrors.INVALID_ON_CONFLICT_VALUE)
+ context.checker.check(
+ onConflict in REPLACE..IGNORE,
+ executableElement, ProcessorErrors.INVALID_ON_CONFLICT_VALUE
+ )
val returnType = delegate.extractReturnType()
val returnTypeName = returnType.typeName
- context.checker.notUnbound(returnTypeName, executableElement,
- ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_INSERTION_METHODS)
+ context.checker.notUnbound(
+ returnTypeName, executableElement,
+ ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_INSERTION_METHODS
+ )
val (entities, params) = delegate.extractParams(
targetEntityType = annotation?.getAsType("entity"),
@@ -58,21 +64,23 @@
executableElement,
ProcessorErrors.missingPrimaryKeysInPartialEntityForInsert(
partialEntityName = pojo.typeName.toString(),
- primaryKeyNames = entity.primaryKey.fields.columnNames)
+ primaryKeyNames = entity.primaryKey.fields.columnNames
+ )
)
// Verify all non null columns without a default value are in the POJO otherwise
// the INSERT will fail with a NOT NULL constraint.
val missingRequiredFields = (entity.fields - entity.primaryKey.fields).filter {
it.nonNull && it.defaultValue == null &&
- pojo.findFieldByColumnName(it.columnName) == null
+ pojo.findFieldByColumnName(it.columnName) == null
}
context.checker.check(
missingRequiredFields.isEmpty(),
executableElement,
ProcessorErrors.missingRequiredColumnsInPartialEntity(
partialEntityName = pojo.typeName.toString(),
- missingColumnNames = missingRequiredFields.map { it.columnName })
+ missingColumnNames = missingRequiredFields.map { it.columnName }
+ )
)
}
)
@@ -80,19 +88,19 @@
val methodBinder = delegate.findInsertMethodBinder(returnType, params)
context.checker.check(
- methodBinder.adapter != null,
- executableElement,
- ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
+ methodBinder.adapter != null,
+ executableElement,
+ ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
)
return InsertionMethod(
- element = executableElement,
- name = executableElement.name,
- returnType = returnType,
- entities = entities,
- parameters = params,
- onConflict = onConflict,
- methodBinder = methodBinder
+ element = executableElement,
+ name = executableElement.name,
+ returnType = returnType,
+ entities = entities,
+ parameters = params,
+ onConflict = onConflict,
+ methodBinder = methodBinder
)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt b/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt
index 6c6fcf7..e702802 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/MethodProcessorDelegate.kt
@@ -24,8 +24,11 @@
import androidx.room.parser.ParsedQuery
import androidx.room.compiler.processing.XDeclaredType
import androidx.room.compiler.processing.XMethodElement
+import androidx.room.compiler.processing.XMethodType
+import androidx.room.compiler.processing.XSuspendMethodType
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XVariableElement
+import androidx.room.compiler.processing.isSuspendFunction
import androidx.room.solver.prepared.binder.CallablePreparedQueryResultBinder.Companion.createPreparedBinder
import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
import androidx.room.solver.query.result.CoroutineResultBinder
@@ -90,7 +93,8 @@
containing: XDeclaredType,
executableElement: XMethodElement
): MethodProcessorDelegate {
- return if (executableElement.isSuspendFunction()) {
+ val asMember = executableElement.asMemberOf(containing)
+ return if (asMember.isSuspendFunction()) {
val hasCoroutineArtifact = context.processingEnv
.findTypeElement(RoomCoroutinesTypeNames.COROUTINES_ROOM.toString()) != null
if (!hasCoroutineArtifact) {
@@ -99,13 +103,15 @@
SuspendMethodProcessorDelegate(
context,
containing,
- executableElement
+ executableElement,
+ asMember
)
} else {
DefaultMethodProcessorDelegate(
context,
containing,
- executableElement
+ executableElement,
+ asMember
)
}
}
@@ -118,12 +124,12 @@
class DefaultMethodProcessorDelegate(
context: Context,
containing: XDeclaredType,
- executableElement: XMethodElement
+ executableElement: XMethodElement,
+ val executableType: XMethodType
) : MethodProcessorDelegate(context, containing, executableElement) {
override fun extractReturnType(): XType {
- val asMember = executableElement.asMemberOf(containing)
- return asMember.returnType
+ return executableType.returnType
}
override fun extractParams() = executableElement.parameters
@@ -146,7 +152,8 @@
override fun findTransactionMethodBinder(callType: TransactionMethod.CallType) =
InstantTransactionMethodBinder(
- TransactionMethodAdapter(executableElement.name, callType))
+ TransactionMethodAdapter(executableElement.name, callType)
+ )
}
/**
@@ -155,7 +162,8 @@
class SuspendMethodProcessorDelegate(
context: Context,
containing: XDeclaredType,
- executableElement: XMethodElement
+ executableElement: XMethodElement,
+ val executableType: XSuspendMethodType
) : MethodProcessorDelegate(context, containing, executableElement) {
private val continuationParam: XVariableElement by lazy {
@@ -167,8 +175,7 @@
}
override fun extractReturnType(): XType {
- val asMember = executableElement.asMemberOf(containing)
- return asMember.getSuspendFunctionReturnType()
+ return executableType.getSuspendFunctionReturnType()
}
override fun extractParams() =
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/PojoMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/PojoMethodProcessor.kt
index 34a2ced..e17180b 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/PojoMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/PojoMethodProcessor.kt
@@ -31,9 +31,9 @@
fun process(): PojoMethod {
val asMember = element.asMemberOf(owner)
return PojoMethod(
- element = element,
- resolvedType = asMember,
- name = element.name
+ element = element,
+ resolvedType = asMember,
+ name = element.name
)
}
}
\ No newline at end of file
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 31b9f4b..24b38ec 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
@@ -67,8 +67,10 @@
companion object {
val PROCESSED_ANNOTATIONS = listOf(ColumnInfo::class, Embedded::class, Relation::class)
- val TARGET_METHOD_ANNOTATIONS = arrayOf(PrimaryKey::class, ColumnInfo::class,
- Embedded::class, Relation::class)
+ val TARGET_METHOD_ANNOTATIONS = arrayOf(
+ PrimaryKey::class, ColumnInfo::class,
+ Embedded::class, Relation::class
+ )
fun createFor(
context: Context,
@@ -89,12 +91,13 @@
}
return PojoProcessor(
- baseContext = context,
- element = pojoElement,
- bindingScope = bindingScope,
- parent = parent,
- referenceStack = referenceStack,
- delegate = delegate)
+ baseContext = context,
+ element = pojoElement,
+ bindingScope = bindingScope,
+ parent = parent,
+ referenceStack = referenceStack,
+ delegate = delegate
+ )
}
}
@@ -115,42 +118,45 @@
val declaredType = element.asDeclaredType()
// TODO handle conflicts with super: b/35568142
val allFields = element.getAllFieldsIncludingPrivateSupers()
- .filter {
- !it.hasAnnotation(Ignore::class) &&
- !it.isStatic() &&
- (!it.isTransient() ||
- it.hasAnyOf(ColumnInfo::class, Embedded::class, Relation::class))
+ .filter {
+ !it.hasAnnotation(Ignore::class) &&
+ !it.isStatic() &&
+ (
+ !it.isTransient() ||
+ it.hasAnyOf(ColumnInfo::class, Embedded::class, Relation::class)
+ )
+ }
+ .groupBy { field ->
+ context.checker.check(
+ PROCESSED_ANNOTATIONS.count { field.hasAnnotation(it) } < 2, field,
+ ProcessorErrors.CANNOT_USE_MORE_THAN_ONE_POJO_FIELD_ANNOTATION
+ )
+ if (field.hasAnnotation(Embedded::class)) {
+ Embedded::class
+ } else if (field.hasAnnotation(Relation::class)) {
+ Relation::class
+ } else {
+ null
}
- .groupBy { field ->
- context.checker.check(
- PROCESSED_ANNOTATIONS.count { field.hasAnnotation(it) } < 2, field,
- ProcessorErrors.CANNOT_USE_MORE_THAN_ONE_POJO_FIELD_ANNOTATION
- )
- if (field.hasAnnotation(Embedded::class)) {
- Embedded::class
- } else if (field.hasAnnotation(Relation::class)) {
- Relation::class
- } else {
- null
- }
- }
+ }
val ignoredColumns =
element.toAnnotationBox(androidx.room.Entity::class)?.value?.ignoredColumns?.toSet()
?: emptySet()
val fieldBindingErrors = mutableMapOf<Field, String>()
val unfilteredMyFields = allFields[null]
- ?.map {
- FieldProcessor(
- baseContext = context,
- containing = declaredType,
- element = it,
- bindingScope = bindingScope,
- fieldParent = parent,
- onBindingError = { field, errorMsg ->
- fieldBindingErrors[field] = errorMsg
- }).process()
- } ?: emptyList()
+ ?.map {
+ FieldProcessor(
+ baseContext = context,
+ containing = declaredType,
+ element = it,
+ bindingScope = bindingScope,
+ fieldParent = parent,
+ onBindingError = { field, errorMsg ->
+ fieldBindingErrors[field] = errorMsg
+ }
+ ).process()
+ } ?: emptyList()
val myFields = unfilteredMyFields.filterNot { ignoredColumns.contains(it.columnName) }
myFields.forEach { field ->
fieldBindingErrors[field]?.let {
@@ -158,11 +164,11 @@
}
}
val unfilteredEmbeddedFields =
- allFields[Embedded::class]
- ?.mapNotNull {
- processEmbeddedField(declaredType, it)
- }
- ?: emptyList()
+ allFields[Embedded::class]
+ ?.mapNotNull {
+ processEmbeddedField(declaredType, it)
+ }
+ ?: emptyList()
val embeddedFields =
unfilteredEmbeddedFields.filterNot { ignoredColumns.contains(it.field.columnName) }
@@ -175,29 +181,32 @@
unfilteredCombinedFields.any { it.columnName == ignoredColumn }
}
context.checker.check(
- missingIgnoredColumns.isEmpty(), element,
- ProcessorErrors.missingIgnoredColumns(missingIgnoredColumns)
+ missingIgnoredColumns.isEmpty(), element,
+ ProcessorErrors.missingIgnoredColumns(missingIgnoredColumns)
)
val myRelationsList = allFields[Relation::class]
- ?.mapNotNull {
- processRelationField(fields, declaredType, it)
- }
- ?: emptyList()
+ ?.mapNotNull {
+ processRelationField(fields, declaredType, it)
+ }
+ ?: emptyList()
val subRelations = embeddedFields.flatMap { it.pojo.relations }
val relations = myRelationsList + subRelations
fields.groupBy { it.columnName }
- .filter { it.value.size > 1 }
- .forEach {
- context.logger.e(element, ProcessorErrors.pojoDuplicateFieldNames(
- it.key, it.value.map(Field::getPath)
- ))
- it.value.forEach {
- context.logger.e(it.element, POJO_FIELD_HAS_DUPLICATE_COLUMN_NAME)
- }
+ .filter { it.value.size > 1 }
+ .forEach {
+ context.logger.e(
+ element,
+ ProcessorErrors.pojoDuplicateFieldNames(
+ it.key, it.value.map(Field::getPath)
+ )
+ )
+ it.value.forEach {
+ context.logger.e(it.element, POJO_FIELD_HAS_DUPLICATE_COLUMN_NAME)
}
+ }
val methods = element.getAllNonPrivateInstanceMethods()
.asSequence()
@@ -240,8 +249,10 @@
assignSetter(it.field, setterCandidates, constructor)
}
- return delegate.createPojo(element, declaredType, fields, embeddedFields, relations,
- constructor)
+ return delegate.createPojo(
+ element, declaredType, fields, embeddedFields, relations,
+ constructor
+ )
}
private fun chooseConstructor(
@@ -305,13 +316,16 @@
Constructor.Param.RelationParam(relationMatches.first())
}
else -> {
- context.logger.e(param, ProcessorErrors.ambigiousConstructor(
+ context.logger.e(
+ param,
+ ProcessorErrors.ambigiousConstructor(
pojo = element.qualifiedName,
paramName = paramName,
matchingFields = matchingFields.map { it.getPath() } +
- embeddedMatches.map { it.field.getPath() } +
- relationMatches.map { it.field.getPath() }
- ))
+ embeddedMatches.map { it.field.getPath() } +
+ relationMatches.map { it.field.getPath() }
+ )
+ )
null
}
}
@@ -330,9 +344,12 @@
val failureMsg = failedConstructors.joinToString("\n") { entry ->
entry.log()
}
- context.logger.e(element, ProcessorErrors.MISSING_POJO_CONSTRUCTOR +
+ context.logger.e(
+ element,
+ ProcessorErrors.MISSING_POJO_CONSTRUCTOR +
"\nTried the following constructors but they failed to match:" +
- "\n$failureMsg")
+ "\n$failureMsg"
+ )
}
context.logger.e(element, ProcessorErrors.MISSING_POJO_CONSTRUCTOR)
return null
@@ -383,21 +400,24 @@
val fieldPrefix = variableElement.toAnnotationBox(Embedded::class)?.value?.prefix ?: ""
val inheritedPrefix = parent?.prefix ?: ""
val embeddedField = Field(
- variableElement,
- variableElement.name,
- type = asMemberType,
- affinity = null,
- parent = parent)
+ variableElement,
+ variableElement.name,
+ type = asMemberType,
+ affinity = null,
+ parent = parent
+ )
val subParent = EmbeddedField(
- field = embeddedField,
- prefix = inheritedPrefix + fieldPrefix,
- parent = parent)
+ field = embeddedField,
+ prefix = inheritedPrefix + fieldPrefix,
+ parent = parent
+ )
subParent.pojo = createFor(
- context = context.fork(variableElement),
- element = asTypeElement,
- bindingScope = bindingScope,
- parent = subParent,
- referenceStack = referenceStack).process()
+ context = context.fork(variableElement),
+ element = asTypeElement,
+ bindingScope = bindingScope,
+ parent = subParent,
+ referenceStack = referenceStack
+ ).process()
return subParent
}
@@ -412,11 +432,14 @@
it.columnName == annotation.value.parentColumn
}
if (parentField == null) {
- context.logger.e(relationElement,
- ProcessorErrors.relationCannotFindParentEntityField(
- entityName = element.qualifiedName,
- columnName = annotation.value.parentColumn,
- availableColumns = myFields.map { it.columnName }))
+ context.logger.e(
+ relationElement,
+ ProcessorErrors.relationCannotFindParentEntityField(
+ entityName = element.qualifiedName,
+ columnName = annotation.value.parentColumn,
+ availableColumns = myFields.map { it.columnName }
+ )
+ )
return null
}
// parse it as an entity.
@@ -455,11 +478,14 @@
// now find the field in the entity.
val entityField = entity.findFieldByColumnName(annotation.value.entityColumn)
if (entityField == null) {
- context.logger.e(relationElement,
- ProcessorErrors.relationCannotFindEntityField(
- entityName = entity.typeName.toString(),
- columnName = annotation.value.entityColumn,
- availableColumns = entity.columnNames))
+ context.logger.e(
+ relationElement,
+ ProcessorErrors.relationCannotFindEntityField(
+ entityName = entity.typeName.toString(),
+ columnName = annotation.value.entityColumn,
+ availableColumns = entity.columnNames
+ )
+ )
return null
}
@@ -467,7 +493,8 @@
val junctionAnnotation = annotation.getAsAnnotationBox<Junction>("associateBy")
val junctionClassInput = junctionAnnotation.getAsType("value")
val junctionElement: XTypeElement? = if (junctionClassInput != null &&
- !junctionClassInput.isTypeOf(Any::class)) {
+ !junctionClassInput.isTypeOf(Any::class)
+ ) {
junctionClassInput.asTypeElement()
} else {
null
@@ -488,12 +515,15 @@
// warn about not having indices in the junction columns, only considering
// 1st column in composite primary key and indices, since order matters.
val coveredColumns = entityOrView.primaryKey.fields.columnNames.first() +
- entityOrView.indices.map { it.columnNames.first() }
+ entityOrView.indices.map { it.columnNames.first() }
if (!coveredColumns.contains(field.columnName)) {
- context.logger.w(Warning.MISSING_INDEX_ON_JUNCTION, field.element,
+ context.logger.w(
+ Warning.MISSING_INDEX_ON_JUNCTION, field.element,
ProcessorErrors.junctionColumnWithoutIndex(
entityName = entityOrView.typeName.toString(),
- columnName = columnName))
+ columnName = columnName
+ )
+ )
}
}
return field
@@ -507,12 +537,16 @@
val junctionParentField = findAndValidateJunctionColumn(
columnName = junctionParentColumn,
onMissingField = {
- context.logger.e(junctionElement,
+ context.logger.e(
+ junctionElement,
ProcessorErrors.relationCannotFindJunctionParentField(
entityName = entityOrView.typeName.toString(),
columnName = junctionParentColumn,
- availableColumns = entityOrView.columnNames))
- })
+ availableColumns = entityOrView.columnNames
+ )
+ )
+ }
+ )
val junctionEntityColumn = if (junctionAnnotation.value.entityColumn.isNotEmpty()) {
junctionAnnotation.value.entityColumn
@@ -522,12 +556,16 @@
val junctionEntityField = findAndValidateJunctionColumn(
columnName = junctionEntityColumn,
onMissingField = {
- context.logger.e(junctionElement,
+ context.logger.e(
+ junctionElement,
ProcessorErrors.relationCannotFindJunctionEntityField(
entityName = entityOrView.typeName.toString(),
columnName = junctionEntityColumn,
- availableColumns = entityOrView.columnNames))
- })
+ availableColumns = entityOrView.columnNames
+ )
+ )
+ }
+ )
if (junctionParentField == null || junctionEntityField == null) {
return null
@@ -536,15 +574,17 @@
androidx.room.vo.Junction(
entity = entityOrView,
parentField = junctionParentField,
- entityField = junctionEntityField)
+ entityField = junctionEntityField
+ )
}
val field = Field(
- element = relationElement,
- name = relationElement.name,
- type = relationElement.asMemberOf(container),
- affinity = null,
- parent = parent)
+ element = relationElement,
+ name = relationElement.name,
+ type = relationElement.asMemberOf(container),
+ affinity = null,
+ parent = parent
+ )
val projection = if (annotation.value.projection.isEmpty()) {
// we need to infer the projection from inputs.
@@ -556,13 +596,13 @@
}
// if types don't match, row adapter prints a warning
return androidx.room.vo.Relation(
- entity = entity,
- pojoType = asType,
- field = field,
- parentField = parentField,
- entityField = entityField,
- junction = junction,
- projection = projection
+ entity = entity,
+ pojoType = asType,
+ field = field,
+ parentField = parentField,
+ entityField = entityField,
+ junction = junction,
+ projection = projection
)
}
@@ -573,9 +613,13 @@
) {
val missingColumns = projectionInput.toList() - entity.columnNames
if (missingColumns.isNotEmpty()) {
- context.logger.e(relationElement,
- ProcessorErrors.relationBadProject(entity.typeName.toString(),
- missingColumns, entity.columnNames))
+ context.logger.e(
+ relationElement,
+ ProcessorErrors.relationBadProject(
+ entity.typeName.toString(),
+ missingColumns, entity.columnNames
+ )
+ )
}
}
@@ -605,11 +649,12 @@
} else {
// last resort, it needs to be a pojo
val pojo = createFor(
- context = context,
- element = typeArgElement,
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = parent,
- referenceStack = referenceStack).process()
+ context = context,
+ element = typeArgElement,
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = parent,
+ referenceStack = referenceStack
+ ).process()
pojo.columnNames
}
}
@@ -618,10 +663,11 @@
private fun detectReferenceRecursion(typeElement: XTypeElement): Boolean {
if (referenceStack.contains(typeElement.qualifiedName)) {
context.logger.e(
- typeElement,
- ProcessorErrors
- .RECURSIVE_REFERENCE_DETECTED
- .format(computeReferenceRecursionString(typeElement)))
+ typeElement,
+ ProcessorErrors
+ .RECURSIVE_REFERENCE_DETECTED
+ .format(computeReferenceRecursionString(typeElement))
+ )
return true
}
return false
@@ -647,31 +693,38 @@
}
private fun assignGetter(field: Field, getterCandidates: List<PojoMethod>) {
- val success = chooseAssignment(field = field,
- candidates = getterCandidates,
- nameVariations = field.getterNameWithVariations,
- getType = { method ->
- method.resolvedType.returnType
- },
- assignFromField = {
- field.getter = FieldGetter(
- name = field.name,
- type = field.type,
- callType = CallType.FIELD)
- },
- assignFromMethod = { match ->
- field.getter = FieldGetter(
- name = match.name,
- type = match.resolvedType.returnType,
- callType = CallType.METHOD)
- },
- reportAmbiguity = { matching ->
- context.logger.e(field.element,
- ProcessorErrors.tooManyMatchingGetters(field, matching))
- })
+ val success = chooseAssignment(
+ field = field,
+ candidates = getterCandidates,
+ nameVariations = field.getterNameWithVariations,
+ getType = { method ->
+ method.resolvedType.returnType
+ },
+ assignFromField = {
+ field.getter = FieldGetter(
+ name = field.name,
+ type = field.type,
+ callType = CallType.FIELD
+ )
+ },
+ assignFromMethod = { match ->
+ field.getter = FieldGetter(
+ name = match.name,
+ type = match.resolvedType.returnType,
+ callType = CallType.METHOD
+ )
+ },
+ reportAmbiguity = { matching ->
+ context.logger.e(
+ field.element,
+ ProcessorErrors.tooManyMatchingGetters(field, matching)
+ )
+ }
+ )
context.checker.check(
success || bindingScope == FieldProcessor.BindingScope.READ_FROM_CURSOR,
- field.element, CANNOT_FIND_GETTER_FOR_FIELD)
+ field.element, CANNOT_FIND_GETTER_FOR_FIELD
+ )
if (success && !field.getter.type.isSameType(field.type)) {
// getter's parameter type is not exactly the same as the field type.
// put a warning and update the value statement binder.
@@ -683,7 +736,8 @@
ownerType = element.type.typeName,
getterType = field.getter.type.typeName,
fieldType = field.typeName
- ))
+ )
+ )
field.statementBinder = context.typeAdapterStore.findStatementValueBinder(
input = field.getter.type,
affinity = field.affinity
@@ -708,38 +762,45 @@
) {
if (constructor != null && constructor.hasField(field)) {
field.setter = FieldSetter(
- name = field.name,
- type = field.type,
- callType = CallType.CONSTRUCTOR
+ name = field.name,
+ type = field.type,
+ callType = CallType.CONSTRUCTOR
)
return
}
- val success = chooseAssignment(field = field,
- candidates = setterCandidates,
- nameVariations = field.setterNameWithVariations,
- getType = { method ->
- method.resolvedType.parameterTypes.first()
- },
- assignFromField = {
- field.setter = FieldSetter(
- name = field.name,
- type = field.type,
- callType = CallType.FIELD)
- },
- assignFromMethod = { match ->
- val paramType = match.resolvedType.parameterTypes.first()
- field.setter = FieldSetter(
- name = match.name,
- type = paramType,
- callType = CallType.METHOD)
- },
- reportAmbiguity = { matching ->
- context.logger.e(field.element,
- ProcessorErrors.tooManyMatchingSetter(field, matching))
- })
+ val success = chooseAssignment(
+ field = field,
+ candidates = setterCandidates,
+ nameVariations = field.setterNameWithVariations,
+ getType = { method ->
+ method.resolvedType.parameterTypes.first()
+ },
+ assignFromField = {
+ field.setter = FieldSetter(
+ name = field.name,
+ type = field.type,
+ callType = CallType.FIELD
+ )
+ },
+ assignFromMethod = { match ->
+ val paramType = match.resolvedType.parameterTypes.first()
+ field.setter = FieldSetter(
+ name = match.name,
+ type = paramType,
+ callType = CallType.METHOD
+ )
+ },
+ reportAmbiguity = { matching ->
+ context.logger.e(
+ field.element,
+ ProcessorErrors.tooManyMatchingSetter(field, matching)
+ )
+ }
+ )
context.checker.check(
success || bindingScope == FieldProcessor.BindingScope.BIND_TO_STMT,
- field.element, CANNOT_FIND_SETTER_FOR_FIELD)
+ field.element, CANNOT_FIND_SETTER_FOR_FIELD
+ )
if (success && !field.setter.type.isSameType(field.type)) {
// setter's parameter type is not exactly the same as the field type.
// put a warning and update the value reader adapter.
@@ -751,7 +812,8 @@
ownerType = element.type.typeName,
setterType = field.setter.type.typeName,
fieldType = field.typeName
- ))
+ )
+ )
field.cursorValueReader = context.typeAdapterStore.findCursorValueReader(
output = field.setter.type,
affinity = field.affinity
@@ -780,15 +842,17 @@
}
val matching = candidates
- .filter {
- // b/69164099
- field.type.isAssignableFromWithoutVariance(getType(it)) &&
- (field.nameWithVariations.contains(it.name) ||
- nameVariations.contains(it.name))
- }
- .groupBy {
- it.element.isPublic()
- }
+ .filter {
+ // b/69164099
+ field.type.isAssignableFromWithoutVariance(getType(it)) &&
+ (
+ field.nameWithVariations.contains(it.name) ||
+ nameVariations.contains(it.name)
+ )
+ }
+ .groupBy {
+ it.element.isPublic()
+ }
if (matching.isEmpty()) {
// we always assign to avoid NPEs in the rest of the compilation.
assignFromField()
@@ -798,7 +862,7 @@
}
// first try public ones, then try non-public
val match = verifyAndChooseOneFrom(matching[true], reportAmbiguity)
- ?: verifyAndChooseOneFrom(matching[false], reportAmbiguity)
+ ?: verifyAndChooseOneFrom(matching[false], reportAmbiguity)
if (match == null) {
assignFromField()
return false
@@ -851,8 +915,10 @@
val annotationName = TARGET_METHOD_ANNOTATIONS
.first { method.hasAnnotation(it) }
.java.simpleName
- context.logger.e(method,
- ProcessorErrors.invalidAnnotationTarget(annotationName, method.kindName()))
+ context.logger.e(
+ method,
+ ProcessorErrors.invalidAnnotationTarget(annotationName, method.kindName())
+ )
}
}
@@ -869,12 +935,13 @@
constructor: Constructor?
): Pojo {
return Pojo(
- element = element,
- type = declaredType,
- fields = fields,
- embeddedFields = embeddedFields,
- relations = relations,
- constructor = constructor)
+ element = element,
+ type = declaredType,
+ fields = fields,
+ embeddedFields = embeddedFields,
+ relations = relations,
+ constructor = constructor
+ )
}
}
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 075dbac..c380e6a 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
@@ -40,31 +40,31 @@
val MISSING_DELETE_ANNOTATION = "Deletion methods must be annotated with ${Delete::class.java}"
val MISSING_UPDATE_ANNOTATION = "Update methods must be annotated with ${Update::class.java}"
val MISSING_RAWQUERY_ANNOTATION = "RawQuery methods must be annotated with" +
- " ${RawQuery::class.java}"
+ " ${RawQuery::class.java}"
val INVALID_ON_CONFLICT_VALUE = "On conflict value must be one of @OnConflictStrategy values."
val TRANSACTION_REFERENCE_DOCS = "https://developer.android.com/reference/androidx/" +
- "room/Transaction.html"
+ "room/Transaction.html"
val INVALID_ANNOTATION_COUNT_IN_DAO_METHOD = "An abstract DAO method must be" +
- " annotated with one and only one of the following annotations: " +
- DaoProcessor.PROCESSED_ANNOTATIONS.joinToString(",") {
- it.java.simpleName
- }
+ " annotated with one and only one of the following annotations: " +
+ DaoProcessor.PROCESSED_ANNOTATIONS.joinToString(",") {
+ it.java.simpleName
+ }
val CANNOT_RESOLVE_RETURN_TYPE = "Cannot resolve return type for %s"
val CANNOT_USE_UNBOUND_GENERICS_IN_QUERY_METHODS = "Cannot use unbound generics in query" +
- " methods. It must be bound to a type through base Dao class."
+ " methods. It must be bound to a type through base Dao class."
val CANNOT_USE_UNBOUND_GENERICS_IN_INSERTION_METHODS = "Cannot use unbound generics in" +
- " insertion methods. It must be bound to a type through base Dao class."
+ " insertion methods. It must be bound to a type through base Dao class."
val CANNOT_USE_UNBOUND_GENERICS_IN_ENTITY_FIELDS = "Cannot use unbound fields in entities."
val CANNOT_USE_UNBOUND_GENERICS_IN_DAO_CLASSES = "Cannot use unbound generics in Dao classes." +
- " If you are trying to create a base DAO, create a normal class, extend it with type" +
- " params then mark the subclass with @Dao."
+ " If you are trying to create a base DAO, create a normal class, extend it with type" +
+ " params then mark the subclass with @Dao."
val CANNOT_FIND_GETTER_FOR_FIELD = "Cannot find getter for field."
val CANNOT_FIND_SETTER_FOR_FIELD = "Cannot find setter for field."
val MISSING_PRIMARY_KEY = "An entity must have at least 1 field annotated with @PrimaryKey"
val AUTO_INCREMENTED_PRIMARY_KEY_IS_NOT_INT = "If a primary key is annotated with" +
- " autoGenerate, its type must be int, Integer, long or Long."
+ " autoGenerate, its type must be int, Integer, long or Long."
val AUTO_INCREMENT_EMBEDDED_HAS_MULTIPLE_FIELDS = "When @PrimaryKey annotation is used on a" +
- " field annotated with @Embedded, the embedded class should have only 1 field."
+ " field annotated with @Embedded, the embedded class should have only 1 field."
fun multiplePrimaryKeyAnnotations(primaryKeys: List<String>): String {
return """
@@ -76,11 +76,11 @@
fun primaryKeyColumnDoesNotExist(columnName: String, allColumns: List<String>): String {
return "$columnName referenced in the primary key does not exists in the Entity." +
- " Available column names:${allColumns.joinToString(", ")}"
+ " Available column names:${allColumns.joinToString(", ")}"
}
val DAO_MUST_BE_AN_ABSTRACT_CLASS_OR_AN_INTERFACE = "Dao class must be an abstract class or" +
- " an interface"
+ " an interface"
val DAO_MUST_BE_ANNOTATED_WITH_DAO = "Dao class must be annotated with @Dao"
fun daoMustHaveMatchingConstructor(daoName: String, dbName: String): String {
@@ -92,106 +92,106 @@
val ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY = "Entity class must be annotated with @Entity"
val DATABASE_ANNOTATION_MUST_HAVE_LIST_OF_ENTITIES = "@Database annotation must specify list" +
- " of entities"
+ " of entities"
val COLUMN_NAME_CANNOT_BE_EMPTY = "Column name cannot be blank. If you don't want to set it" +
- ", just remove the @ColumnInfo annotation or use @ColumnInfo.INHERIT_FIELD_NAME."
+ ", just remove the @ColumnInfo annotation or use @ColumnInfo.INHERIT_FIELD_NAME."
val ENTITY_TABLE_NAME_CANNOT_BE_EMPTY = "Entity table name cannot be blank. If you don't want" +
- " to set it, just remove the tableName property."
+ " to set it, just remove the tableName property."
val ENTITY_TABLE_NAME_CANNOT_START_WITH_SQLITE =
"Entity table name cannot start with \"sqlite_\"."
val VIEW_MUST_BE_ANNOTATED_WITH_DATABASE_VIEW = "View class must be annotated with " +
- "@DatabaseView"
+ "@DatabaseView"
val VIEW_NAME_CANNOT_BE_EMPTY = "View name cannot be blank. If you don't want" +
- " to set it, just remove the viewName property."
+ " to set it, just remove the viewName property."
val VIEW_NAME_CANNOT_START_WITH_SQLITE =
- "View name cannot start with \"sqlite_\"."
+ "View name cannot start with \"sqlite_\"."
val VIEW_QUERY_MUST_BE_SELECT =
- "Query for @DatabaseView must be a SELECT."
+ "Query for @DatabaseView must be a SELECT."
val VIEW_QUERY_CANNOT_TAKE_ARGUMENTS =
- "Query for @DatabaseView cannot take any arguments."
+ "Query for @DatabaseView cannot take any arguments."
fun viewCircularReferenceDetected(views: List<String>): String {
return "Circular reference detected among views: ${views.joinToString(", ")}"
}
val CANNOT_BIND_QUERY_PARAMETER_INTO_STMT = "Query method parameters should either be a" +
- " type that can be converted into a database column or a List / Array that contains" +
- " such type. You can consider adding a Type Adapter for this."
+ " type that can be converted into a database column or a List / Array that contains" +
+ " such type. You can consider adding a Type Adapter for this."
val QUERY_PARAMETERS_CANNOT_START_WITH_UNDERSCORE = "Query/Insert method parameters cannot " +
- "start with underscore (_)."
+ "start with underscore (_)."
fun cannotFindQueryResultAdapter(returnTypeName: String) = "Not sure how to convert a " +
- "Cursor to this method's return type ($returnTypeName)."
+ "Cursor to this method's return type ($returnTypeName)."
val INSERTION_DOES_NOT_HAVE_ANY_PARAMETERS_TO_INSERT = "Method annotated with" +
- " @Insert but does not have any parameters to insert."
+ " @Insert but does not have any parameters to insert."
val DELETION_MISSING_PARAMS = "Method annotated with" +
- " @Delete but does not have any parameters to delete."
+ " @Delete but does not have any parameters to delete."
val CANNOT_FIND_DELETE_RESULT_ADAPTER = "Not sure how to handle delete method's " +
- "return type. Currently the supported return types are void, int or Int."
+ "return type. Currently the supported return types are void, int or Int."
val CANNOT_FIND_UPDATE_RESULT_ADAPTER = "Not sure how to handle update method's " +
- "return type. Currently the supported return types are void, int or Int."
+ "return type. Currently the supported return types are void, int or Int."
val CANNOT_FIND_INSERT_RESULT_ADAPTER = "Not sure how to handle insert method's return type."
val UPDATE_MISSING_PARAMS = "Method annotated with" +
- " @Update but does not have any parameters to update."
+ " @Update but does not have any parameters to update."
val TRANSACTION_METHOD_MODIFIERS = "Method annotated with @Transaction must not be " +
- "private, final, or abstract. It can be abstract only if the method is also" +
- " annotated with @Query."
+ "private, final, or abstract. It can be abstract only if the method is also" +
+ " annotated with @Query."
fun transactionMethodAsync(returnTypeName: String) = "Method annotated with @Transaction must" +
- " not return deferred/async return type $returnTypeName. Since transactions are" +
- " thread confined and Room cannot guarantee that all queries in the method" +
- " implementation are performed on the same thread, only synchronous @Transaction" +
- " implemented methods are allowed. If a transaction is started and a change of thread" +
- " is done and waited upon then a database deadlock can occur if the additional thread" +
- " attempts to perform a query. This restrictions prevents such situation from" +
- " occurring."
+ " not return deferred/async return type $returnTypeName. Since transactions are" +
+ " thread confined and Room cannot guarantee that all queries in the method" +
+ " implementation are performed on the same thread, only synchronous @Transaction" +
+ " implemented methods are allowed. If a transaction is started and a change of thread" +
+ " is done and waited upon then a database deadlock can occur if the additional thread" +
+ " attempts to perform a query. This restrictions prevents such situation from" +
+ " occurring."
val TRANSACTION_MISSING_ON_RELATION = "The return value includes a POJO with a @Relation." +
- " It is usually desired to annotate this method with @Transaction to avoid" +
- " possibility of inconsistent results between the POJO and its relations. See " +
- TRANSACTION_REFERENCE_DOCS + " for details."
+ " It is usually desired to annotate this method with @Transaction to avoid" +
+ " possibility of inconsistent results between the POJO and its relations. See " +
+ TRANSACTION_REFERENCE_DOCS + " for details."
val CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER = "Type of the parameter must be a class " +
- "annotated with @Entity or a collection/array of it."
+ "annotated with @Entity or a collection/array of it."
val DB_MUST_EXTEND_ROOM_DB = "Classes annotated with @Database should extend " +
- RoomTypeNames.ROOM_DB
+ RoomTypeNames.ROOM_DB
val OBSERVABLE_QUERY_NOTHING_TO_OBSERVE = "Observable query return type (LiveData, Flowable" +
- ", DataSource, DataSourceFactory etc) can only be used with SELECT queries that" +
- " directly or indirectly (via @Relation, for example) access at least one table. For" +
- " @RawQuery, you should specify the list of tables to be observed via the" +
- " observedEntities field."
+ ", DataSource, DataSourceFactory etc) can only be used with SELECT queries that" +
+ " directly or indirectly (via @Relation, for example) access at least one table. For" +
+ " @RawQuery, you should specify the list of tables to be observed via the" +
+ " observedEntities field."
val RECURSIVE_REFERENCE_DETECTED = "Recursive referencing through @Embedded and/or @Relation " +
- "detected: %s"
+ "detected: %s"
private val TOO_MANY_MATCHING_GETTERS = "Ambiguous getter for %s. All of the following " +
- "match: %s. You can @Ignore the ones that you don't want to match."
+ "match: %s. You can @Ignore the ones that you don't want to match."
fun tooManyMatchingGetters(field: Field, methodNames: List<String>): String {
return TOO_MANY_MATCHING_GETTERS.format(field, methodNames.joinToString(", "))
}
private val TOO_MANY_MATCHING_SETTERS = "Ambiguous setter for %s. All of the following " +
- "match: %s. You can @Ignore the ones that you don't want to match."
+ "match: %s. You can @Ignore the ones that you don't want to match."
fun tooManyMatchingSetter(field: Field, methodNames: List<String>): String {
return TOO_MANY_MATCHING_SETTERS.format(field, methodNames.joinToString(", "))
}
val CANNOT_FIND_COLUMN_TYPE_ADAPTER = "Cannot figure out how to save this field into" +
- " database. You can consider adding a type converter for it."
+ " database. You can consider adding a type converter for it."
val CANNOT_FIND_STMT_BINDER = "Cannot figure out how to bind this field into a statement."
@@ -200,7 +200,7 @@
const val DEFAULT_VALUE_NULLABILITY = "Use of NULL as the default value of a non-null field"
private val MISSING_PARAMETER_FOR_BIND = "Each bind variable in the query must have a" +
- " matching method parameter. Cannot find method parameters for %s."
+ " matching method parameter. Cannot find method parameters for %s."
fun missingParameterForBindVariable(bindVarName: List<String>): String {
return MISSING_PARAMETER_FOR_BIND.format(bindVarName.joinToString(", "))
@@ -209,12 +209,13 @@
private val UNUSED_QUERY_METHOD_PARAMETER = "Unused parameter%s: %s"
fun unusedQueryMethodParameter(unusedParams: List<String>): String {
return UNUSED_QUERY_METHOD_PARAMETER.format(
- if (unusedParams.size > 1) "s" else "",
- unusedParams.joinToString(","))
+ if (unusedParams.size > 1) "s" else "",
+ unusedParams.joinToString(",")
+ )
}
private val DUPLICATE_TABLES_OR_VIEWS =
- "The name \"%s\" is used by multiple entities or views: %s"
+ "The name \"%s\" is used by multiple entities or views: %s"
fun duplicateTableNames(tableName: String, entityNames: List<String>): String {
return DUPLICATE_TABLES_OR_VIEWS.format(tableName, entityNames.joinToString(", "))
}
@@ -289,15 +290,15 @@
val TYPE_CONVERTER_BAD_RETURN_TYPE = "Invalid return type for a type converter."
val TYPE_CONVERTER_MUST_RECEIVE_1_PARAM = "Type converters must receive 1 parameter."
val TYPE_CONVERTER_EMPTY_CLASS = "Class is referenced as a converter but it does not have any" +
- " converter methods."
+ " converter methods."
val TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR = "Classes that are used as TypeConverters must" +
- " have no-argument public constructors. Use a ProvidedTypeConverter annotation if you" +
- " need to take control over creating an instance of a TypeConverter."
+ " have no-argument public constructors. Use a ProvidedTypeConverter annotation if you" +
+ " need to take control over creating an instance of a TypeConverter."
val TYPE_CONVERTER_MUST_BE_PUBLIC = "Type converters must be public."
fun duplicateTypeConverters(converters: List<CustomTypeConverter>): String {
return "Multiple methods define the same conversion. Conflicts with these:" +
- " ${converters.joinToString(", ") { it.toString() }}"
+ " ${converters.joinToString(", ") { it.toString() }}"
}
// TODO must print field paths.
@@ -305,48 +306,48 @@
fun pojoDuplicateFieldNames(columnName: String, fieldPaths: List<String>): String {
return "Multiple fields have the same columnName: $columnName." +
- " Field names: ${fieldPaths.joinToString(", ")}."
+ " Field names: ${fieldPaths.joinToString(", ")}."
}
fun embeddedPrimaryKeyIsDropped(entityQName: String, fieldName: String): String {
return "Primary key constraint on $fieldName is ignored when being merged into " +
- entityQName
+ entityQName
}
val INDEX_COLUMNS_CANNOT_BE_EMPTY = "List of columns in an index cannot be empty"
fun indexColumnDoesNotExist(columnName: String, allColumns: List<String>): String {
return "$columnName referenced in the index does not exists in the Entity." +
- " Available column names:${allColumns.joinToString(", ")}"
+ " Available column names:${allColumns.joinToString(", ")}"
}
fun duplicateIndexInEntity(indexName: String): String {
return "There are multiple indices with name $indexName. This happen if you've declared" +
- " the same index multiple times or different indices have the same name. See" +
- " @Index documentation for details."
+ " the same index multiple times or different indices have the same name. See" +
+ " @Index documentation for details."
}
fun duplicateIndexInDatabase(indexName: String, indexPaths: List<String>): String {
return "There are multiple indices with name $indexName. You should rename " +
- "${indexPaths.size - 1} of these to avoid the conflict:" +
- "${indexPaths.joinToString(", ")}."
+ "${indexPaths.size - 1} of these to avoid the conflict:" +
+ "${indexPaths.joinToString(", ")}."
}
fun droppedEmbeddedFieldIndex(fieldPath: String, grandParent: String): String {
return "The index will be dropped when being merged into $grandParent" +
- "($fieldPath). You must re-declare it in $grandParent if you want to index this" +
- " field in $grandParent."
+ "($fieldPath). You must re-declare it in $grandParent if you want to index this" +
+ " field in $grandParent."
}
fun droppedEmbeddedIndex(entityName: String, fieldPath: String, grandParent: String): String {
return "Indices defined in $entityName will be dropped when it is merged into" +
- " $grandParent ($fieldPath). You can re-declare them in $grandParent."
+ " $grandParent ($fieldPath). You can re-declare them in $grandParent."
}
fun droppedSuperClassIndex(childEntity: String, superEntity: String): String {
return "Indices defined in $superEntity will NOT be re-used in $childEntity. If you want" +
- " to inherit them, you must re-declare them in $childEntity." +
- " Alternatively, you can set inheritSuperIndices to true in the @Entity annotation."
+ " to inherit them, you must re-declare them in $childEntity." +
+ " Alternatively, you can set inheritSuperIndices to true in the @Entity annotation."
}
fun droppedSuperClassFieldIndex(
@@ -355,9 +356,9 @@
superEntity: String
): String {
return "Index defined on field `$fieldName` in $superEntity will NOT be re-used in" +
- " $childEntity. " +
- "If you want to inherit it, you must re-declare it in $childEntity." +
- " Alternatively, you can set inheritSuperIndices to true in the @Entity annotation."
+ " $childEntity. " +
+ "If you want to inherit it, you must re-declare it in $childEntity." +
+ " Alternatively, you can set inheritSuperIndices to true in the @Entity annotation."
}
val NOT_ENTITY_OR_VIEW = "The class must be either @Entity or @DatabaseView."
@@ -368,7 +369,7 @@
availableColumns: List<String>
): String {
return "Cannot find the child entity column `$columnName` in $entityName." +
- " Options: ${availableColumns.joinToString(", ")}"
+ " Options: ${availableColumns.joinToString(", ")}"
}
fun relationCannotFindParentEntityField(
@@ -377,7 +378,7 @@
availableColumns: List<String>
): String {
return "Cannot find the parent entity column `$columnName` in $entityName." +
- " Options: ${availableColumns.joinToString(", ")}"
+ " Options: ${availableColumns.joinToString(", ")}"
}
fun relationCannotFindJunctionEntityField(
@@ -386,7 +387,7 @@
availableColumns: List<String>
): String {
return "Cannot find the child entity referencing column `$columnName` in the junction " +
- "$entityName. Options: ${availableColumns.joinToString(", ")}"
+ "$entityName. Options: ${availableColumns.joinToString(", ")}"
}
fun relationCannotFindJunctionParentField(
@@ -395,14 +396,14 @@
availableColumns: List<String>
): String {
return "Cannot find the parent entity referencing column `$columnName` in the junction " +
- "$entityName. Options: ${availableColumns.joinToString(", ")}"
+ "$entityName. Options: ${availableColumns.joinToString(", ")}"
}
fun junctionColumnWithoutIndex(entityName: String, columnName: String) =
- "The column $columnName in the junction entity $entityName is being used to resolve " +
- "a relationship but it is not covered by any index. This might cause a " +
- "full table scan when resolving the relationship, it is highly advised to " +
- "create an index that covers this column."
+ "The column $columnName in the junction entity $entityName is being used to resolve " +
+ "a relationship but it is not covered by any index. This might cause a " +
+ "full table scan when resolving the relationship, it is highly advised to " +
+ "create an index that covers this column."
val RELATION_IN_ENTITY = "Entities cannot have relations."
@@ -445,13 +446,13 @@
}
val CANNOT_USE_MORE_THAN_ONE_POJO_FIELD_ANNOTATION = "A field can be annotated with only" +
- " one of the following:" + PojoProcessor.PROCESSED_ANNOTATIONS.joinToString(",") {
+ " one of the following:" + PojoProcessor.PROCESSED_ANNOTATIONS.joinToString(",") {
it.java.simpleName
}
fun missingIgnoredColumns(missingIgnoredColumns: List<String>): String {
return "Non-existent columns are specified to be ignored in ignoreColumns: " +
- missingIgnoredColumns.joinToString(",")
+ missingIgnoredColumns.joinToString(",")
}
fun relationBadProject(
@@ -466,11 +467,11 @@
}
val MISSING_SCHEMA_EXPORT_DIRECTORY = "Schema export directory is not provided to the" +
- " annotation processor so we cannot export the schema. You can either provide" +
- " `room.schemaLocation` annotation processor argument OR set exportSchema to false."
+ " annotation processor so we cannot export the schema. You can either provide" +
+ " `room.schemaLocation` annotation processor argument OR set exportSchema to false."
val INVALID_FOREIGN_KEY_ACTION = "Invalid foreign key action. It must be one of the constants" +
- " defined in ForeignKey.Action"
+ " defined in ForeignKey.Action"
fun foreignKeyNotAnEntity(className: String): String {
return """
@@ -483,7 +484,7 @@
fun foreignKeyChildColumnDoesNotExist(columnName: String, allColumns: List<String>): String {
return "($columnName) referenced in the foreign key does not exists in the Entity." +
- " Available column names:${allColumns.joinToString(", ")}"
+ " Available column names:${allColumns.joinToString(", ")}"
}
fun foreignKeyParentColumnDoesNotExist(
@@ -492,7 +493,7 @@
allColumns: List<String>
): String {
return "($missingColumn) does not exist in $parentEntity. Available columns are" +
- " ${allColumns.joinToString(",")}"
+ " ${allColumns.joinToString(",")}"
}
val FOREIGN_KEY_EMPTY_CHILD_COLUMN_LIST = "Must specify at least 1 column name for the child"
@@ -558,16 +559,16 @@
}
val MISSING_ROOM_GUAVA_ARTIFACT = "To use Guava features, you must add `guava`" +
- " artifact from Room as a dependency. androidx.room:room-guava:<version>"
+ " artifact from Room as a dependency. androidx.room:room-guava:<version>"
val MISSING_ROOM_RXJAVA2_ARTIFACT = "To use RxJava2 features, you must add `rxjava2`" +
- " artifact from Room as a dependency. androidx.room:room-rxjava2:<version>"
+ " artifact from Room as a dependency. androidx.room:room-rxjava2:<version>"
val MISSING_ROOM_RXJAVA3_ARTIFACT = "To use RxJava3 features, you must add `rxjava3`" +
- " artifact from Room as a dependency. androidx.room:room-rxjava3:<version>"
+ " artifact from Room as a dependency. androidx.room:room-rxjava3:<version>"
val MISSING_ROOM_COROUTINE_ARTIFACT = "To use Coroutine features, you must add `ktx`" +
- " artifact from Room as a dependency. androidx.room:room-ktx:<version>"
+ " artifact from Room as a dependency. androidx.room:room-ktx:<version>"
fun ambigiousConstructor(
pojo: String,
@@ -600,22 +601,22 @@
val PAGING_SPECIFY_DATA_SOURCE_TYPE = "For now, Room only supports PositionalDataSource class."
val PAGING_SPECIFY_PAGING_SOURCE_TYPE = "For now, Room only supports PagingSource with Key of" +
- " type Int."
+ " type Int."
fun primaryKeyNull(field: String): String {
return "You must annotate primary keys with @NonNull. \"$field\" is nullable. SQLite " +
- "considers this a " +
- "bug and Room does not allow it. See SQLite docs for details: " +
- "https://www.sqlite.org/lang_createtable.html"
+ "considers this a " +
+ "bug and Room does not allow it. See SQLite docs for details: " +
+ "https://www.sqlite.org/lang_createtable.html"
}
val INVALID_COLUMN_NAME = "Invalid column name. Room does not allow using ` or \" in column" +
- " names"
+ " names"
val INVALID_TABLE_NAME = "Invalid table name. Room does not allow using ` or \" in table names"
val RAW_QUERY_BAD_PARAMS = "RawQuery methods should have 1 and only 1 parameter with type" +
- " String or SupportSQLiteQuery"
+ " String or SupportSQLiteQuery"
val RAW_QUERY_BAD_RETURN_TYPE = "RawQuery methods must return a non-void type."
@@ -629,10 +630,10 @@
}
val RAW_QUERY_STRING_PARAMETER_REMOVED = "RawQuery does not allow passing a string anymore." +
- " Please use ${SupportDbTypeNames.QUERY}."
+ " Please use ${SupportDbTypeNames.QUERY}."
val MISSING_COPY_ANNOTATIONS = "Annotated property getter is missing " +
- "@AutoValue.CopyAnnotations."
+ "@AutoValue.CopyAnnotations."
fun invalidAnnotationTarget(annotationName: String, elementKindName: String): String {
return "@$annotationName is not allowed in this $elementKindName."
@@ -643,49 +644,49 @@
val FOREIGN_KEYS_IN_FTS_ENTITY = "Foreign Keys not allowed in FTS Entity."
val MISSING_PRIMARY_KEYS_ANNOTATION_IN_ROW_ID = "The field with column name 'rowid' in " +
- "an FTS entity must be annotated with @PrimaryKey."
+ "an FTS entity must be annotated with @PrimaryKey."
val TOO_MANY_PRIMARY_KEYS_IN_FTS_ENTITY = "An FTS entity can only have a single primary key."
val INVALID_FTS_ENTITY_PRIMARY_KEY_NAME = "The single primary key field in an FTS entity " +
- "must either be named 'rowid' or must be annotated with @ColumnInfo(name = \"rowid\")"
+ "must either be named 'rowid' or must be annotated with @ColumnInfo(name = \"rowid\")"
val INVALID_FTS_ENTITY_PRIMARY_KEY_AFFINITY = "The single @PrimaryKey annotated field in an " +
- "FTS entity must be of INTEGER affinity."
+ "FTS entity must be of INTEGER affinity."
fun missingLanguageIdField(columnName: String) = "The specified 'languageid' column: " +
- "\"$columnName\", was not found."
+ "\"$columnName\", was not found."
val INVALID_FTS_ENTITY_LANGUAGE_ID_AFFINITY = "The 'languageid' field must be of INTEGER " +
- "affinity."
+ "affinity."
fun missingNotIndexedField(missingNotIndexedColumns: List<String>) =
- "Non-existent columns are specified to be not indexed in notIndexed: " +
- missingNotIndexedColumns.joinToString(",")
+ "Non-existent columns are specified to be not indexed in notIndexed: " +
+ missingNotIndexedColumns.joinToString(",")
val INVALID_FTS_ENTITY_PREFIX_SIZES = "Prefix sizes to index must non-zero positive values."
val FTS_EXTERNAL_CONTENT_CANNOT_FIND_ENTITY = "Cannot find external content entity class."
fun externalContentNotAnEntity(className: String) = "External content entity referenced in " +
- "a Fts4 annotation must be a @Entity class. $className is not an entity"
+ "a Fts4 annotation must be a @Entity class. $className is not an entity"
fun missingFtsContentField(ftsClassName: String, columnName: String, contentClassName: String) =
- "External Content FTS Entity '$ftsClassName' has declared field with column name " +
- "'$columnName' that was not found in the external content entity " +
- "'$contentClassName'."
+ "External Content FTS Entity '$ftsClassName' has declared field with column name " +
+ "'$columnName' that was not found in the external content entity " +
+ "'$contentClassName'."
fun missingExternalContentEntity(ftsClassName: String, contentClassName: String) =
- "External Content FTS Entity '$ftsClassName' has a declared content entity " +
- "'$contentClassName' that is not present in the same @Database. Maybe you " +
- "forgot to add it to the entities section of the @Database?"
+ "External Content FTS Entity '$ftsClassName' has a declared content entity " +
+ "'$contentClassName' that is not present in the same @Database. Maybe you " +
+ "forgot to add it to the entities section of the @Database?"
fun cannotFindAsEntityField(entityName: String) = "Cannot find a column in the entity " +
- "$entityName that matches with this partial entity field. If you don't wish to use " +
- "the field then you can annotate it with @Ignore."
+ "$entityName that matches with this partial entity field. If you don't wish to use " +
+ "the field then you can annotate it with @Ignore."
val INVALID_TARGET_ENTITY_IN_SHORTCUT_METHOD = "Target entity declared in @Insert, @Update " +
- "or @Delete must be annotated with @Entity."
+ "or @Delete must be annotated with @Entity."
val INVALID_RELATION_IN_PARTIAL_ENTITY = "Partial entities cannot have relations."
@@ -699,21 +700,21 @@
partialEntityName: String,
primaryKeyNames: List<String>
) = "The partial entity $partialEntityName is missing the primary key fields " +
- "(${primaryKeyNames.joinToString()}) needed to perform an INSERT. If your single " +
- "primary key is auto generated then the fields are optional."
+ "(${primaryKeyNames.joinToString()}) needed to perform an INSERT. If your single " +
+ "primary key is auto generated then the fields are optional."
fun missingRequiredColumnsInPartialEntity(
partialEntityName: String,
missingColumnNames: List<String>
) = "The partial entity $partialEntityName is missing required columns " +
- "(${missingColumnNames.joinToString()}) needed to perform an INSERT. These are " +
- "NOT NULL columns without default values."
+ "(${missingColumnNames.joinToString()}) needed to perform an INSERT. These are " +
+ "NOT NULL columns without default values."
fun missingPrimaryKeysInPartialEntityForUpdate(
partialEntityName: String,
primaryKeyNames: List<String>
) = "The partial entity $partialEntityName is missing the primary key fields " +
- "(${primaryKeyNames.joinToString()}) needed to perform an UPDATE."
+ "(${primaryKeyNames.joinToString()}) needed to perform an UPDATE."
fun cannotFindPreparedQueryResultAdapter(
returnType: String,
@@ -721,26 +722,32 @@
) = StringBuilder().apply {
append("Not sure how to handle query method's return type ($returnType). ")
if (type == QueryType.INSERT) {
- append("INSERT query methods must either return void " +
- "or long (the rowid of the inserted row).")
+ append(
+ "INSERT query methods must either return void " +
+ "or long (the rowid of the inserted row)."
+ )
} else if (type == QueryType.UPDATE) {
- append("UPDATE query methods must either return void " +
- "or int (the number of updated rows).")
+ append(
+ "UPDATE query methods must either return void " +
+ "or int (the number of updated rows)."
+ )
} else if (type == QueryType.DELETE) {
- append("DELETE query methods must either return void " +
- "or int (the number of deleted rows).")
+ append(
+ "DELETE query methods must either return void " +
+ "or int (the number of deleted rows)."
+ )
}
}.toString()
val JDK_VERSION_HAS_BUG =
"Current JDK version ${System.getProperty("java.runtime.version") ?: ""} has a bug" +
- " (https://bugs.openjdk.java.net/browse/JDK-8007720)" +
- " that prevents Room from being incremental." +
- " Consider using JDK 11+ or the embedded JDK shipped with Android Studio 3.5+."
+ " (https://bugs.openjdk.java.net/browse/JDK-8007720)" +
+ " that prevents Room from being incremental." +
+ " Consider using JDK 11+ or the embedded JDK shipped with Android Studio 3.5+."
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."
+ "Instead declare return type as ${KotlinTypeNames.FLOW} and use Flow transforming " +
+ "functions that converts the Flow into a Channel."
fun mismatchedGetter(
fieldName: String,
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/QueryParameterProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/QueryParameterProcessor.kt
index 4591d69..29fd451 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/QueryParameterProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/QueryParameterProcessor.kt
@@ -30,16 +30,21 @@
fun process(): QueryParameter {
val asMember = element.asMemberOf(containing)
val parameterAdapter = context.typeAdapterStore.findQueryParameterAdapter(asMember)
- context.checker.check(parameterAdapter != null, element,
- ProcessorErrors.CANNOT_BIND_QUERY_PARAMETER_INTO_STMT)
+ context.checker.check(
+ parameterAdapter != null, element,
+ ProcessorErrors.CANNOT_BIND_QUERY_PARAMETER_INTO_STMT
+ )
val name = element.name
- context.checker.check(!name.startsWith("_"), element,
- ProcessorErrors.QUERY_PARAMETERS_CANNOT_START_WITH_UNDERSCORE)
+ context.checker.check(
+ !name.startsWith("_"), element,
+ ProcessorErrors.QUERY_PARAMETERS_CANNOT_START_WITH_UNDERSCORE
+ )
return QueryParameter(
- name = name,
- sqlName = sqlName ?: name,
- type = asMember,
- queryParamAdapter = parameterAdapter)
+ name = name,
+ sqlName = sqlName ?: name,
+ type = asMember,
+ queryParamAdapter = parameterAdapter
+ )
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt
index e1ed550..64161db 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/RawQueryMethodProcessor.kt
@@ -38,12 +38,16 @@
val delegate = MethodProcessorDelegate.createFor(context, containing, executableElement)
val returnType = delegate.extractReturnType()
- context.checker.check(executableElement.hasAnnotation(RawQuery::class), executableElement,
- ProcessorErrors.MISSING_RAWQUERY_ANNOTATION)
+ context.checker.check(
+ executableElement.hasAnnotation(RawQuery::class), executableElement,
+ ProcessorErrors.MISSING_RAWQUERY_ANNOTATION
+ )
val returnTypeName = returnType.typeName
- context.checker.notUnbound(returnTypeName, executableElement,
- ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_QUERY_METHODS)
+ context.checker.notUnbound(
+ returnTypeName, executableElement,
+ ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_QUERY_METHODS
+ )
val observedTableNames = processObservedTables()
val query = SqlParser.rawQueryForTables(observedTableNames)
// build the query but don't calculate result info since we just guessed it.
@@ -51,49 +55,53 @@
val runtimeQueryParam = findRuntimeQueryParameter(delegate.extractParams())
val inTransaction = executableElement.hasAnnotation(Transaction::class)
val rawQueryMethod = RawQueryMethod(
- element = executableElement,
- name = executableElement.name,
- observedTableNames = observedTableNames,
- returnType = returnType,
- runtimeQueryParam = runtimeQueryParam,
- inTransaction = inTransaction,
- queryResultBinder = resultBinder
+ element = executableElement,
+ name = executableElement.name,
+ observedTableNames = observedTableNames,
+ returnType = returnType,
+ runtimeQueryParam = runtimeQueryParam,
+ inTransaction = inTransaction,
+ queryResultBinder = resultBinder
)
// TODO: Lift this restriction, to allow for INSERT, UPDATE and DELETE raw statements.
- context.checker.check(rawQueryMethod.returnsValue, executableElement,
- ProcessorErrors.RAW_QUERY_BAD_RETURN_TYPE)
+ context.checker.check(
+ rawQueryMethod.returnsValue, executableElement,
+ ProcessorErrors.RAW_QUERY_BAD_RETURN_TYPE
+ )
return rawQueryMethod
}
private fun processObservedTables(): Set<String> {
val annotation = executableElement.toAnnotationBox(RawQuery::class)
return annotation?.getAsTypeList("observedEntities")
- ?.map {
- it.asTypeElement()
- }
- ?.flatMap {
- if (it.isEntityElement()) {
- val entity = EntityProcessor(
- context = context,
- element = it
- ).process()
- arrayListOf(entity.tableName)
- } else {
- val pojo = PojoProcessor.createFor(
- context = context,
- element = it,
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null
- ).process()
- val tableNames = pojo.accessedTableNames()
- // if it is empty, report error as it does not make sense
- if (tableNames.isEmpty()) {
- context.logger.e(executableElement,
- ProcessorErrors.rawQueryBadEntity(it.type.typeName))
- }
- tableNames
+ ?.map {
+ it.asTypeElement()
+ }
+ ?.flatMap {
+ if (it.isEntityElement()) {
+ val entity = EntityProcessor(
+ context = context,
+ element = it
+ ).process()
+ arrayListOf(entity.tableName)
+ } else {
+ val pojo = PojoProcessor.createFor(
+ context = context,
+ element = it,
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
+ ).process()
+ val tableNames = pojo.accessedTableNames()
+ // if it is empty, report error as it does not make sense
+ if (tableNames.isEmpty()) {
+ context.logger.e(
+ executableElement,
+ ProcessorErrors.rawQueryBadEntity(it.type.typeName)
+ )
}
- }?.toSet() ?: emptySet()
+ tableNames
+ }
+ }?.toSet() ?: emptySet()
}
private fun findRuntimeQueryParameter(
@@ -106,8 +114,9 @@
val isSupportSql = supportQueryType.isAssignableFrom(param)
if (isSupportSql) {
return RawQueryMethod.RuntimeQueryParameter(
- paramName = extractParams[0].name,
- type = supportQueryType.typeName)
+ paramName = extractParams[0].name,
+ type = supportQueryType.typeName
+ )
}
val stringType = processingEnv.requireType("java.lang.String")
val isString = stringType.isAssignableFrom(param)
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutMethodProcessor.kt
index 50e0fcd..f174a1e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutMethodProcessor.kt
@@ -56,19 +56,24 @@
ShortcutParameterProcessor(
baseContext = context,
containing = containing,
- element = it).process()
+ element = it
+ ).process()
}
context.checker.check(params.isNotEmpty(), executableElement, missingParamError)
val targetEntity = if (targetEntityType != null &&
- !targetEntityType.isTypeOf(Any::class)) {
+ !targetEntityType.isTypeOf(Any::class)
+ ) {
processEntity(
element = targetEntityType.asTypeElement(),
onInvalid = {
- context.logger.e(executableElement,
- ProcessorErrors.INVALID_TARGET_ENTITY_IN_SHORTCUT_METHOD)
+ context.logger.e(
+ executableElement,
+ ProcessorErrors.INVALID_TARGET_ENTITY_IN_SHORTCUT_METHOD
+ )
return emptyMap<String, ShortcutEntity>() to emptyList()
- })
+ }
+ )
} else {
null
}
@@ -88,41 +93,56 @@
targetEntity: Entity,
params: List<ShortcutQueryParameter>,
onValidatePartialEntity: (Entity, Pojo) -> Unit
- ) = params.associateBy({ it.name }, { param ->
- if (targetEntity.type.isSameType(param.pojoType!!)) {
- ShortcutEntity(entity = targetEntity, partialEntity = null)
- } else {
- // Target entity and pojo param are not the same, process and validate partial entity.
- val pojo = PojoProcessor.createFor(
- context = context,
- element = param.pojoType.asTypeElement(),
- bindingScope = FieldProcessor.BindingScope.BIND_TO_STMT,
- parent = null
- ).process().also { pojo ->
- pojo.fields.filter { targetEntity.findFieldByColumnName(it.columnName) == null }
- .forEach { context.logger.e(it.element,
- ProcessorErrors.cannotFindAsEntityField(targetEntity.typeName.toString())) }
+ ) = params.associateBy(
+ { it.name },
+ { param ->
+ if (targetEntity.type.isSameType(param.pojoType!!)) {
+ ShortcutEntity(entity = targetEntity, partialEntity = null)
+ } else {
+ // Target entity and pojo param are not the same, process and validate partial entity.
+ val pojo = PojoProcessor.createFor(
+ context = context,
+ element = param.pojoType.asTypeElement(),
+ bindingScope = FieldProcessor.BindingScope.BIND_TO_STMT,
+ parent = null
+ ).process().also { pojo ->
+ pojo.fields.filter { targetEntity.findFieldByColumnName(it.columnName) == null }
+ .forEach {
+ context.logger.e(
+ it.element,
+ ProcessorErrors.cannotFindAsEntityField(
+ targetEntity.typeName.toString()
+ )
- if (pojo.relations.isNotEmpty()) {
- // TODO: Support Pojos with relations.
- context.logger.e(pojo.element,
- ProcessorErrors.INVALID_RELATION_IN_PARTIAL_ENTITY)
+ )
+ }
+
+ if (pojo.relations.isNotEmpty()) {
+ // TODO: Support Pojos with relations.
+ context.logger.e(
+ pojo.element,
+ ProcessorErrors.INVALID_RELATION_IN_PARTIAL_ENTITY
+ )
+ }
+ onValidatePartialEntity(targetEntity, pojo)
}
- onValidatePartialEntity(targetEntity, pojo)
+ ShortcutEntity(entity = targetEntity, partialEntity = pojo)
}
- ShortcutEntity(entity = targetEntity, partialEntity = pojo)
}
- })
+ )
private fun extractEntities(params: List<ShortcutQueryParameter>) =
params.mapNotNull {
val entity = processEntity(
element = it.pojoType!!.asTypeElement(),
onInvalid = {
- context.logger.e(it.element,
- ProcessorErrors.CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER)
+ context.logger.e(
+ it.element,
+ ProcessorErrors.CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER
+ )
return@mapNotNull null
- })
+ }
+ )
it.name to ShortcutEntity(entity = entity!!, partialEntity = null)
}.toMap()
@@ -130,7 +150,8 @@
if (element.isEntityElement()) {
EntityProcessor(
context = context,
- element = element).process()
+ element = element
+ ).process()
} else {
onInvalid()
null
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt
index b9002d1..3491a72 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/ShortcutParameterProcessor.kt
@@ -35,16 +35,18 @@
fun process(): ShortcutQueryParameter {
val asMember = element.asMemberOf(containing)
val name = element.name
- context.checker.check(!name.startsWith("_"), element,
- ProcessorErrors.QUERY_PARAMETERS_CANNOT_START_WITH_UNDERSCORE)
+ context.checker.check(
+ !name.startsWith("_"), element,
+ ProcessorErrors.QUERY_PARAMETERS_CANNOT_START_WITH_UNDERSCORE
+ )
val (pojoType, isMultiple) = extractPojoType(asMember)
return ShortcutQueryParameter(
- element = element,
- name = name,
- type = asMember,
- pojoType = pojoType,
- isMultiple = isMultiple
+ element = element,
+ name = name,
+ type = asMember,
+ pojoType = pojoType,
+ isMultiple = isMultiple
)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt
index eb2597f..2091b46 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/TableEntityProcessor.kt
@@ -54,8 +54,10 @@
}
private fun doProcess(): Entity {
- context.checker.hasAnnotation(element, androidx.room.Entity::class,
- ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY)
+ context.checker.hasAnnotation(
+ element, androidx.room.Entity::class,
+ ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY
+ )
val annotationBox = element.toAnnotationBox(androidx.room.Entity::class)
val tableName: String
val entityIndices: List<IndexInput>
@@ -72,10 +74,14 @@
entityIndices = emptyList()
inheritSuperIndices = false
}
- context.checker.notBlank(tableName, element,
- ProcessorErrors.ENTITY_TABLE_NAME_CANNOT_BE_EMPTY)
- context.checker.check(!tableName.startsWith("sqlite_", true), element,
- ProcessorErrors.ENTITY_TABLE_NAME_CANNOT_START_WITH_SQLITE)
+ context.checker.notBlank(
+ tableName, element,
+ ProcessorErrors.ENTITY_TABLE_NAME_CANNOT_BE_EMPTY
+ )
+ context.checker.check(
+ !tableName.startsWith("sqlite_", true), element,
+ ProcessorErrors.ENTITY_TABLE_NAME_CANNOT_START_WITH_SQLITE
+ )
val pojo = PojoProcessor.createFor(
context = context,
@@ -87,30 +93,34 @@
context.checker.check(pojo.relations.isEmpty(), element, RELATION_IN_ENTITY)
val fieldIndices = pojo.fields
- .filter { it.indexed }.mapNotNull {
- if (it.parent != null) {
- it.indexed = false
- context.logger.w(Warning.INDEX_FROM_EMBEDDED_FIELD_IS_DROPPED, it.element,
- ProcessorErrors.droppedEmbeddedFieldIndex(
- it.getPath(), element.qualifiedName
- ))
- null
- } else if (it.element.enclosingTypeElement != element && !inheritSuperIndices) {
- it.indexed = false
- context.logger.w(Warning.INDEX_FROM_PARENT_FIELD_IS_DROPPED,
- ProcessorErrors.droppedSuperClassFieldIndex(
- it.columnName, element.toString(),
- it.element.enclosingTypeElement.toString()
- ))
- null
- } else {
- IndexInput(
- name = createIndexName(listOf(it.columnName), tableName),
- unique = false,
- columnNames = listOf(it.columnName)
+ .filter { it.indexed }.mapNotNull {
+ if (it.parent != null) {
+ it.indexed = false
+ context.logger.w(
+ Warning.INDEX_FROM_EMBEDDED_FIELD_IS_DROPPED, it.element,
+ ProcessorErrors.droppedEmbeddedFieldIndex(
+ it.getPath(), element.qualifiedName
)
- }
+ )
+ null
+ } else if (it.element.enclosingTypeElement != element && !inheritSuperIndices) {
+ it.indexed = false
+ context.logger.w(
+ Warning.INDEX_FROM_PARENT_FIELD_IS_DROPPED,
+ ProcessorErrors.droppedSuperClassFieldIndex(
+ it.columnName, element.toString(),
+ it.element.enclosingTypeElement.toString()
+ )
+ )
+ null
+ } else {
+ IndexInput(
+ name = createIndexName(listOf(it.columnName), tableName),
+ unique = false,
+ columnNames = listOf(it.columnName)
+ )
}
+ }
val superIndices = loadSuperIndices(element.superType, tableName, inheritSuperIndices)
val indexInputs = entityIndices + fieldIndices + superIndices
val indices = validateAndCreateIndices(indexInputs, pojo)
@@ -118,31 +128,37 @@
val primaryKey = findAndValidatePrimaryKey(pojo.fields, pojo.embeddedFields)
val affinity = primaryKey.fields.firstOrNull()?.affinity ?: SQLTypeAffinity.TEXT
context.checker.check(
- !primaryKey.autoGenerateId || affinity == SQLTypeAffinity.INTEGER,
- primaryKey.fields.firstOrNull()?.element ?: element,
- ProcessorErrors.AUTO_INCREMENTED_PRIMARY_KEY_IS_NOT_INT
+ !primaryKey.autoGenerateId || affinity == SQLTypeAffinity.INTEGER,
+ primaryKey.fields.firstOrNull()?.element ?: element,
+ ProcessorErrors.AUTO_INCREMENTED_PRIMARY_KEY_IS_NOT_INT
)
val entityForeignKeys = validateAndCreateForeignKeyReferences(foreignKeyInputs, pojo)
checkIndicesForForeignKeys(entityForeignKeys, primaryKey, indices)
- context.checker.check(SqlParser.isValidIdentifier(tableName), element,
- ProcessorErrors.INVALID_TABLE_NAME)
+ context.checker.check(
+ SqlParser.isValidIdentifier(tableName), element,
+ ProcessorErrors.INVALID_TABLE_NAME
+ )
pojo.fields.forEach {
- context.checker.check(SqlParser.isValidIdentifier(it.columnName), it.element,
- ProcessorErrors.INVALID_COLUMN_NAME)
+ context.checker.check(
+ SqlParser.isValidIdentifier(it.columnName), it.element,
+ ProcessorErrors.INVALID_COLUMN_NAME
+ )
}
- val entity = Entity(element = element,
- tableName = tableName,
- type = pojo.type,
- fields = pojo.fields,
- embeddedFields = pojo.embeddedFields,
- indices = indices,
- primaryKey = primaryKey,
- foreignKeys = entityForeignKeys,
- constructor = pojo.constructor,
- shadowTableName = null)
+ val entity = Entity(
+ element = element,
+ tableName = tableName,
+ type = pojo.type,
+ fields = pojo.fields,
+ embeddedFields = pojo.embeddedFields,
+ indices = indices,
+ primaryKey = primaryKey,
+ foreignKeys = entityForeignKeys,
+ constructor = pojo.constructor,
+ shadowTableName = null
+ )
return entity
}
@@ -153,9 +169,9 @@
indices: List<Index>
) {
fun covers(columnNames: List<String>, fields: List<Field>): Boolean =
- fields.size >= columnNames.size && columnNames.withIndex().all {
- fields[it.index].columnName == it.value
- }
+ fields.size >= columnNames.size && columnNames.withIndex().all {
+ fields[it.index].columnName == it.value
+ }
entityForeignKeys.forEach { fKey ->
val columnNames = fKey.childFields.map { it.columnName }
@@ -164,11 +180,15 @@
}
if (!exists) {
if (columnNames.size == 1) {
- context.logger.w(Warning.MISSING_INDEX_ON_FOREIGN_KEY_CHILD, element,
- ProcessorErrors.foreignKeyMissingIndexInChildColumn(columnNames[0]))
+ context.logger.w(
+ Warning.MISSING_INDEX_ON_FOREIGN_KEY_CHILD, element,
+ ProcessorErrors.foreignKeyMissingIndexInChildColumn(columnNames[0])
+ )
} else {
- context.logger.w(Warning.MISSING_INDEX_ON_FOREIGN_KEY_CHILD, element,
- ProcessorErrors.foreignKeyMissingIndexInChildColumns(columnNames))
+ context.logger.w(
+ Warning.MISSING_INDEX_ON_FOREIGN_KEY_CHILD, element,
+ ProcessorErrors.foreignKeyMissingIndexInChildColumns(columnNames)
+ )
}
}
}
@@ -199,9 +219,12 @@
return@map null
}
if (it.childColumns.size != it.parentColumns.size) {
- context.logger.e(element, ProcessorErrors.foreignKeyColumnNumberMismatch(
+ context.logger.e(
+ element,
+ ProcessorErrors.foreignKeyColumnNumberMismatch(
it.childColumns, it.parentColumns
- ))
+ )
+ )
return@map null
}
val parentElement = try {
@@ -212,17 +235,23 @@
}
val parentAnnotation = parentElement.toAnnotationBox(androidx.room.Entity::class)
if (parentAnnotation == null) {
- context.logger.e(element,
- ProcessorErrors.foreignKeyNotAnEntity(parentElement.toString()))
+ context.logger.e(
+ element,
+ ProcessorErrors.foreignKeyNotAnEntity(parentElement.toString())
+ )
return@map null
}
val tableName = extractTableName(parentElement, parentAnnotation.value)
val fields = it.childColumns.mapNotNull { columnName ->
val field = pojo.findFieldByColumnName(columnName)
if (field == null) {
- context.logger.e(pojo.element,
- ProcessorErrors.foreignKeyChildColumnDoesNotExist(columnName,
- pojo.columnNames))
+ context.logger.e(
+ pojo.element,
+ ProcessorErrors.foreignKeyChildColumnDoesNotExist(
+ columnName,
+ pojo.columnNames
+ )
+ )
}
field
}
@@ -230,12 +259,12 @@
return@map null
}
ForeignKey(
- parentTable = tableName,
- childFields = fields,
- parentColumns = it.parentColumns,
- onDelete = it.onDelete,
- onUpdate = it.onUpdate,
- deferred = it.deferred
+ parentTable = tableName,
+ childFields = fields,
+ parentColumns = it.parentColumns,
+ onDelete = it.onDelete,
+ onUpdate = it.onUpdate,
+ deferred = it.deferred
)
}.filterNotNull()
}
@@ -245,8 +274,8 @@
embeddedFields: List<EmbeddedField>
): PrimaryKey {
val candidates = collectPrimaryKeysFromEntityAnnotations(element, fields) +
- collectPrimaryKeysFromPrimaryKeyAnnotations(fields) +
- collectPrimaryKeysFromEmbeddedFields(embeddedFields)
+ collectPrimaryKeysFromPrimaryKeyAnnotations(fields) +
+ collectPrimaryKeysFromEmbeddedFields(embeddedFields)
context.checker.check(candidates.isNotEmpty(), element, ProcessorErrors.MISSING_PRIMARY_KEY)
@@ -259,7 +288,8 @@
candidates.filterNot { it.autoGenerateId }.forEach { candidate ->
candidate.fields.forEach { field ->
if (candidate.fields.size > 1 ||
- (candidate.fields.size == 1 && field.affinity != SQLTypeAffinity.INTEGER)) {
+ (candidate.fields.size == 1 && field.affinity != SQLTypeAffinity.INTEGER)
+ ) {
if (!verifiedFields.contains(field)) {
context.checker.check(
field.nonNull,
@@ -305,15 +335,19 @@
val grandParentField = field.parent.mRootParent.field.element
// bound for entity.
context.fork(grandParentField).logger.w(
- Warning.PRIMARY_KEY_FROM_EMBEDDED_IS_DROPPED,
- grandParentField,
- ProcessorErrors.embeddedPrimaryKeyIsDropped(
- element.qualifiedName, field.name))
+ Warning.PRIMARY_KEY_FROM_EMBEDDED_IS_DROPPED,
+ grandParentField,
+ ProcessorErrors.embeddedPrimaryKeyIsDropped(
+ element.qualifiedName, field.name
+ )
+ )
null
} else {
- PrimaryKey(declaredIn = field.element.enclosingTypeElement,
- fields = Fields(field),
- autoGenerateId = it.value.autoGenerate)
+ PrimaryKey(
+ declaredIn = field.element.enclosingTypeElement,
+ fields = Fields(field),
+ autoGenerateId = it.value.autoGenerate
+ )
}
}
}
@@ -333,14 +367,22 @@
} else {
val fields = primaryKeyColumns.mapNotNull { pKeyColumnName ->
val field = availableFields.firstOrNull { it.columnName == pKeyColumnName }
- context.checker.check(field != null, typeElement,
- ProcessorErrors.primaryKeyColumnDoesNotExist(pKeyColumnName,
- availableFields.map { it.columnName }))
+ context.checker.check(
+ field != null, typeElement,
+ ProcessorErrors.primaryKeyColumnDoesNotExist(
+ pKeyColumnName,
+ availableFields.map { it.columnName }
+ )
+ )
field
}
- listOf(PrimaryKey(declaredIn = typeElement,
+ listOf(
+ PrimaryKey(
+ declaredIn = typeElement,
fields = Fields(fields),
- autoGenerateId = false))
+ autoGenerateId = false
+ )
+ )
}
} ?: emptyList()
// checks supers.
@@ -362,12 +404,16 @@
): List<PrimaryKey> {
return embeddedFields.mapNotNull { embeddedField ->
embeddedField.field.element.toAnnotationBox(androidx.room.PrimaryKey::class)?.let {
- context.checker.check(!it.value.autoGenerate || embeddedField.pojo.fields.size == 1,
- embeddedField.field.element,
- ProcessorErrors.AUTO_INCREMENT_EMBEDDED_HAS_MULTIPLE_FIELDS)
- PrimaryKey(declaredIn = embeddedField.field.element.enclosingTypeElement,
- fields = embeddedField.pojo.fields,
- autoGenerateId = it.value.autoGenerate)
+ context.checker.check(
+ !it.value.autoGenerate || embeddedField.pojo.fields.size == 1,
+ embeddedField.field.element,
+ ProcessorErrors.AUTO_INCREMENT_EMBEDDED_HAS_MULTIPLE_FIELDS
+ )
+ PrimaryKey(
+ declaredIn = embeddedField.field.element.enclosingTypeElement,
+ fields = embeddedField.pojo.fields,
+ autoGenerateId = it.value.autoGenerate
+ )
}
}
}
@@ -388,9 +434,11 @@
return if (myPKeys.size == 1) {
// just note, this is not worth an error or warning
(candidates - myPKeys).forEach {
- context.logger.d(element,
- "${it.toHumanReadableString()} is" +
- " overridden by ${myPKeys.first().toHumanReadableString()}")
+ context.logger.d(
+ element,
+ "${it.toHumanReadableString()} is" +
+ " overridden by ${myPKeys.first().toHumanReadableString()}"
+ )
}
myPKeys.first()
} else if (myPKeys.isEmpty()) {
@@ -401,8 +449,12 @@
}
PrimaryKey.MISSING
} else {
- context.logger.e(element, ProcessorErrors.multiplePrimaryKeyAnnotations(
- myPKeys.map(PrimaryKey::toHumanReadableString)))
+ context.logger.e(
+ element,
+ ProcessorErrors.multiplePrimaryKeyAnnotations(
+ myPKeys.map(PrimaryKey::toHumanReadableString)
+ )
+ )
PrimaryKey.MISSING
}
}
@@ -413,12 +465,16 @@
): List<Index> {
// check for columns
val indices = inputs.mapNotNull { input ->
- context.checker.check(input.columnNames.isNotEmpty(), element,
- INDEX_COLUMNS_CANNOT_BE_EMPTY)
+ context.checker.check(
+ input.columnNames.isNotEmpty(), element,
+ INDEX_COLUMNS_CANNOT_BE_EMPTY
+ )
val fields = input.columnNames.mapNotNull { columnName ->
val field = pojo.findFieldByColumnName(columnName)
- context.checker.check(field != null, element,
- ProcessorErrors.indexColumnDoesNotExist(columnName, pojo.columnNames))
+ context.checker.check(
+ field != null, element,
+ ProcessorErrors.indexColumnDoesNotExist(columnName, pojo.columnNames)
+ )
field
}
if (fields.isEmpty()) {
@@ -430,11 +486,11 @@
// check for duplicate indices
indices
- .groupBy { it.name }
- .filter { it.value.size > 1 }
- .forEach {
- context.logger.e(element, ProcessorErrors.duplicateIndexInEntity(it.key))
- }
+ .groupBy { it.name }
+ .filter { it.value.size > 1 }
+ .forEach {
+ context.logger.e(element, ProcessorErrors.duplicateIndexInEntity(it.key))
+ }
// see if any embedded field is an entity with indices, if so, report a warning
pojo.embeddedFields.forEach { embedded ->
@@ -442,12 +498,15 @@
embeddedElement.toAnnotationBox(androidx.room.Entity::class)?.let {
val subIndices = extractIndices(it, "")
if (subIndices.isNotEmpty()) {
- context.logger.w(Warning.INDEX_FROM_EMBEDDED_ENTITY_IS_DROPPED,
- embedded.field.element, ProcessorErrors.droppedEmbeddedIndex(
+ context.logger.w(
+ Warning.INDEX_FROM_EMBEDDED_ENTITY_IS_DROPPED,
+ embedded.field.element,
+ ProcessorErrors.droppedEmbeddedIndex(
entityName = embedded.pojo.typeName.toString(),
fieldPath = embedded.field.getPath(),
grandParent = element.qualifiedName
- ))
+ )
+ )
}
}
}
@@ -465,28 +524,31 @@
}
val parentElement = typeMirror.asTypeElement()
val myIndices = parentElement
- .toAnnotationBox(androidx.room.Entity::class)?.let { annotation ->
- val indices = extractIndices(annotation, tableName = "super")
- if (indices.isEmpty()) {
- emptyList()
- } else if (inherit) {
- // rename them
- indices.map {
- IndexInput(
+ .toAnnotationBox(androidx.room.Entity::class)?.let { annotation ->
+ val indices = extractIndices(annotation, tableName = "super")
+ if (indices.isEmpty()) {
+ emptyList()
+ } else if (inherit) {
+ // rename them
+ indices.map {
+ IndexInput(
name = createIndexName(it.columnNames, tableName),
unique = it.unique,
- columnNames = it.columnNames)
- }
- } else {
- context.logger.w(Warning.INDEX_FROM_PARENT_IS_DROPPED,
+ columnNames = it.columnNames
+ )
+ }
+ } else {
+ context.logger.w(
+ Warning.INDEX_FROM_PARENT_IS_DROPPED,
parentElement,
ProcessorErrors.droppedSuperClassIndex(
- childEntity = element.qualifiedName,
- superEntity = parentElement.qualifiedName
- ))
- emptyList()
- }
- } ?: emptyList()
+ childEntity = element.qualifiedName,
+ superEntity = parentElement.qualifiedName
+ )
+ )
+ emptyList()
+ }
+ } ?: emptyList()
return myIndices + loadSuperIndices(parentElement.superType, tableName, inherit)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/TransactionMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/TransactionMethodProcessor.kt
index 2d5ddc6..8551c97 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/TransactionMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/TransactionMethodProcessor.kt
@@ -36,9 +36,10 @@
val delegate = MethodProcessorDelegate.createFor(context, containing, executableElement)
val hasKotlinDefaultImpl = executableElement.hasKotlinDefaultImpl()
context.checker.check(
- executableElement.isOverrideableIgnoringContainer() &&
- (!executableElement.isAbstract() || hasKotlinDefaultImpl),
- executableElement, ProcessorErrors.TRANSACTION_METHOD_MODIFIERS)
+ executableElement.isOverrideableIgnoringContainer() &&
+ (!executableElement.isAbstract() || hasKotlinDefaultImpl),
+ executableElement, ProcessorErrors.TRANSACTION_METHOD_MODIFIERS
+ )
val returnType = delegate.extractReturnType()
val rawReturnType = returnType.rawType
@@ -64,11 +65,12 @@
}
return TransactionMethod(
- element = executableElement,
- returnType = returnType,
- parameterNames = delegate.extractParams().map { it.name },
- callType = callType,
- methodBinder = delegate.findTransactionMethodBinder(callType))
+ element = executableElement,
+ returnType = returnType,
+ parameterNames = delegate.extractParams().map { it.name },
+ callType = callType,
+ methodBinder = delegate.findTransactionMethodBinder(callType)
+ )
}
companion object {
@@ -84,6 +86,7 @@
RxJava3TypeNames.MAYBE,
RxJava3TypeNames.SINGLE,
RxJava3TypeNames.COMPLETABLE,
- GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE)
+ GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
+ )
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/UpdateMethodProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/UpdateMethodProcessor.kt
index 7f08df9..3075e8d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/UpdateMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/UpdateMethodProcessor.kt
@@ -34,11 +34,13 @@
fun process(): UpdateMethod {
val delegate = ShortcutMethodProcessor(context, containing, executableElement)
val annotation = delegate
- .extractAnnotation(Update::class, ProcessorErrors.MISSING_UPDATE_ANNOTATION)
+ .extractAnnotation(Update::class, ProcessorErrors.MISSING_UPDATE_ANNOTATION)
val onConflict = annotation?.value?.onConflict ?: OnConflictProcessor.INVALID_ON_CONFLICT
- context.checker.check(onConflict in REPLACE..IGNORE,
- executableElement, ProcessorErrors.INVALID_ON_CONFLICT_VALUE)
+ context.checker.check(
+ onConflict in REPLACE..IGNORE,
+ executableElement, ProcessorErrors.INVALID_ON_CONFLICT_VALUE
+ )
val (entities, params) = delegate.extractParams(
targetEntityType = annotation?.getAsType("entity"),
@@ -47,10 +49,12 @@
val missingPrimaryKeys = entity.primaryKey.fields.filter {
pojo.findFieldByColumnName(it.columnName) == null
}
- context.checker.check(missingPrimaryKeys.isEmpty(), executableElement,
+ context.checker.check(
+ missingPrimaryKeys.isEmpty(), executableElement,
ProcessorErrors.missingPrimaryKeysInPartialEntityForUpdate(
partialEntityName = pojo.typeName.toString(),
- primaryKeyNames = missingPrimaryKeys.map { it.columnName })
+ primaryKeyNames = missingPrimaryKeys.map { it.columnName }
+ )
)
}
)
@@ -59,18 +63,18 @@
val methodBinder = delegate.findDeleteOrUpdateMethodBinder(returnType)
context.checker.check(
- methodBinder.adapter != null,
- executableElement,
- ProcessorErrors.CANNOT_FIND_UPDATE_RESULT_ADAPTER
+ methodBinder.adapter != null,
+ executableElement,
+ ProcessorErrors.CANNOT_FIND_UPDATE_RESULT_ADAPTER
)
return UpdateMethod(
- element = delegate.executableElement,
- name = delegate.executableElement.name,
- entities = entities,
- onConflictStrategy = onConflict,
- methodBinder = methodBinder,
- parameters = params
+ element = delegate.executableElement,
+ name = delegate.executableElement.name,
+ entities = entities,
+ onConflictStrategy = onConflict,
+ methodBinder = methodBinder,
+ parameters = params
)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegate.kt b/room/compiler/src/main/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegate.kt
index 42aac34f..6fc4899 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegate.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegate.kt
@@ -53,8 +53,10 @@
autoValueAbstractGetters.forEach {
val hasRoomAnnotation = it.hasAnnotationWithPackage("androidx.room")
if (hasRoomAnnotation && !it.hasAnnotation(CopyAnnotations::class)) {
- context.logger.w(Warning.MISSING_COPY_ANNOTATIONS, it,
- ProcessorErrors.MISSING_COPY_ANNOTATIONS)
+ context.logger.w(
+ Warning.MISSING_COPY_ANNOTATIONS, it,
+ ProcessorErrors.MISSING_COPY_ANNOTATIONS
+ )
}
}
@@ -65,17 +67,19 @@
.forEach { method ->
val annotationName = TARGET_METHOD_ANNOTATIONS.first { method.hasAnnotation(it) }
.java.simpleName
- context.logger.e(method,
- ProcessorErrors.invalidAnnotationTarget(annotationName, method.kindName()))
+ context.logger.e(
+ method,
+ ProcessorErrors.invalidAnnotationTarget(annotationName, method.kindName())
+ )
}
}
override fun findConstructors(element: XTypeElement): List<XExecutableElement> {
return autoValueElement.getDeclaredMethods().filter {
it.isStatic() &&
- !it.hasAnnotation(Ignore::class) &&
- !it.isPrivate() &&
- it.returnType.isSameType(autoValueElement.type)
+ !it.hasAnnotation(Ignore::class) &&
+ !it.isPrivate() &&
+ it.returnType.isSameType(autoValueElement.type)
}
}
@@ -87,12 +91,14 @@
relations: List<androidx.room.vo.Relation>,
constructor: Constructor?
): Pojo {
- return Pojo(element = element,
- type = autoValueDeclaredType,
- fields = fields,
- embeddedFields = embeddedFields,
- relations = relations,
- constructor = constructor)
+ return Pojo(
+ element = element,
+ type = autoValueDeclaredType,
+ fields = fields,
+ embeddedFields = embeddedFields,
+ relations = relations,
+ constructor = constructor
+ )
}
companion object {
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/cache/Cache.kt b/room/compiler/src/main/kotlin/androidx/room/processor/cache/Cache.kt
index fee6e5c..268d0ce 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/cache/Cache.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/cache/Cache.kt
@@ -45,9 +45,12 @@
private val entries: MutableMap<FullKey<K>, T> = source?.entries ?: mutableMapOf()
fun get(key: K, calculate: () -> T): T {
val fullKey = FullKey(converters, suppressedWarnings, key)
- return entries.getOrPut(fullKey, {
- calculate()
- })
+ return entries.getOrPut(
+ fullKey,
+ {
+ calculate()
+ }
+ )
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/ObservableQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/ObservableQueryResultBinderProvider.kt
index 44397c2..46f7d7eb 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/ObservableQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/ObservableQueryResultBinderProvider.kt
@@ -39,15 +39,17 @@
final override fun provide(declared: XDeclaredType, query: ParsedQuery): QueryResultBinder {
val typeArg = extractTypeArg(declared)
val adapter = context.typeAdapterStore.findQueryResultAdapter(typeArg, query)
- val tableNames = ((adapter?.accessedTableNames() ?: emptyList()) +
- query.tables.map { it.name }).toSet()
+ val tableNames = (
+ (adapter?.accessedTableNames() ?: emptyList()) +
+ query.tables.map { it.name }
+ ).toSet()
if (tableNames.isEmpty()) {
context.logger.e(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
}
return create(
- typeArg = typeArg,
- resultAdapter = adapter,
- tableNames = tableNames
+ typeArg = typeArg,
+ resultAdapter = adapter,
+ tableNames = tableNames
)
}
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt b/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
index 9bc4c56..2f227c6 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
@@ -33,40 +33,50 @@
RX2_FLOWABLE(
version = RxVersion.TWO,
className = RxJava2TypeNames.FLOWABLE,
- factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_FLOWABLE),
+ factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_FLOWABLE
+ ),
RX2_OBSERVABLE(
version = RxVersion.TWO,
className = RxJava2TypeNames.OBSERVABLE,
- factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_OBSERVABLE),
+ factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_OBSERVABLE
+ ),
RX2_SINGLE(
version = RxVersion.TWO,
- className = RxJava2TypeNames.SINGLE),
+ className = RxJava2TypeNames.SINGLE
+ ),
RX2_MAYBE(
version = RxVersion.TWO,
className = RxJava2TypeNames.MAYBE,
- canBeNull = true),
+ canBeNull = true
+ ),
RX2_COMPLETABLE(
version = RxVersion.TWO,
- className = RxJava2TypeNames.COMPLETABLE),
+ className = RxJava2TypeNames.COMPLETABLE
+ ),
// RxJava3 types
RX3_FLOWABLE(
version = RxVersion.THREE,
className = RxJava3TypeNames.FLOWABLE,
- factoryMethodName = RoomRxJava3TypeNames.RX_ROOM_CREATE_FLOWABLE),
+ factoryMethodName = RoomRxJava3TypeNames.RX_ROOM_CREATE_FLOWABLE
+ ),
RX3_OBSERVABLE(
version = RxVersion.THREE,
className = RxJava3TypeNames.OBSERVABLE,
- factoryMethodName = RoomRxJava3TypeNames.RX_ROOM_CREATE_OBSERVABLE),
+ factoryMethodName = RoomRxJava3TypeNames.RX_ROOM_CREATE_OBSERVABLE
+ ),
RX3_SINGLE(
version = RxVersion.THREE,
- className = RxJava3TypeNames.SINGLE),
+ className = RxJava3TypeNames.SINGLE
+ ),
RX3_MAYBE(
version = RxVersion.THREE,
className = RxJava3TypeNames.MAYBE,
- canBeNull = true),
+ canBeNull = true
+ ),
RX3_COMPLETABLE(
version = RxVersion.THREE,
- className = RxJava3TypeNames.COMPLETABLE);
+ className = RxJava3TypeNames.COMPLETABLE
+ );
fun isSingle() = this == RX2_SINGLE || this == RX3_SINGLE
}
@@ -79,9 +89,11 @@
TWO(
rxRoomClassName = RoomRxJava2TypeNames.RX_ROOM,
emptyResultExceptionClassName = RoomRxJava2TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
- missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT),
+ missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT
+ ),
THREE(
rxRoomClassName = RoomRxJava3TypeNames.RX_ROOM,
emptyResultExceptionClassName = RoomRxJava3TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
- missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA3_ARTIFACT);
+ missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA3_ARTIFACT
+ );
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index b420de9..d79a71c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -116,9 +116,11 @@
companion object {
fun copy(context: Context, store: TypeAdapterStore): TypeAdapterStore {
- return TypeAdapterStore(context = context,
- columnTypeAdapters = store.columnTypeAdapters,
- typeConverters = store.typeConverters)
+ return TypeAdapterStore(
+ context = context,
+ columnTypeAdapters = store.columnTypeAdapters,
+ typeConverters = store.typeConverters
+ )
}
fun create(context: Context, vararg extras: Any): TypeAdapterStore {
@@ -144,19 +146,21 @@
}
val primitives = PrimitiveColumnTypeAdapter
- .createPrimitiveAdapters(context.processingEnv)
+ .createPrimitiveAdapters(context.processingEnv)
primitives.forEach(::addColumnAdapter)
BoxedPrimitiveColumnTypeAdapter
- .createBoxedPrimitiveAdapters(primitives)
- .forEach(::addColumnAdapter)
+ .createBoxedPrimitiveAdapters(primitives)
+ .forEach(::addColumnAdapter)
addColumnAdapter(StringColumnTypeAdapter(context.processingEnv))
addColumnAdapter(ByteArrayColumnTypeAdapter(context.processingEnv))
addColumnAdapter(ByteBufferColumnTypeAdapter(context.processingEnv))
PrimitiveBooleanToIntConverter.create(context.processingEnv).forEach(::addTypeConverter)
BoxedBooleanToBoxedIntConverter.create(context.processingEnv)
- .forEach(::addTypeConverter)
- return TypeAdapterStore(context = context, columnTypeAdapters = adapters,
- typeConverters = converters)
+ .forEach(::addTypeConverter)
+ return TypeAdapterStore(
+ context = context, columnTypeAdapters = adapters,
+ typeConverters = converters
+ )
}
}
@@ -250,8 +254,10 @@
// we could not find a two way version, search for anything
val targetTypes = targetTypeMirrorsFor(affinity)
val converter = findTypeConverter(targetTypes, output) ?: return null
- return CompositeAdapter(output,
- getAllColumnAdapters(converter.from).first(), null, converter)
+ return CompositeAdapter(
+ output,
+ getAllColumnAdapters(converter.from).first(), null, converter
+ )
}
/**
@@ -269,7 +275,7 @@
else -> {
typeConverters.firstOrNull {
it.from.isSameType(converter.to) &&
- it.to.isSameType(converter.from)
+ it.to.isSameType(converter.from)
}
}
}
@@ -291,9 +297,11 @@
val intoStatement = findTypeConverter(out, targetTypes) ?: return null
// ok found a converter, try the reverse now
val fromCursor = reverse(intoStatement) ?: findTypeConverter(intoStatement.to, out)
- ?: return null
- return CompositeAdapter(out, getAllColumnAdapters(intoStatement.to).first(), intoStatement,
- fromCursor)
+ ?: return null
+ return CompositeAdapter(
+ out, getAllColumnAdapters(intoStatement.to).first(), intoStatement,
+ fromCursor
+ )
}
private fun findDirectAdapterFor(
@@ -401,7 +409,7 @@
return null
} else if (typeMirror.isArray() && typeMirror.componentType.isNotByte()) {
val rowAdapter =
- findRowAdapter(typeMirror.componentType, query) ?: return null
+ findRowAdapter(typeMirror.componentType, query) ?: return null
return ArrayQueryResultAdapter(rowAdapter)
} else {
val rowAdapter = findRowAdapter(typeMirror, query) ?: return null
@@ -425,20 +433,22 @@
val resultInfo = query.resultInfo
val (rowAdapter, rowAdapterLogs) = if (resultInfo != null && query.errors.isEmpty() &&
- resultInfo.error == null) {
+ resultInfo.error == null
+ ) {
// if result info is not null, first try a pojo row adapter
context.collectLogs { subContext ->
val pojo = PojoProcessor.createFor(
- context = subContext,
- element = typeMirror.asTypeElement(),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null
+ context = subContext,
+ element = typeMirror.asTypeElement(),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
).process()
PojoRowAdapter(
- context = subContext,
- info = resultInfo,
- pojo = pojo,
- out = typeMirror)
+ context = subContext,
+ info = resultInfo,
+ pojo = pojo,
+ out = typeMirror
+ )
}
} else {
Pair(null, null)
@@ -448,10 +458,12 @@
// we don't know what query returns. Check for entity.
val asElement = typeMirror.asTypeElement()
if (asElement.isEntityElement()) {
- return EntityRowAdapter(EntityProcessor(
+ return EntityRowAdapter(
+ EntityProcessor(
context = context,
element = asElement.asTypeElement()
- ).process())
+ ).process()
+ )
}
}
@@ -461,8 +473,10 @@
}
if ((resultInfo?.columns?.size ?: 1) == 1) {
- val singleColumn = findCursorValueReader(typeMirror,
- resultInfo?.columns?.get(0)?.type)
+ val singleColumn = findCursorValueReader(
+ typeMirror,
+ resultInfo?.columns?.get(0)?.type
+ )
if (singleColumn != null) {
return SingleColumnRowAdapter(singleColumn)
}
@@ -476,16 +490,17 @@
// just go w/ pojo and hope for the best. this happens for @RawQuery where we
// try to guess user's intention and hope that their query fits the result.
val pojo = PojoProcessor.createFor(
- context = context,
- element = typeMirror.asTypeElement(),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null
+ context = context,
+ element = typeMirror.asTypeElement(),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
).process()
return PojoRowAdapter(
- context = context,
- info = null,
- pojo = pojo,
- out = typeMirror)
+ context = context,
+ info = null,
+ pojo = pojo,
+ out = typeMirror
+ )
}
return null
} else {
@@ -496,10 +511,12 @@
fun findQueryParameterAdapter(typeMirror: XType): QueryParameterAdapter? {
if (typeMirror.isType() &&
- context.COMMON_TYPES.COLLECTION.rawType.isAssignableFrom(typeMirror)) {
+ context.COMMON_TYPES.COLLECTION.rawType.isAssignableFrom(typeMirror)
+ ) {
val declared = typeMirror.asDeclaredType()
val binder = findStatementValueBinder(
- declared.typeArguments.first().extendsBoundOrSelf(), null)
+ declared.typeArguments.first().extendsBoundOrSelf(), null
+ )
if (binder != null) {
return CollectionQueryParameterAdapter(binder)
} else {
@@ -586,19 +603,19 @@
* prioritized.
*/
private fun getAllTypeConverters(input: XType, excludes: List<XType>):
- List<TypeConverter> {
- // for input, check assignability because it defines whether we can use the method or not.
- // for excludes, use exact match
- return typeConverters.filter { converter ->
- converter.from.isAssignableFrom(input) &&
+ List<TypeConverter> {
+ // for input, check assignability because it defines whether we can use the method or not.
+ // for excludes, use exact match
+ return typeConverters.filter { converter ->
+ converter.from.isAssignableFrom(input) &&
!excludes.any { it.isSameType(converter.to) }
- }.sortedByDescending {
- // if it is the same, prioritize
- if (it.from.isSameType(input)) {
- 2
- } else {
- 1
+ }.sortedByDescending {
+ // if it is the same, prioritize
+ if (it.from.isSameType(input)) {
+ 2
+ } else {
+ 1
+ }
}
}
- }
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/CoroutineFlowResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/CoroutineFlowResultBinderProvider.kt
index 871d752..13f6140 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/CoroutineFlowResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/CoroutineFlowResultBinderProvider.kt
@@ -50,8 +50,10 @@
override fun provide(declared: XDeclaredType, query: ParsedQuery): QueryResultBinder {
val typeArg = declared.typeArguments.first()
val adapter = context.typeAdapterStore.findQueryResultAdapter(typeArg, query)
- val tableNames = ((adapter?.accessedTableNames() ?: emptyList()) +
- query.tables.map { it.name }).toSet()
+ val tableNames = (
+ (adapter?.accessedTableNames() ?: emptyList()) +
+ query.tables.map { it.name }
+ ).toSet()
if (tableNames.isEmpty()) {
context.logger.e(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider.kt
index 9a9f53b..f47fdb5 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider.kt
@@ -42,14 +42,16 @@
ListQueryResultAdapter(it)
}
- val tableNames = ((adapter?.accessedTableNames() ?: emptyList()) +
- query.tables.map { it.name }).toSet()
+ val tableNames = (
+ (adapter?.accessedTableNames() ?: emptyList()) +
+ query.tables.map { it.name }
+ ).toSet()
val countedBinder = PositionalDataSourceQueryResultBinder(adapter, tableNames)
return DataSourceFactoryQueryResultBinder(countedBinder)
}
override fun matches(declared: XDeclaredType): Boolean =
- declared.typeArguments.size == 2 && isLivePagedList(declared)
+ declared.typeArguments.size == 2 && isLivePagedList(declared)
private fun isLivePagedList(declared: XDeclaredType): Boolean {
if (dataSourceFactoryType == null) {
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceQueryResultBinderProvider.kt
index 79cbc8d..7e0cc2d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/DataSourceQueryResultBinderProvider.kt
@@ -44,8 +44,10 @@
val listAdapter = context.typeAdapterStore.findRowAdapter(typeArg, query)?.let {
ListQueryResultAdapter(it)
}
- val tableNames = ((listAdapter?.accessedTableNames() ?: emptyList()) +
- query.tables.map { it.name }).toSet()
+ val tableNames = (
+ (listAdapter?.accessedTableNames() ?: emptyList()) +
+ query.tables.map { it.name }
+ ).toSet()
return PositionalDataSourceQueryResultBinder(listAdapter, tableNames)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider.kt
index 89a9492..b9c1b7c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider.kt
@@ -49,9 +49,11 @@
// Use the type T inside ListenableFuture<T> as the type to adapt and to pass into
// the binder.
val adapter = context.typeAdapterStore.findQueryResultAdapter(
- declared.typeArguments.first(), query)
+ declared.typeArguments.first(), query
+ )
return GuavaListenableFutureQueryResultBinder(
- declared.typeArguments.first(), adapter)
+ declared.typeArguments.first(), adapter
+ )
}
/**
@@ -59,5 +61,5 @@
*/
override fun matches(declared: XDeclaredType): Boolean =
declared.typeArguments.size == 1 &&
- declared.rawType.typeName == GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
+ declared.rawType.typeName == GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/InstantQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/InstantQueryResultBinderProvider.kt
index 6fd94a5..7803d8c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/InstantQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/InstantQueryResultBinderProvider.kt
@@ -26,7 +26,8 @@
class InstantQueryResultBinderProvider(val context: Context) : QueryResultBinderProvider {
override fun provide(declared: XDeclaredType, query: ParsedQuery): QueryResultBinder {
return InstantQueryResultBinder(
- context.typeAdapterStore.findQueryResultAdapter(declared, query))
+ context.typeAdapterStore.findQueryResultAdapter(declared, query)
+ )
}
override fun matches(declared: XDeclaredType): Boolean = true
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
index b206b60..ee8a83e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/LiveDataQueryResultBinderProvider.kt
@@ -40,13 +40,14 @@
tableNames: Set<String>
): QueryResultBinder {
return LiveDataQueryResultBinder(
- typeArg = typeArg,
- tableNames = tableNames,
- adapter = resultAdapter)
+ typeArg = typeArg,
+ tableNames = tableNames,
+ adapter = resultAdapter
+ )
}
override fun matches(declared: XDeclaredType): Boolean =
- declared.typeArguments.size == 1 && isLiveData(declared)
+ declared.typeArguments.size == 1 && isLiveData(declared)
private fun isLiveData(declared: XDeclaredType): Boolean {
if (liveDataType == null) {
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/PagingSourceQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/PagingSourceQueryResultBinderProvider.kt
index 23dcd54..44a1148 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/PagingSourceQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/PagingSourceQueryResultBinderProvider.kt
@@ -42,8 +42,10 @@
val listAdapter = context.typeAdapterStore.findRowAdapter(typeArg, query)?.let {
ListQueryResultAdapter(it)
}
- val tableNames = ((listAdapter?.accessedTableNames() ?: emptyList()) +
- query.tables.map { it.name }).toSet()
+ val tableNames = (
+ (listAdapter?.accessedTableNames() ?: emptyList()) +
+ query.tables.map { it.name }
+ ).toSet()
return PagingSourceQueryResultBinder(
PositionalDataSourceQueryResultBinder(listAdapter, tableNames)
)
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CallablePreparedQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CallablePreparedQueryResultBinder.kt
index a33abec..3e44550 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CallablePreparedQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CallablePreparedQueryResultBinder.kt
@@ -57,7 +57,8 @@
binderScope.prepareQueryStmtBlock(),
preparedStmtField,
dbField,
- binderScope)
+ binderScope
+ )
addCode(binderScope.generate())
}.build()
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binder/InstantPreparedQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binder/InstantPreparedQueryResultBinder.kt
index 4f64c84..231ead9 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binder/InstantPreparedQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binder/InstantPreparedQueryResultBinder.kt
@@ -41,6 +41,7 @@
stmtQueryVal = scope.prepareQueryStmtBlock(),
preparedStmtField = preparedStmtField,
dbField = dbField,
- scope = scope)
+ scope = scope
+ )
}
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/GuavaListenableFuturePreparedQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/GuavaListenableFuturePreparedQueryResultBinderProvider.kt
index ef034ab..b565c14 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/GuavaListenableFuturePreparedQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/GuavaListenableFuturePreparedQueryResultBinderProvider.kt
@@ -37,7 +37,7 @@
override fun matches(declared: XDeclaredType): Boolean =
declared.typeArguments.size == 1 &&
- declared.rawType.typeName == GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
+ declared.rawType.typeName == GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
override fun provide(declared: XDeclaredType, query: ParsedQuery): PreparedQueryResultBinder {
if (!hasGuavaRoom) {
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/ArrayQueryParameterAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/ArrayQueryParameterAdapter.kt
index 477e0e9..76d85e0 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/ArrayQueryParameterAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/ArrayQueryParameterAdapter.kt
@@ -26,7 +26,7 @@
* Binds ARRAY(T) (e.g. int[]) into String[] args of a query.
*/
class ArrayQueryParameterAdapter(val bindAdapter: StatementValueBinder) :
- QueryParameterAdapter(true) {
+ QueryParameterAdapter(true) {
override fun bindToStmt(
inputVarName: String,
stmtVarName: String,
@@ -35,10 +35,12 @@
) {
scope.builder().apply {
val itrVar = scope.getTmpVar("_item")
- beginControlFlow("for ($T $L : $L)", bindAdapter.typeMirror().typeName, itrVar,
- inputVarName).apply {
- bindAdapter.bindToStmt(stmtVarName, startIndexVarName, itrVar, scope)
- addStatement("$L ++", startIndexVarName)
+ beginControlFlow(
+ "for ($T $L : $L)", bindAdapter.typeMirror().typeName, itrVar,
+ inputVarName
+ ).apply {
+ bindAdapter.bindToStmt(stmtVarName, startIndexVarName, itrVar, scope)
+ addStatement("$L ++", startIndexVarName)
}
endControlFlow()
}
@@ -46,6 +48,6 @@
override fun getArgCount(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
scope.builder()
- .addStatement("final $T $L = $L.length", TypeName.INT, outputVarName, inputVarName)
+ .addStatement("final $T $L = $L.length", TypeName.INT, outputVarName, inputVarName)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/BasicQueryParameterAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/BasicQueryParameterAdapter.kt
index da2038d..eba18d3 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/BasicQueryParameterAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/BasicQueryParameterAdapter.kt
@@ -23,7 +23,7 @@
* Knows how to convert a query parameter into arguments
*/
class BasicQueryParameterAdapter(val bindAdapter: StatementValueBinder) :
- QueryParameterAdapter(false) {
+ QueryParameterAdapter(false) {
override fun bindToStmt(
inputVarName: String,
stmtVarName: String,
@@ -36,7 +36,9 @@
}
override fun getArgCount(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
- throw UnsupportedOperationException("should not call getArgCount on basic adapters." +
- "It is always one.")
+ throw UnsupportedOperationException(
+ "should not call getArgCount on basic adapters." +
+ "It is always one."
+ )
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/CollectionQueryParameterAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/CollectionQueryParameterAdapter.kt
index b935167..732a073 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/CollectionQueryParameterAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/parameter/CollectionQueryParameterAdapter.kt
@@ -26,7 +26,7 @@
* Binds Collection<T> (e.g. List<T>) into String[] query args.
*/
class CollectionQueryParameterAdapter(val bindAdapter: StatementValueBinder) :
- QueryParameterAdapter(true) {
+ QueryParameterAdapter(true) {
override fun bindToStmt(
inputVarName: String,
stmtVarName: String,
@@ -35,17 +35,19 @@
) {
scope.builder().apply {
val itrVar = scope.getTmpVar("_item")
- beginControlFlow("for ($T $L : $L)", bindAdapter.typeMirror().typeName, itrVar,
- inputVarName).apply {
- bindAdapter.bindToStmt(stmtVarName, startIndexVarName, itrVar, scope)
- addStatement("$L ++", startIndexVarName)
- }
+ beginControlFlow(
+ "for ($T $L : $L)", bindAdapter.typeMirror().typeName, itrVar,
+ inputVarName
+ ).apply {
+ bindAdapter.bindToStmt(stmtVarName, startIndexVarName, itrVar, scope)
+ addStatement("$L ++", startIndexVarName)
+ }
endControlFlow()
}
}
override fun getArgCount(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
scope.builder()
- .addStatement("final $T $L = $L.size()", TypeName.INT, outputVarName, inputVarName)
+ .addStatement("final $T $L = $L.size()", TypeName.INT, outputVarName, inputVarName)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ArrayQueryResultAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ArrayQueryResultAdapter.kt
index 549e0df..9d7d0c1 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ArrayQueryResultAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ArrayQueryResultAdapter.kt
@@ -29,8 +29,10 @@
rowAdapter?.onCursorReady(cursorVarName, scope)
val arrayType = ArrayTypeName.of(type.typeName)
- addStatement("final $T $L = new $T[$L.getCount()]",
- arrayType, outVarName, type.typeName, cursorVarName)
+ addStatement(
+ "final $T $L = new $T[$L.getCount()]",
+ arrayType, outVarName, type.typeName, cursorVarName
+ )
val tmpVarName = scope.getTmpVar("_item")
val indexVar = scope.getTmpVar("_index")
addStatement("$T $L = 0", TypeName.INT, indexVar)
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineFlowResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineFlowResultBinder.kt
index 77313b2..ce7b50f 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineFlowResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineFlowResultBinder.kt
@@ -49,7 +49,8 @@
dbField = dbField,
inTransaction = inTransaction,
scope = scope,
- cancellationSignalVar = "null")
+ cancellationSignalVar = "null"
+ )
}.apply {
if (canReleaseQuery) {
addMethod(createFinalizeMethod(roomSQLiteQueryVar))
@@ -65,7 +66,8 @@
if (inTransaction) "true" else "false",
String::class.arrayTypeName,
tableNamesList,
- callableImpl)
+ callableImpl
+ )
}
}
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt
index acfab73..844aa5d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CoroutineResultBinder.kt
@@ -60,7 +60,8 @@
dbField = dbField,
inTransaction = inTransaction,
scope = scope,
- cancellationSignalVar = "null")
+ cancellationSignalVar = "null"
+ )
}.build()
scope.builder().apply {
@@ -71,7 +72,8 @@
if (inTransaction) "true" else "false",
cancellationSignalVar,
callableImpl,
- continuationParamName)
+ continuationParamName
+ )
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CursorQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CursorQueryResultBinder.kt
index 9f8c9e7..beccfd7 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CursorQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/CursorQueryResultBinder.kt
@@ -39,8 +39,10 @@
}
transactionWrapper?.beginTransactionWithControlFlow()
val resultName = scope.getTmpVar("_tmpResult")
- builder.addStatement("final $T $L = $N.query($L)", AndroidTypeNames.CURSOR, resultName,
- dbField, roomSQLiteQueryVar)
+ builder.addStatement(
+ "final $T $L = $N.query($L)", AndroidTypeNames.CURSOR, resultName,
+ dbField, roomSQLiteQueryVar
+ )
transactionWrapper?.commitTransaction()
builder.addStatement("return $L", resultName)
transactionWrapper?.endTransactionWithControlFlow()
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/EntityRowAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/EntityRowAdapter.kt
index a66f9e1..34fa1b4 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/EntityRowAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/EntityRowAdapter.kt
@@ -31,6 +31,6 @@
override fun convert(outVarName: String, cursorVarName: String, scope: CodeGenScope) {
scope.builder()
- .addStatement("$L = $N($L)", outVarName, methodSpec, cursorVarName)
+ .addStatement("$L = $N($L)", outVarName, methodSpec, cursorVarName)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/GuavaOptionalQueryResultAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/GuavaOptionalQueryResultAdapter.kt
index bbd3d4f..59d2cb2 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/GuavaOptionalQueryResultAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/GuavaOptionalQueryResultAdapter.kt
@@ -38,11 +38,12 @@
val valueVarName = scope.getTmpVar("_value")
resultAdapter.convert(valueVarName, cursorVarName, scope)
addStatement(
- "final $T $L = $T.fromNullable($L)",
- ParameterizedTypeName.get(GuavaBaseTypeNames.OPTIONAL, type?.typeName),
- outVarName,
- GuavaBaseTypeNames.OPTIONAL,
- valueVarName)
+ "final $T $L = $T.fromNullable($L)",
+ ParameterizedTypeName.get(GuavaBaseTypeNames.OPTIONAL, type?.typeName),
+ outVarName,
+ GuavaBaseTypeNames.OPTIONAL,
+ valueVarName
+ )
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ImmutableListQueryResultAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ImmutableListQueryResultAdapter.kt
index 3bf310d..9cf42ed 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ImmutableListQueryResultAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ImmutableListQueryResultAdapter.kt
@@ -33,9 +33,11 @@
val immutableListBuilderType = ParameterizedTypeName
.get(ClassName.get(ImmutableList.Builder::class.java), type.typeName)
val immutableListBuilderName = scope.getTmpVar("_immutableListBuilder")
- addStatement("final $T $L = $T.<$T>builder()",
+ addStatement(
+ "final $T $L = $T.<$T>builder()",
immutableListBuilderType, immutableListBuilderName,
- ClassName.get(ImmutableList::class.java), type.typeName)
+ ClassName.get(ImmutableList::class.java), type.typeName
+ )
val tmpVarName = scope.getTmpVar("_item")
beginControlFlow("while($L.moveToNext())", cursorVarName).apply {
addStatement("final $T $L", type.typeName, tmpVarName)
@@ -43,8 +45,10 @@
addStatement("$L.add($L)", immutableListBuilderName, tmpVarName)
}
endControlFlow()
- addStatement("final $T $L = $L.build()",
- collectionType, outVarName, immutableListBuilderName)
+ addStatement(
+ "final $T $L = $L.build()",
+ collectionType, outVarName, immutableListBuilderName
+ )
rowAdapter?.onCursorFinished()?.invoke(scope)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ListQueryResultAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ListQueryResultAdapter.kt
index ba5f29d..8767c2b 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ListQueryResultAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/ListQueryResultAdapter.kt
@@ -29,11 +29,13 @@
scope.builder().apply {
rowAdapter?.onCursorReady(cursorVarName, scope)
val collectionType = ParameterizedTypeName
- .get(ClassName.get(List::class.java), type.typeName)
+ .get(ClassName.get(List::class.java), type.typeName)
val arrayListType = ParameterizedTypeName
- .get(ClassName.get(ArrayList::class.java), type.typeName)
- addStatement("final $T $L = new $T($L.getCount())",
- collectionType, outVarName, arrayListType, cursorVarName)
+ .get(ClassName.get(ArrayList::class.java), type.typeName)
+ addStatement(
+ "final $T $L = new $T($L.getCount())",
+ collectionType, outVarName, arrayListType, cursorVarName
+ )
val tmpVarName = scope.getTmpVar("_item")
beginControlFlow("while($L.moveToNext())", cursorVarName).apply {
addStatement("final $T $L", type.typeName, tmpVarName)
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/OptionalQueryResultAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/OptionalQueryResultAdapter.kt
index f6f5157..ab6ba52 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/OptionalQueryResultAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/OptionalQueryResultAdapter.kt
@@ -40,11 +40,12 @@
val valueVarName = scope.getTmpVar("_value")
resultAdapter.convert(valueVarName, cursorVarName, scope)
addStatement(
- "final $T $L = $T.ofNullable($L)",
- ParameterizedTypeName.get(CommonTypeNames.OPTIONAL, type?.typeName),
- outVarName,
- CommonTypeNames.OPTIONAL,
- valueVarName)
+ "final $T $L = $T.ofNullable($L)",
+ ParameterizedTypeName.get(CommonTypeNames.OPTIONAL, type?.typeName),
+ outVarName,
+ CommonTypeNames.OPTIONAL,
+ valueVarName
+ )
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
index aed5aea..067a9d2 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
@@ -87,7 +87,8 @@
ProcessorErrors.pojoMissingNonNull(
pojoTypeName = pojo.typeName,
missingPojoFields = nonNulls.map { it.name },
- allQueryColumns = info.columns.map { it.name })
+ allQueryColumns = info.columns.map { it.name }
+ )
)
}
if (matchedFields.isEmpty()) {
@@ -120,7 +121,8 @@
override fun onCursorReady(cursorVarName: String, scope: CodeGenScope) {
mapping.fieldsWithIndices = mapping.matchedFields.map {
val indexVar = scope.getTmpVar(
- "_cursorIndexOf${it.name.stripNonJava().capitalize(Locale.US)}")
+ "_cursorIndexOf${it.name.stripNonJava().capitalize(Locale.US)}"
+ )
val indexMethod = if (info == null) {
"getColumnIndex"
} else {
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/PositionalDataSourceQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/PositionalDataSourceQueryResultBinder.kt
index 7da04a0f..e6c6087 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/PositionalDataSourceQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/PositionalDataSourceQueryResultBinder.kt
@@ -36,7 +36,8 @@
) : QueryResultBinder(listAdapter) {
val itemTypeName: TypeName = listAdapter?.rowAdapter?.out?.typeName ?: TypeName.OBJECT
val typeName: ParameterizedTypeName = ParameterizedTypeName.get(
- RoomTypeNames.LIMIT_OFFSET_DATA_SOURCE, itemTypeName)
+ RoomTypeNames.LIMIT_OFFSET_DATA_SOURCE, itemTypeName
+ )
override fun convertAndReturn(
roomSQLiteQueryVar: String,
canReleaseQuery: Boolean,
@@ -48,8 +49,10 @@
// we don't need a comma. If list is empty, this prevents generating bad code (it is still
// an error to have empty list but that is already reported while item is processed)
val tableNamesList = tableNames.joinToString("") { ", \"$it\"" }
- val spec = TypeSpec.anonymousClassBuilder("$N, $L, $L $L",
- dbField, roomSQLiteQueryVar, inTransaction, tableNamesList).apply {
+ val spec = TypeSpec.anonymousClassBuilder(
+ "$N, $L, $L $L",
+ dbField, roomSQLiteQueryVar, inTransaction, tableNamesList
+ ).apply {
superclass(typeName)
addMethod(createConvertRowsMethod(scope))
}.build()
@@ -59,17 +62,17 @@
}
private fun createConvertRowsMethod(scope: CodeGenScope): MethodSpec =
- MethodSpec.methodBuilder("convertRows").apply {
- addAnnotation(Override::class.java)
- addModifiers(Modifier.PROTECTED)
- returns(ParameterizedTypeName.get(CommonTypeNames.LIST, itemTypeName))
- val cursorParam = ParameterSpec.builder(AndroidTypeNames.CURSOR, "cursor")
- .build()
- addParameter(cursorParam)
- val resultVar = scope.getTmpVar("_res")
- val rowsScope = scope.fork()
- listAdapter?.convert(resultVar, cursorParam.name, rowsScope)
- addCode(rowsScope.builder().build())
- addStatement("return $L", resultVar)
- }.build()
+ MethodSpec.methodBuilder("convertRows").apply {
+ addAnnotation(Override::class.java)
+ addModifiers(Modifier.PROTECTED)
+ returns(ParameterizedTypeName.get(CommonTypeNames.LIST, itemTypeName))
+ val cursorParam = ParameterSpec.builder(AndroidTypeNames.CURSOR, "cursor")
+ .build()
+ addParameter(cursorParam)
+ val resultVar = scope.getTmpVar("_res")
+ val rowsScope = scope.fork()
+ listAdapter?.convert(resultVar, cursorParam.name, rowsScope)
+ addCode(rowsScope.builder().build())
+ addStatement("return $L", resultVar)
+ }.build()
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/QueryResultAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/QueryResultAdapter.kt
index 62db148..dc27eaf 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/QueryResultAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/QueryResultAdapter.kt
@@ -27,7 +27,7 @@
// indicates whether the cursor should be copied before converting
open fun shouldCopyCursor() = rowAdapter is PojoRowAdapter &&
- rowAdapter.relationCollectors.isNotEmpty()
+ rowAdapter.relationCollectors.isNotEmpty()
fun accessedTableNames(): List<String> {
return (rowAdapter as? PojoRowAdapter)?.relationTableNames() ?: emptyList()
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
index 07a1160..d486787 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
@@ -50,7 +50,8 @@
roomSQLiteQueryVar = roomSQLiteQueryVar,
dbField = dbField,
inTransaction = inTransaction,
- scope = scope)
+ scope = scope
+ )
}.apply {
if (canReleaseQuery) {
addMethod(createFinalizeMethod(roomSQLiteQueryVar))
@@ -81,23 +82,27 @@
val shouldCopyCursor = adapter?.shouldCopyCursor() == true
val outVar = scope.getTmpVar("_result")
val cursorVar = scope.getTmpVar("_cursor")
- addStatement("final $T $L = $T.query($N, $L, $L, $L)",
- AndroidTypeNames.CURSOR,
- cursorVar,
- RoomTypeNames.DB_UTIL,
- dbField,
- roomSQLiteQueryVar,
- if (shouldCopyCursor) "true" else "false",
- "null")
+ addStatement(
+ "final $T $L = $T.query($N, $L, $L, $L)",
+ AndroidTypeNames.CURSOR,
+ cursorVar,
+ RoomTypeNames.DB_UTIL,
+ dbField,
+ roomSQLiteQueryVar,
+ if (shouldCopyCursor) "true" else "false",
+ "null"
+ )
beginControlFlow("try").apply {
adapter?.convert(outVar, cursorVar, adapterScope)
addCode(adapterScope.generate())
if (!rxType.canBeNull) {
beginControlFlow("if($L == null)", outVar).apply {
- addStatement("throw new $T($S + $L.getSql())",
- rxType.version.emptyResultExceptionClassName,
- "Query returned empty result set: ",
- roomSQLiteQueryVar)
+ addStatement(
+ "throw new $T($S + $L.getSql())",
+ rxType.version.emptyResultExceptionClassName,
+ "Query returned empty result set: ",
+ roomSQLiteQueryVar
+ )
}
endControlFlow()
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
index d25051d..717d70f 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
@@ -43,12 +43,14 @@
scope: CodeGenScope
) {
val callableImpl = CallableTypeSpecBuilder(typeArg.typeName) {
- createRunQueryAndReturnStatements(builder = this,
+ createRunQueryAndReturnStatements(
+ builder = this,
roomSQLiteQueryVar = roomSQLiteQueryVar,
inTransaction = inTransaction,
dbField = dbField,
scope = scope,
- cancellationSignalVar = "null")
+ cancellationSignalVar = "null"
+ )
}.apply {
if (canReleaseQuery) {
addMethod(createFinalizeMethod(roomSQLiteQueryVar))
@@ -56,14 +58,16 @@
}.build()
scope.builder().apply {
val tableNamesList = queryTableNames.joinToString(",") { "\"$it\"" }
- addStatement("return $T.$N($N, $L, new $T{$L}, $L)",
+ addStatement(
+ "return $T.$N($N, $L, new $T{$L}, $L)",
rxType.version.rxRoomClassName,
rxType.factoryMethodName,
dbField,
if (inTransaction) "true" else "false",
String::class.arrayTypeName,
tableNamesList,
- callableImpl)
+ callableImpl
+ )
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/SingleEntityQueryResultAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/SingleEntityQueryResultAdapter.kt
index de66448..2411b81 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/SingleEntityQueryResultAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/SingleEntityQueryResultAdapter.kt
@@ -30,7 +30,7 @@
rowAdapter?.onCursorReady(cursorVarName, scope)
addStatement("final $T $L", type.typeName, outVarName)
beginControlFlow("if($L.moveToFirst())", cursorVarName)
- rowAdapter?.convert(outVarName, cursorVarName, scope)
+ rowAdapter?.convert(outVarName, cursorVarName, scope)
nextControlFlow("else").apply {
addStatement("$L = $L", outVarName, rowAdapter?.out?.defaultValue())
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableInsertMethodBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableInsertMethodBinder.kt
index 35a5b2d..c053354 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableInsertMethodBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableInsertMethodBinder.kt
@@ -38,33 +38,33 @@
adapter: InsertMethodAdapter?
) : InsertMethodBinder(adapter) {
- companion object {
- fun createInsertBinder(
- typeArg: XType,
- adapter: InsertMethodAdapter?,
- addCodeBlock: CodeBlock.Builder.(callableImpl: TypeSpec, dbField: FieldSpec) -> Unit
- ) = CallableInsertMethodBinder(typeArg, addCodeBlock, adapter)
- }
+ companion object {
+ fun createInsertBinder(
+ typeArg: XType,
+ adapter: InsertMethodAdapter?,
+ addCodeBlock: CodeBlock.Builder.(callableImpl: TypeSpec, dbField: FieldSpec) -> Unit
+ ) = CallableInsertMethodBinder(typeArg, addCodeBlock, adapter)
+ }
- override fun convertAndReturn(
- parameters: List<ShortcutQueryParameter>,
- insertionAdapters: Map<String, Pair<FieldSpec, TypeSpec>>,
- dbField: FieldSpec,
- scope: CodeGenScope
- ) {
- val adapterScope = scope.fork()
- val callableImpl = CallableTypeSpecBuilder(typeArg.typeName) {
- adapter?.createInsertionMethodBody(
- parameters = parameters,
- insertionAdapters = insertionAdapters,
- dbField = dbField,
- scope = adapterScope
- )
- addCode(adapterScope.generate())
- }.build()
+ override fun convertAndReturn(
+ parameters: List<ShortcutQueryParameter>,
+ insertionAdapters: Map<String, Pair<FieldSpec, TypeSpec>>,
+ dbField: FieldSpec,
+ scope: CodeGenScope
+ ) {
+ val adapterScope = scope.fork()
+ val callableImpl = CallableTypeSpecBuilder(typeArg.typeName) {
+ adapter?.createInsertionMethodBody(
+ parameters = parameters,
+ insertionAdapters = insertionAdapters,
+ dbField = dbField,
+ scope = adapterScope
+ )
+ addCode(adapterScope.generate())
+ }.build()
- scope.builder().apply {
- addStmntBlock(callableImpl, dbField)
- }
+ scope.builder().apply {
+ addStmntBlock(callableImpl, dbField)
}
- }
\ No newline at end of file
+ }
+}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantDeleteOrUpdateMethodBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantDeleteOrUpdateMethodBinder.kt
index 3e3e938..be271f5 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantDeleteOrUpdateMethodBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantDeleteOrUpdateMethodBinder.kt
@@ -41,10 +41,10 @@
addStatement("$N.assertNotSuspendingTransaction()", DaoWriter.dbField)
}
adapter?.createDeleteOrUpdateMethodBody(
- parameters = parameters,
- adapters = adapters,
- dbField = dbField,
- scope = scope
+ parameters = parameters,
+ adapters = adapters,
+ dbField = dbField,
+ scope = scope
)
}
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantInsertMethodBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantInsertMethodBinder.kt
index d0f1310..b808080 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantInsertMethodBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/InstantInsertMethodBinder.kt
@@ -39,10 +39,10 @@
addStatement("$N.assertNotSuspendingTransaction()", DaoWriter.dbField)
}
adapter?.createInsertionMethodBody(
- parameters = parameters,
- insertionAdapters = insertionAdapters,
- dbField = dbField,
- scope = scope
+ parameters = parameters,
+ insertionAdapters = insertionAdapters,
+ dbField = dbField,
+ scope = scope
)
}
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureDeleteOrUpdateMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureDeleteOrUpdateMethodBinderProvider.kt
index e1fcc51..0cd47a0 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureDeleteOrUpdateMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureDeleteOrUpdateMethodBinderProvider.kt
@@ -40,7 +40,7 @@
override fun matches(declared: XDeclaredType): Boolean =
declared.typeArguments.size == 1 &&
- declared.rawType.typeName == GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
+ declared.rawType.typeName == GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
override fun provide(declared: XDeclaredType): DeleteOrUpdateMethodBinder {
if (!hasGuavaRoom) {
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureInsertMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureInsertMethodBinderProvider.kt
index f62767d..94ebcf9 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureInsertMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/GuavaListenableFutureInsertMethodBinderProvider.kt
@@ -41,7 +41,7 @@
override fun matches(declared: XDeclaredType): Boolean =
declared.typeArguments.size == 1 &&
- declared.rawType.typeName == GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
+ declared.rawType.typeName == GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
override fun provide(
declared: XDeclaredType,
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/InstantInsertMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/InstantInsertMethodBinderProvider.kt
index b1f1fb9..e5353de 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/InstantInsertMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/InstantInsertMethodBinderProvider.kt
@@ -34,7 +34,7 @@
params: List<ShortcutQueryParameter>
): InsertMethodBinder {
return InstantInsertMethodBinder(
- context.typeAdapterStore.findInsertAdapter(declared, params)
+ context.typeAdapterStore.findInsertAdapter(declared, params)
)
}
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
index 822be43..bf12591 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
@@ -41,7 +41,7 @@
open fun extractTypeArg(declared: XDeclaredType): XType = declared.typeArguments.first()
override fun matches(declared: XDeclaredType): Boolean =
- declared.typeArguments.size == 1 && matchesRxType(declared)
+ declared.typeArguments.size == 1 && matchesRxType(declared)
private fun matchesRxType(declared: XDeclaredType): Boolean {
return declared.rawType.typeName == rxType.className
@@ -81,7 +81,7 @@
* Like this, the generated Callable.call method will return Void.
*/
override fun extractTypeArg(declared: XDeclaredType): XType =
- context.COMMON_TYPES.VOID
+ context.COMMON_TYPES.VOID
override fun matches(declared: XDeclaredType): Boolean = isCompletable(declared)
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
index f8480a6..b934dd7 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
@@ -42,7 +42,7 @@
open fun extractTypeArg(declared: XDeclaredType): XType = declared.typeArguments.first()
override fun matches(declared: XDeclaredType): Boolean =
- declared.typeArguments.size == 1 && matchesRxType(declared)
+ declared.typeArguments.size == 1 && matchesRxType(declared)
private fun matchesRxType(declared: XDeclaredType): Boolean {
return declared.rawType.typeName == rxType.className
@@ -85,7 +85,7 @@
* Like this, the generated Callable.call method will return Void.
*/
override fun extractTypeArg(declared: XDeclaredType): XType =
- context.COMMON_TYPES.VOID
+ context.COMMON_TYPES.VOID
override fun matches(declared: XDeclaredType): Boolean = isCompletable(declared)
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/DeleteOrUpdateMethodAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/DeleteOrUpdateMethodAdapter.kt
index f85ca8c..dffe5b7 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/DeleteOrUpdateMethodAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/DeleteOrUpdateMethodAdapter.kt
@@ -41,9 +41,9 @@
private fun isDeleteOrUpdateValid(returnType: XType): Boolean {
return returnType.isVoid() ||
- returnType.isInt() ||
- returnType.isVoidObject() ||
- returnType.isKotlinUnit()
+ returnType.isInt() ||
+ returnType.isVoidObject() ||
+ returnType.isKotlinUnit()
}
}
@@ -66,9 +66,11 @@
beginControlFlow("try").apply {
parameters.forEach { param ->
val adapter = adapters[param.name]?.first
- addStatement("$L$N.$L($L)",
- if (resultVar == null) "" else "$resultVar +=",
- adapter, param.handleMethodName(), param.name)
+ addStatement(
+ "$L$N.$L($L)",
+ if (resultVar == null) "" else "$resultVar +=",
+ adapter, param.handleMethodName(), param.name
+ )
}
addStatement("$N.setTransactionSuccessful()", dbField)
if (resultVar != null) {
@@ -87,9 +89,11 @@
}
private fun hasResultValue(returnType: XType): Boolean {
- return !(returnType.isVoid() ||
+ return !(
+ returnType.isVoid() ||
returnType.isVoidObject() ||
- returnType.isKotlinUnit())
+ returnType.isKotlinUnit()
+ )
}
private fun hasNullReturn(returnType: XType) = returnType.isVoidObject()
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/InsertMethodAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/InsertMethodAdapter.kt
index a9a6590..215ffb5 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/InsertMethodAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/result/InsertMethodAdapter.kt
@@ -57,25 +57,27 @@
}
if (params.isEmpty() || params.size > 1) {
return insertionType == InsertionType.INSERT_VOID ||
- insertionType == InsertionType.INSERT_UNIT
+ insertionType == InsertionType.INSERT_UNIT
}
return if (params.first().isMultiple) {
insertionType in MULTIPLE_ITEM_SET
} else {
insertionType == InsertionType.INSERT_VOID ||
- insertionType == InsertionType.INSERT_VOID_OBJECT ||
- insertionType == InsertionType.INSERT_UNIT ||
- insertionType == InsertionType.INSERT_SINGLE_ID
+ insertionType == InsertionType.INSERT_VOID_OBJECT ||
+ insertionType == InsertionType.INSERT_UNIT ||
+ insertionType == InsertionType.INSERT_SINGLE_ID
}
}
private val MULTIPLE_ITEM_SET by lazy {
- setOf(InsertionType.INSERT_VOID,
- InsertionType.INSERT_VOID_OBJECT,
- InsertionType.INSERT_UNIT,
- InsertionType.INSERT_ID_ARRAY,
- InsertionType.INSERT_ID_ARRAY_BOX,
- InsertionType.INSERT_ID_LIST)
+ setOf(
+ InsertionType.INSERT_VOID,
+ InsertionType.INSERT_VOID_OBJECT,
+ InsertionType.INSERT_UNIT,
+ InsertionType.INSERT_ID_ARRAY,
+ InsertionType.INSERT_ID_ARRAY_BOX,
+ InsertionType.INSERT_ID_LIST
+ )
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
@@ -124,8 +126,8 @@
// TODO collect results
addStatement("$N.beginTransaction()", dbField)
val needsResultVar = insertionType != InsertionType.INSERT_VOID &&
- insertionType != InsertionType.INSERT_VOID_OBJECT &&
- insertionType != InsertionType.INSERT_UNIT
+ insertionType != InsertionType.INSERT_VOID_OBJECT &&
+ insertionType != InsertionType.INSERT_UNIT
val resultVar = if (needsResultVar) {
scope.getTmpVar("_result")
} else {
@@ -138,13 +140,17 @@
if (needsResultVar) {
// if it has more than 1 parameter, we would've already printed the error
// so we don't care about re-declaring the variable here
- addStatement("$T $L = $N.$L($L)",
- insertionType.returnTypeName, resultVar,
- insertionAdapter, insertionType.methodName,
- param.name)
+ addStatement(
+ "$T $L = $N.$L($L)",
+ insertionType.returnTypeName, resultVar,
+ insertionAdapter, insertionType.methodName,
+ param.name
+ )
} else {
- addStatement("$N.$L($L)", insertionAdapter, insertionType.methodName,
- param.name)
+ addStatement(
+ "$N.$L($L)", insertionAdapter, insertionType.methodName,
+ param.name
+ )
}
}
addStatement("$N.setTransactionSuccessful()", dbField)
@@ -164,7 +170,7 @@
}
enum class InsertionType(
- // methodName matches EntityInsertionAdapter methods
+ // methodName matches EntityInsertionAdapter methods
val methodName: String,
val returnTypeName: TypeName
) {
@@ -172,11 +178,17 @@
INSERT_VOID_OBJECT("insert", TypeName.VOID), // return void
INSERT_UNIT("insert", KotlinTypeNames.UNIT), // return kotlin.Unit.INSTANCE
INSERT_SINGLE_ID("insertAndReturnId", TypeName.LONG), // return long
- INSERT_ID_ARRAY("insertAndReturnIdsArray",
- ArrayTypeName.of(TypeName.LONG)), // return long[]
- INSERT_ID_ARRAY_BOX("insertAndReturnIdsArrayBox",
- ArrayTypeName.of(TypeName.LONG.box())), // return Long[]
- INSERT_ID_LIST("insertAndReturnIdsList", // return List<Long>
- ParameterizedTypeName.get(List::class.typeName, TypeName.LONG.box())),
+ INSERT_ID_ARRAY(
+ "insertAndReturnIdsArray",
+ ArrayTypeName.of(TypeName.LONG)
+ ), // return long[]
+ INSERT_ID_ARRAY_BOX(
+ "insertAndReturnIdsArrayBox",
+ ArrayTypeName.of(TypeName.LONG.box())
+ ), // return Long[]
+ INSERT_ID_LIST(
+ "insertAndReturnIdsList", // return List<Long>
+ ParameterizedTypeName.get(List::class.typeName, TypeName.LONG.box())
+ ),
}
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/transaction/binder/CoroutineTransactionMethodBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/transaction/binder/CoroutineTransactionMethodBinder.kt
index 04fdcc4..a5df23c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/transaction/binder/CoroutineTransactionMethodBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/transaction/binder/CoroutineTransactionMethodBinder.kt
@@ -48,7 +48,8 @@
val innerContinuationParamName = "__cont"
val functionImpl = Function1TypeSpecBuilder(
parameterTypeName = ParameterizedTypeName.get(
- CONTINUATION, WildcardTypeName.supertypeOf(returnType.typeName)),
+ CONTINUATION, WildcardTypeName.supertypeOf(returnType.typeName)
+ ),
parameterName = innerContinuationParamName,
returnTypeName = ClassName.OBJECT
) {
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/transaction/result/TransactionMethodAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/transaction/result/TransactionMethodAdapter.kt
index 2811589..a393201 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/transaction/result/TransactionMethodAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/transaction/result/TransactionMethodAdapter.kt
@@ -46,7 +46,8 @@
val format = buildString {
if (resultVar != null && returnStmt) {
throw IllegalStateException(
- "Can't assign to var and return in the same statement.")
+ "Can't assign to var and return in the same statement."
+ )
} else if (resultVar != null) {
append("$T $L = ")
params.add(returnType.typeName)
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
index 69e3a95..7a3664c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
@@ -28,26 +28,30 @@
val tBoolean = processingEnvironment.requireType("java.lang.Boolean")
val tInt = processingEnvironment.requireType("java.lang.Integer")
return listOf(
- object : TypeConverter(tBoolean, tInt) {
- override fun convert(
- inputVarName: String,
- outputVarName: String,
- scope: CodeGenScope
- ) {
- scope.builder().addStatement("$L = $L == null ? null : ($L ? 1 : 0)",
- outputVarName, inputVarName, inputVarName)
- }
- },
- object : TypeConverter(tInt, tBoolean) {
- override fun convert(
- inputVarName: String,
- outputVarName: String,
- scope: CodeGenScope
- ) {
- scope.builder().addStatement("$L = $L == null ? null : $L != 0",
- outputVarName, inputVarName, inputVarName)
- }
+ object : TypeConverter(tBoolean, tInt) {
+ override fun convert(
+ inputVarName: String,
+ outputVarName: String,
+ scope: CodeGenScope
+ ) {
+ scope.builder().addStatement(
+ "$L = $L == null ? null : ($L ? 1 : 0)",
+ outputVarName, inputVarName, inputVarName
+ )
}
+ },
+ object : TypeConverter(tInt, tBoolean) {
+ override fun convert(
+ inputVarName: String,
+ outputVarName: String,
+ scope: CodeGenScope
+ ) {
+ scope.builder().addStatement(
+ "$L = $L == null ? null : $L != 0",
+ outputVarName, inputVarName, inputVarName
+ )
+ }
+ }
)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteArrayColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteArrayColumnTypeAdapter.kt
index 0e81eb2..e705fea 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteArrayColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteArrayColumnTypeAdapter.kt
@@ -23,8 +23,9 @@
import com.squareup.javapoet.TypeName
class ByteArrayColumnTypeAdapter(env: XProcessingEnv) : ColumnTypeAdapter(
- out = env.getArrayType(TypeName.BYTE),
- typeAffinity = SQLTypeAffinity.BLOB) {
+ out = env.getArrayType(TypeName.BYTE),
+ typeAffinity = SQLTypeAffinity.BLOB
+) {
override fun readFromCursor(
outVarName: String,
cursorVarName: String,
@@ -32,7 +33,7 @@
scope: CodeGenScope
) {
scope.builder()
- .addStatement("$L = $L.getBlob($L)", outVarName, cursorVarName, indexVarName)
+ .addStatement("$L = $L.getBlob($L)", outVarName, cursorVarName, indexVarName)
}
override fun bindToStmt(
@@ -43,9 +44,9 @@
) {
scope.builder().apply {
beginControlFlow("if ($L == null)", valueVarName)
- .addStatement("$L.bindNull($L)", stmtName, indexVarName)
+ .addStatement("$L.bindNull($L)", stmtName, indexVarName)
nextControlFlow("else")
- .addStatement("$L.bindBlob($L, $L)", stmtName, indexVarName, valueVarName)
+ .addStatement("$L.bindBlob($L, $L)", stmtName, indexVarName, valueVarName)
endControlFlow()
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteBufferColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteBufferColumnTypeAdapter.kt
index 66a77a1..3aeaa88 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteBufferColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/ByteBufferColumnTypeAdapter.kt
@@ -35,8 +35,10 @@
scope: CodeGenScope
) {
scope.builder()
- .addStatement("$L = $T.wrap($L.getBlob($L))",
- outVarName, TypeName.get(ByteBuffer::class.java), cursorVarName, indexVarName)
+ .addStatement(
+ "$L = $T.wrap($L.getBlob($L))",
+ outVarName, TypeName.get(ByteBuffer::class.java), cursorVarName, indexVarName
+ )
}
override fun bindToStmt(
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/ColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/ColumnTypeAdapter.kt
index 9405efc..c1fdc6d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/ColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/ColumnTypeAdapter.kt
@@ -24,7 +24,7 @@
* A code generator that can read a field from Cursor and write a field to a Statement
*/
abstract class ColumnTypeAdapter(val out: XType, val typeAffinity: SQLTypeAffinity) :
- StatementValueBinder, CursorValueReader {
+ StatementValueBinder, CursorValueReader {
val outTypeName: TypeName by lazy { out.typeName }
override fun typeMirror() = out
override fun affinity(): SQLTypeAffinity = typeAffinity
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/CompositeTypeConverter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/CompositeTypeConverter.kt
index 450a6b6..63f2e69 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/CompositeTypeConverter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/CompositeTypeConverter.kt
@@ -24,7 +24,8 @@
* combines 2 type converters
*/
class CompositeTypeConverter(val conv1: TypeConverter, val conv2: TypeConverter) : TypeConverter(
- conv1.from, conv2.to) {
+ conv1.from, conv2.to
+) {
override fun convert(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
scope.builder().apply {
val tmp = scope.getTmpVar()
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/CustomTypeConverterWrapper.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/CustomTypeConverterWrapper.kt
index 6d2b5e9..9df809b 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/CustomTypeConverterWrapper.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/CustomTypeConverterWrapper.kt
@@ -41,18 +41,24 @@
override fun convert(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
scope.builder().apply {
if (custom.isEnclosingClassKotlinObject) {
- addStatement("$L = $T.INSTANCE.$L($L)",
+ addStatement(
+ "$L = $T.INSTANCE.$L($L)",
outputVarName, custom.typeName,
- custom.methodName, inputVarName)
+ custom.methodName, inputVarName
+ )
} else if (custom.isStatic) {
- addStatement("$L = $T.$L($L)",
- outputVarName, custom.typeName,
- custom.methodName, inputVarName)
+ addStatement(
+ "$L = $T.$L($L)",
+ outputVarName, custom.typeName,
+ custom.methodName, inputVarName
+ )
} else {
if (custom.isProvidedConverter) {
- addStatement("$L = $N().$L($L)",
+ addStatement(
+ "$L = $N().$L($L)",
outputVarName, providedTypeConverter(scope),
- custom.methodName, inputVarName)
+ custom.methodName, inputVarName
+ )
} else {
addStatement(
"$L = $N.$L($L)",
@@ -73,14 +79,14 @@
val converterField = scope.writer.getOrCreateField(object : ClassWriter.SharedFieldSpec(
baseName, custom.typeName
) {
- override fun getUniqueKey(): String {
- return "converter_${custom.typeName}"
- }
+ override fun getUniqueKey(): String {
+ return "converter_${custom.typeName}"
+ }
- override fun prepare(writer: ClassWriter, builder: FieldSpec.Builder) {
- builder.addModifiers(Modifier.PRIVATE)
- }
- })
+ override fun prepare(writer: ClassWriter, builder: FieldSpec.Builder) {
+ builder.addModifiers(Modifier.PRIVATE)
+ }
+ })
return scope.writer.getOrCreateMethod(object : ClassWriter.SharedMethodSpec(baseName) {
override fun getUniqueKey(): String {
@@ -123,17 +129,18 @@
fun typeConverter(scope: CodeGenScope): FieldSpec {
val baseName = (custom.typeName as ClassName).simpleName().decapitalize(Locale.US)
return scope.writer.getOrCreateField(object : ClassWriter.SharedFieldSpec(
- baseName, custom.typeName) {
- override fun getUniqueKey(): String {
- return "converter_${custom.typeName}"
- }
+ baseName, custom.typeName
+ ) {
+ override fun getUniqueKey(): String {
+ return "converter_${custom.typeName}"
+ }
- override fun prepare(writer: ClassWriter, builder: FieldSpec.Builder) {
- builder.addModifiers(Modifier.PRIVATE)
- builder.addModifiers(Modifier.FINAL)
- builder.initializer("new $T()", custom.typeName)
- }
- })
+ override fun prepare(writer: ClassWriter, builder: FieldSpec.Builder) {
+ builder.addModifiers(Modifier.PRIVATE)
+ builder.addModifiers(Modifier.FINAL)
+ builder.initializer("new $T()", custom.typeName)
+ }
+ })
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/NoOpConverter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/NoOpConverter.kt
index 2c7e651..9656ce7 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/NoOpConverter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/NoOpConverter.kt
@@ -29,9 +29,10 @@
* etc.
*/
class NoOpConverter(type: XType) : TypeConverter(
- type, type) {
+ type, type
+) {
override fun convert(inputVarName: String, outputVarName: String, scope: CodeGenScope) {
scope.builder()
- .addStatement("$L = $L", outputVarName, inputVarName)
+ .addStatement("$L = $L", outputVarName, inputVarName)
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveBooleanToIntConverter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveBooleanToIntConverter.kt
index 43cf6b3..0dac5cc 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveBooleanToIntConverter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveBooleanToIntConverter.kt
@@ -29,23 +29,24 @@
val tBoolean = processingEnvironment.requireType(TypeName.BOOLEAN)
val tInt = processingEnvironment.requireType(TypeName.INT)
return listOf(
- object : TypeConverter(tBoolean, tInt) {
- override fun convert(
- inputVarName: String,
- outputVarName: String,
- scope: CodeGenScope
- ) {
- scope.builder().addStatement("$L = $L ? 1 : 0", outputVarName, inputVarName)
- }
- },
- object : TypeConverter(tInt, tBoolean) {
- override fun convert(
- inputVarName: String,
- outputVarName: String,
- scope: CodeGenScope
- ) {
- scope.builder().addStatement("$L = $L != 0", outputVarName, inputVarName)
- }
- })
+ object : TypeConverter(tBoolean, tInt) {
+ override fun convert(
+ inputVarName: String,
+ outputVarName: String,
+ scope: CodeGenScope
+ ) {
+ scope.builder().addStatement("$L = $L ? 1 : 0", outputVarName, inputVarName)
+ }
+ },
+ object : TypeConverter(tInt, tBoolean) {
+ override fun convert(
+ inputVarName: String,
+ outputVarName: String,
+ scope: CodeGenScope
+ ) {
+ scope.builder().addStatement("$L = $L != 0", outputVarName, inputVarName)
+ }
+ }
+ )
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveColumnTypeAdapter.kt
index 22b6cf3..88c9c73 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/PrimitiveColumnTypeAdapter.kt
@@ -42,32 +42,32 @@
typeAffinity: SQLTypeAffinity
) : ColumnTypeAdapter(out, typeAffinity) {
val cast = if (cursorGetter == "get${out.typeName.toString().capitalize(Locale.US)}")
- ""
- else
- "(${out.typeName}) "
+ ""
+ else
+ "(${out.typeName}) "
companion object {
fun createPrimitiveAdapters(
processingEnvironment: XProcessingEnv
): List<PrimitiveColumnTypeAdapter> {
return listOf(
- Triple(INT, "getInt", "bindLong"),
- Triple(SHORT, "getShort", "bindLong"),
- Triple(BYTE, "getShort", "bindLong"),
- Triple(LONG, "getLong", "bindLong"),
- Triple(CHAR, "getInt", "bindLong"),
- Triple(FLOAT, "getFloat", "bindDouble"),
- Triple(DOUBLE, "getDouble", "bindDouble")
+ Triple(INT, "getInt", "bindLong"),
+ Triple(SHORT, "getShort", "bindLong"),
+ Triple(BYTE, "getShort", "bindLong"),
+ Triple(LONG, "getLong", "bindLong"),
+ Triple(CHAR, "getInt", "bindLong"),
+ Triple(FLOAT, "getFloat", "bindDouble"),
+ Triple(DOUBLE, "getDouble", "bindDouble")
).map {
PrimitiveColumnTypeAdapter(
- out = processingEnvironment.requireType(it.first),
- cursorGetter = it.second,
- stmtSetter = it.third,
- typeAffinity = when (it.first) {
- INT, SHORT, BYTE, LONG, CHAR -> SQLTypeAffinity.INTEGER
- FLOAT, DOUBLE -> REAL
- else -> throw IllegalArgumentException("invalid type")
- }
+ out = processingEnvironment.requireType(it.first),
+ cursorGetter = it.second,
+ stmtSetter = it.third,
+ typeAffinity = when (it.first) {
+ INT, SHORT, BYTE, LONG, CHAR -> SQLTypeAffinity.INTEGER
+ FLOAT, DOUBLE -> REAL
+ else -> throw IllegalArgumentException("invalid type")
+ }
)
}
}
@@ -80,7 +80,7 @@
scope: CodeGenScope
) {
scope.builder()
- .addStatement("$L.$L($L, $L)", stmtName, stmtSetter, indexVarName, valueVarName)
+ .addStatement("$L.$L($L, $L)", stmtName, stmtSetter, indexVarName, valueVarName)
}
override fun readFromCursor(
@@ -90,7 +90,9 @@
scope: CodeGenScope
) {
scope.builder()
- .addStatement("$L = $L$L.$L($L)", outVarName, cast, cursorVarName,
- cursorGetter, indexVarName)
+ .addStatement(
+ "$L = $L$L.$L($L)", outVarName, cast, cursorVarName,
+ cursorGetter, indexVarName
+ )
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/StringColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/StringColumnTypeAdapter.kt
index a741f5d..36593b2 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/StringColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/StringColumnTypeAdapter.kt
@@ -30,7 +30,7 @@
scope: CodeGenScope
) {
scope.builder()
- .addStatement("$L = $L.getString($L)", outVarName, cursorVarName, indexVarName)
+ .addStatement("$L = $L.getString($L)", outVarName, cursorVarName, indexVarName)
}
override fun bindToStmt(
@@ -41,9 +41,9 @@
) {
scope.builder().apply {
beginControlFlow("if ($L == null)", valueVarName)
- .addStatement("$L.bindNull($L)", stmtName, indexVarName)
+ .addStatement("$L.bindNull($L)", stmtName, indexVarName)
nextControlFlow("else")
- .addStatement("$L.bindString($L, $L)", stmtName, indexVarName, valueVarName)
+ .addStatement("$L.bindString($L, $L)", stmtName, indexVarName, valueVarName)
endControlFlow()
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerificationErrors.kt b/room/compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerificationErrors.kt
index 7032107..be417e4 100644
--- a/room/compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerificationErrors.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerificationErrors.kt
@@ -25,7 +25,7 @@
}
private val CANNOT_CREATE_SQLITE_CONNECTION: String = "Room cannot create an SQLite" +
- " connection to verify the queries. Query verification will be disabled. Error: %s"
+ " connection to verify the queries. Query verification will be disabled. Error: %s"
fun cannotCreateConnection(exception: Throwable): String {
return CANNOT_CREATE_SQLITE_CONNECTION.format(exception.message)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerifier.kt b/room/compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerifier.kt
index cdc63bc..d7fd403 100644
--- a/room/compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerifier.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerifier.kt
@@ -78,18 +78,18 @@
val tempDir = System.getProperty("org.sqlite.tmpdir", defaultTempDir)
checkNotNull(tempDir) {
"Room needs the java.io.tmpdir or org.sqlite.tmpdir system property to be set to " +
- "setup SQLite."
+ "setup SQLite."
}
File(tempDir).also {
check(
it.isDirectory &&
- (it.exists() || it.mkdirs()) &&
- it.canRead() &&
- it.canWrite()
+ (it.exists() || it.mkdirs()) &&
+ it.canRead() &&
+ it.canWrite()
) {
"The temp dir [$tempDir] needs to be a directory, must be readable, writable " +
- "and allow executables. Please, provide a temporary directory that " +
- "fits the requirements via the 'org.sqlite.tmpdir' property."
+ "and allow executables. Please, provide a temporary directory that " +
+ "fits the requirements via the 'org.sqlite.tmpdir' property."
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt b/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
index ba15d80..338892d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/Constructor.kt
@@ -43,13 +43,17 @@
fun writeConstructor(outVar: String, args: String, builder: CodeBlock.Builder) {
when {
element.isConstructor() -> {
- builder.addStatement("$L = new $T($L)", outVar,
- element.enclosingTypeElement.asDeclaredType().typeName, args)
+ builder.addStatement(
+ "$L = new $T($L)", outVar,
+ element.enclosingTypeElement.asDeclaredType().typeName, args
+ )
}
element.isMethod() -> {
- builder.addStatement("$L = $T.$L($L)", outVar,
- element.enclosingTypeElement.asDeclaredType().typeName,
- element.name, args)
+ builder.addStatement(
+ "$L = $T.$L($L)", outVar,
+ element.enclosingTypeElement.asDeclaredType().typeName,
+ element.name, args
+ )
}
else -> throw IllegalStateException("Invalid constructor kind ${element.kindName()}")
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/Database.kt b/room/compiler/src/main/kotlin/androidx/room/vo/Database.kt
index e32179a..a22fb9d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/Database.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/Database.kt
@@ -49,10 +49,14 @@
}
val bundle by lazy {
- DatabaseBundle(version, identityHash, entities.map(Entity::toBundle),
- views.map(DatabaseView::toBundle),
- listOf(RoomMasterTable.CREATE_QUERY,
- RoomMasterTable.createInsertQuery(identityHash)))
+ DatabaseBundle(
+ version, identityHash, entities.map(Entity::toBundle),
+ views.map(DatabaseView::toBundle),
+ listOf(
+ RoomMasterTable.CREATE_QUERY,
+ RoomMasterTable.createInsertQuery(identityHash)
+ )
+ )
}
/**
@@ -68,28 +72,28 @@
val legacyIdentityHash: String by lazy {
val entityDescriptions = entities
- .sortedBy { it.tableName }
- .map { it.createTableQuery }
+ .sortedBy { it.tableName }
+ .map { it.createTableQuery }
val indexDescriptions = entities
- .flatMap { entity ->
- entity.indices.map { index ->
- // For legacy purposes we need to remove the later added 'IF NOT EXISTS'
- // part of the create statement, otherwise old valid legacy hashes stop
- // being accepted even though the schema has not changed. b/139306173
- if (index.unique) {
- "CREATE UNIQUE INDEX"
- } else {
- // The extra space between 'CREATE' and 'INDEX' is on purpose, this
- // is a typo we have to live with.
- "CREATE INDEX"
- } + index.createQuery(entity.tableName).substringAfter("IF NOT EXISTS")
- }
+ .flatMap { entity ->
+ entity.indices.map { index ->
+ // For legacy purposes we need to remove the later added 'IF NOT EXISTS'
+ // part of the create statement, otherwise old valid legacy hashes stop
+ // being accepted even though the schema has not changed. b/139306173
+ if (index.unique) {
+ "CREATE UNIQUE INDEX"
+ } else {
+ // The extra space between 'CREATE' and 'INDEX' is on purpose, this
+ // is a typo we have to live with.
+ "CREATE INDEX"
+ } + index.createQuery(entity.tableName).substringAfter("IF NOT EXISTS")
}
+ }
val viewDescriptions = views
- .sortedBy { it.viewName }
- .map { it.viewName + it.query.original }
+ .sortedBy { it.viewName }
+ .map { it.viewName + it.query.original }
val input = (entityDescriptions + indexDescriptions + viewDescriptions)
- .joinToString("¯\\_(ツ)_/¯")
+ .joinToString("¯\\_(ツ)_/¯")
DigestUtils.md5Hex(input)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/Entity.kt b/room/compiler/src/main/kotlin/androidx/room/vo/Entity.kt
index 5a90968..933f36a 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/Entity.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/Entity.kt
@@ -55,10 +55,12 @@
}
private fun createTableQuery(tableName: String): String {
- val definitions = (fields.map {
- val autoIncrement = primaryKey.autoGenerateId && primaryKey.fields.contains(it)
- it.databaseDefinition(autoIncrement)
- } + createPrimaryKeyDefinition() + createForeignKeyDefinitions()).filterNotNull()
+ val definitions = (
+ fields.map {
+ val autoIncrement = primaryKey.autoGenerateId && primaryKey.fields.contains(it)
+ it.databaseDefinition(autoIncrement)
+ } + createPrimaryKeyDefinition() + createForeignKeyDefinitions()
+ ).filterNotNull()
return "CREATE TABLE IF NOT EXISTS `$tableName` (${definitions.joinToString(", ")})"
}
@@ -78,28 +80,32 @@
fun shouldBeDeletedAfter(other: Entity): Boolean {
return foreignKeys.any {
it.parentTable == other.tableName &&
- ((!it.deferred && it.onDelete == ForeignKeyAction.NO_ACTION) ||
- it.onDelete == ForeignKeyAction.RESTRICT)
+ (
+ (!it.deferred && it.onDelete == ForeignKeyAction.NO_ACTION) ||
+ it.onDelete == ForeignKeyAction.RESTRICT
+ )
}
}
open fun toBundle(): EntityBundle = EntityBundle(
- tableName,
- createTableQuery(BundleUtil.TABLE_NAME_PLACEHOLDER),
- fields.map { it.toBundle() },
- primaryKey.toBundle(),
- indices.map { it.toBundle() },
- foreignKeys.map { it.toBundle() })
+ tableName,
+ createTableQuery(BundleUtil.TABLE_NAME_PLACEHOLDER),
+ fields.map { it.toBundle() },
+ primaryKey.toBundle(),
+ indices.map { it.toBundle() },
+ foreignKeys.map { it.toBundle() }
+ )
fun isUnique(columns: List<String>): Boolean {
return if (primaryKey.columnNames.size == columns.size &&
- primaryKey.columnNames.containsAll(columns)) {
+ primaryKey.columnNames.containsAll(columns)
+ ) {
true
} else {
indices.any { index ->
index.unique &&
- index.fields.size == columns.size &&
- index.columnNames.containsAll(columns)
+ index.fields.size == columns.size &&
+ index.columnNames.containsAll(columns)
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/Field.kt b/room/compiler/src/main/kotlin/androidx/room/vo/Field.kt
index a687db7..6565af1 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/Field.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/Field.kt
@@ -113,13 +113,13 @@
val getterNameWithVariations by lazy {
nameWithVariations.map { "get${it.capitalize(Locale.US)}" } +
- if (typeName == TypeName.BOOLEAN || typeName == TypeName.BOOLEAN.box()) {
- nameWithVariations.flatMap {
- listOf("is${it.capitalize(Locale.US)}", "has${it.capitalize(Locale.US)}")
- }
- } else {
- emptyList()
+ if (typeName == TypeName.BOOLEAN || typeName == TypeName.BOOLEAN.box()) {
+ nameWithVariations.flatMap {
+ listOf("is${it.capitalize(Locale.US)}", "has${it.capitalize(Locale.US)}")
}
+ } else {
+ emptyList()
+ }
}
val setterNameWithVariations by lazy {
@@ -146,14 +146,15 @@
return "`$columnName` ${(affinity ?: SQLTypeAffinity.TEXT).name}$columnSpec"
}
- fun toBundle(): FieldBundle = FieldBundle(pathWithDotNotation, columnName,
- affinity?.name ?: SQLTypeAffinity.TEXT.name, nonNull, defaultValue
+ fun toBundle(): FieldBundle = FieldBundle(
+ pathWithDotNotation, columnName,
+ affinity?.name ?: SQLTypeAffinity.TEXT.name, nonNull, defaultValue
)
companion object {
fun calcNonNull(type: XType, parent: EmbeddedField?): Boolean {
return XNullability.NONNULL == type.nullability &&
- (parent == null || parent.isNonNullRecursively())
+ (parent == null || parent.isNonNullRecursively())
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/FieldWithIndex.kt b/room/compiler/src/main/kotlin/androidx/room/vo/FieldWithIndex.kt
index 4a75db0..a880b64 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/FieldWithIndex.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/FieldWithIndex.kt
@@ -27,9 +27,11 @@
companion object {
fun byOrder(fields: List<Field>): List<FieldWithIndex> {
return fields.mapIndexed { index, field ->
- FieldWithIndex(field = field,
- indexVar = "${index + 1}",
- alwaysExists = true)
+ FieldWithIndex(
+ field = field,
+ indexVar = "${index + 1}",
+ alwaysExists = true
+ )
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/ForeignKey.kt b/room/compiler/src/main/kotlin/androidx/room/vo/ForeignKey.kt
index dc77e77..c802a99 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/ForeignKey.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/ForeignKey.kt
@@ -31,19 +31,19 @@
) : HasSchemaIdentity {
override fun getIdKey(): String {
return parentTable +
- "-${parentColumns.joinToString(",")}" +
- "-${childFields.joinToString(",") {it.columnName}}" +
- "-${onDelete.sqlName}" +
- "-${onUpdate.sqlName}" +
- "-$deferred"
+ "-${parentColumns.joinToString(",")}" +
+ "-${childFields.joinToString(",") {it.columnName}}" +
+ "-${onDelete.sqlName}" +
+ "-${onUpdate.sqlName}" +
+ "-$deferred"
}
fun databaseDefinition(): String {
return "FOREIGN KEY(${joinEscaped(childFields.map { it.columnName })})" +
- " REFERENCES `$parentTable`(${joinEscaped(parentColumns)})" +
- " ON UPDATE ${onUpdate.sqlName}" +
- " ON DELETE ${onDelete.sqlName}" +
- " ${deferredDeclaration()}"
+ " REFERENCES `$parentTable`(${joinEscaped(parentColumns)})" +
+ " ON UPDATE ${onUpdate.sqlName}" +
+ " ON DELETE ${onDelete.sqlName}" +
+ " ${deferredDeclaration()}"
}
private fun deferredDeclaration(): String {
@@ -57,8 +57,8 @@
private fun joinEscaped(values: Iterable<String>) = values.joinToString(", ") { "`$it`" }
fun toBundle(): ForeignKeyBundle = ForeignKeyBundle(
- parentTable, onDelete.sqlName, onUpdate.sqlName,
- childFields.map { it.columnName },
- parentColumns
+ parentTable, onDelete.sqlName, onUpdate.sqlName,
+ childFields.map { it.columnName },
+ parentColumns
)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/FtsEntity.kt b/room/compiler/src/main/kotlin/androidx/room/vo/FtsEntity.kt
index 0cbc0d1..bb52495 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/FtsEntity.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/FtsEntity.kt
@@ -36,8 +36,10 @@
shadowTableName: String?,
val ftsVersion: FtsVersion,
val ftsOptions: FtsOptions
-) : Entity(element, tableName, type, fields, embeddedFields, primaryKey, emptyList(), emptyList(),
- constructor, shadowTableName) {
+) : Entity(
+ element, tableName, type, fields, embeddedFields, primaryKey, emptyList(), emptyList(),
+ constructor, shadowTableName
+) {
override val createTableQuery by lazy {
createTableQuery(tableName)
@@ -47,7 +49,7 @@
fields.filterNot {
// 'rowid' primary key column and language id column are hidden columns
primaryKey.fields.isNotEmpty() && primaryKey.fields.first() == it ||
- ftsOptions.languageIdColumnName == it.columnName
+ ftsOptions.languageIdColumnName == it.columnName
}
}
@@ -86,9 +88,9 @@
private fun createTableQuery(tableName: String, includeTokenizer: Boolean = true): String {
val definitions = nonHiddenFields.map { it.databaseDefinition(false) } +
- ftsOptions.databaseDefinition(includeTokenizer)
+ ftsOptions.databaseDefinition(includeTokenizer)
return "CREATE VIRTUAL TABLE IF NOT EXISTS `$tableName` " +
- "USING ${ftsVersion.name}(${definitions.joinToString(", ")})"
+ "USING ${ftsVersion.name}(${definitions.joinToString(", ")})"
}
private fun createSyncTriggers(contentTable: String): List<String> {
@@ -105,9 +107,9 @@
tableName: String,
contentTableName: String
) = "CREATE TRIGGER IF NOT EXISTS ${createTriggerName(tableName, "BEFORE_$triggerOp")} " +
- "BEFORE $triggerOp ON `$contentTableName` BEGIN " +
- "DELETE FROM `$tableName` WHERE `docid`=OLD.`rowid`; " +
- "END"
+ "BEFORE $triggerOp ON `$contentTableName` BEGIN " +
+ "DELETE FROM `$tableName` WHERE `docid`=OLD.`rowid`; " +
+ "END"
private fun createAfterTrigger(
triggerOp: String,
@@ -115,23 +117,24 @@
contentTableName: String,
columnNames: List<String>
) = "CREATE TRIGGER IF NOT EXISTS ${createTriggerName(tableName, "AFTER_$triggerOp")} " +
- "AFTER $triggerOp ON `$contentTableName` BEGIN " +
- "INSERT INTO `$tableName`(" +
- (listOf("docid") + columnNames).joinToString(separator = ", ") { "`$it`" } + ") " +
- "VALUES (" +
- (listOf("rowid") + columnNames).joinToString(separator = ", ") { "NEW.`$it`" } + "); " +
- "END"
+ "AFTER $triggerOp ON `$contentTableName` BEGIN " +
+ "INSERT INTO `$tableName`(" +
+ (listOf("docid") + columnNames).joinToString(separator = ", ") { "`$it`" } + ") " +
+ "VALUES (" +
+ (listOf("rowid") + columnNames).joinToString(separator = ", ") { "NEW.`$it`" } + "); " +
+ "END"
// If trigger name prefix is changed be sure to update DBUtil#dropFtsSyncTriggers
private fun createTriggerName(tableName: String, triggerOp: String) =
- "room_fts_content_sync_${tableName}_$triggerOp"
+ "room_fts_content_sync_${tableName}_$triggerOp"
override fun toBundle() = FtsEntityBundle(
- tableName,
- createTableQuery(BundleUtil.TABLE_NAME_PLACEHOLDER),
- nonHiddenFields.map { it.toBundle() },
- primaryKey.toBundle(),
- ftsVersion.name,
- ftsOptions.toBundle(),
- contentSyncTriggerCreateQueries)
+ tableName,
+ createTableQuery(BundleUtil.TABLE_NAME_PLACEHOLDER),
+ nonHiddenFields.map { it.toBundle() },
+ primaryKey.toBundle(),
+ ftsVersion.name,
+ ftsOptions.toBundle(),
+ contentSyncTriggerCreateQueries
+ )
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/FtsOptions.kt b/room/compiler/src/main/kotlin/androidx/room/vo/FtsOptions.kt
index 36819e6..2738ca5 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/FtsOptions.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/FtsOptions.kt
@@ -47,10 +47,13 @@
fun databaseDefinition(includeTokenizer: Boolean = true): List<String> {
return mutableListOf<String>().apply {
- if (includeTokenizer && (tokenizer != androidx.room.FtsOptions.TOKENIZER_SIMPLE ||
- tokenizerArgs.isNotEmpty())) {
+ if (includeTokenizer && (
+ tokenizer != androidx.room.FtsOptions.TOKENIZER_SIMPLE ||
+ tokenizerArgs.isNotEmpty()
+ )
+ ) {
val tokenizeAndArgs = listOf("tokenize=$tokenizer") +
- tokenizerArgs.map { "`$it`" }
+ tokenizerArgs.map { "`$it`" }
add(tokenizeAndArgs.joinToString(separator = " "))
}
@@ -81,20 +84,22 @@
}
fun toBundle() = FtsOptionsBundle(
- tokenizer,
- tokenizerArgs,
- contentEntity?.tableName ?: "",
- languageIdColumnName,
- matchInfo.name,
- notIndexedColumns,
- prefixSizes,
- preferredOrder.name)
+ tokenizer,
+ tokenizerArgs,
+ contentEntity?.tableName ?: "",
+ languageIdColumnName,
+ matchInfo.name,
+ notIndexedColumns,
+ prefixSizes,
+ preferredOrder.name
+ )
companion object {
val defaultTokenizers = listOf(
androidx.room.FtsOptions.TOKENIZER_SIMPLE,
androidx.room.FtsOptions.TOKENIZER_PORTER,
androidx.room.FtsOptions.TOKENIZER_ICU,
- androidx.room.FtsOptions.TOKENIZER_UNICODE61)
+ androidx.room.FtsOptions.TOKENIZER_UNICODE61
+ )
}
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/Index.kt b/room/compiler/src/main/kotlin/androidx/room/vo/Index.kt
index 8d0f0718..88a8c56 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/Index.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/Index.kt
@@ -23,14 +23,14 @@
* Represents a processed index.
*/
data class Index(val name: String, val unique: Boolean, override val fields: Fields) :
- HasSchemaIdentity, HasFields {
+ HasSchemaIdentity, HasFields {
companion object {
// should match the value in TableInfo.Index.DEFAULT_PREFIX
const val DEFAULT_PREFIX = "index_"
}
constructor(name: String, unique: Boolean, fields: List<Field>) :
- this(name, unique, Fields(fields))
+ this(name, unique, Fields(fields))
override fun getIdKey() = "$unique-$name-${columnNames.joinToString(",")}"
@@ -43,9 +43,11 @@
return """
CREATE $indexSQL IF NOT EXISTS `$name`
ON `$tableName` (${columnNames.joinToString(", ") { "`$it`" }})
- """.trimIndent().replace("\n", " ")
+ """.trimIndent().replace("\n", " ")
}
- fun toBundle(): IndexBundle = IndexBundle(name, unique, columnNames,
- createQuery(BundleUtil.TABLE_NAME_PLACEHOLDER))
+ fun toBundle(): IndexBundle = IndexBundle(
+ name, unique, columnNames,
+ createQuery(BundleUtil.TABLE_NAME_PLACEHOLDER)
+ )
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/QueryMethod.kt b/room/compiler/src/main/kotlin/androidx/room/vo/QueryMethod.kt
index 8d4f906..222a715 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/QueryMethod.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/QueryMethod.kt
@@ -39,9 +39,12 @@
Pair(it, parameters.firstOrNull())
} else if (it.text.startsWith(":")) {
val subName = it.text.substring(1)
- Pair(it, parameters.firstOrNull {
- it.sqlName == subName
- })
+ Pair(
+ it,
+ parameters.firstOrNull {
+ it.sqlName == subName
+ }
+ )
} else {
Pair(it, null)
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/QueryParameter.kt b/room/compiler/src/main/kotlin/androidx/room/vo/QueryParameter.kt
index 9411598..6bf3975 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/QueryParameter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/QueryParameter.kt
@@ -23,9 +23,9 @@
* Holds the parameter for a {@link QueryMethod}.
*/
data class QueryParameter(
- // this is name seen by java
+ // this is name seen by java
val name: String,
- // this is the name used in the query. Might be different for kotlin queries
+ // this is the name used in the query. Might be different for kotlin queries
val sqlName: String,
val type: XType,
val queryParamAdapter: QueryParameterAdapter?
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/Relation.kt b/room/compiler/src/main/kotlin/androidx/room/vo/Relation.kt
index 8771777..1d2c0a2 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/Relation.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/Relation.kt
@@ -47,12 +47,14 @@
private fun createSelect(resultFields: Set<String>) = buildString {
if (junction != null) {
val resultColumns = resultFields.map { "`${entity.tableName}`.`$it` AS `$it`" } +
- "_junction.`${junction.parentField.columnName}`"
+ "_junction.`${junction.parentField.columnName}`"
append("SELECT ${resultColumns.joinToString(",")}")
append(" FROM `${junction.entity.tableName}` AS _junction")
- append(" INNER JOIN `${entity.tableName}` ON" +
+ append(
+ " INNER JOIN `${entity.tableName}` ON" +
" (_junction.`${junction.entityField.columnName}`" +
- " = `${entity.tableName}`.`${entityField.columnName}`)")
+ " = `${entity.tableName}`.`${entityField.columnName}`)"
+ )
append(" WHERE _junction.`${junction.parentField.columnName}` IN (:args)")
} else {
val resultColumns = resultFields.map { "`$it`" }.toSet() + "`${entityField.columnName}`"
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt b/room/compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt
index f182418..dc3171e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/RelationCollector.kt
@@ -68,7 +68,8 @@
fun writeInitCode(scope: CodeGenScope) {
varName = scope.getTmpVar(
- "_collection${relation.field.getPath().stripNonJava().capitalize(Locale.US)}")
+ "_collection${relation.field.getPath().stripNonJava().capitalize(Locale.US)}"
+ )
scope.builder().apply {
addStatement("final $T $L = new $T()", mapTypeName, varName, mapTypeName)
}
@@ -87,9 +88,12 @@
readKey(cursorVarName, indexVar, scope) { tmpVar ->
if (relationTypeIsCollection) {
val tmpCollectionVar = scope.getTmpVar(
- "_tmp${relation.field.name.stripNonJava().capitalize(Locale.US)}Collection")
- addStatement("$T $L = $L.get($L)", relationTypeName, tmpCollectionVar,
- varName, tmpVar)
+ "_tmp${relation.field.name.stripNonJava().capitalize(Locale.US)}Collection"
+ )
+ addStatement(
+ "$T $L = $L.get($L)", relationTypeName, tmpCollectionVar,
+ varName, tmpVar
+ )
beginControlFlow("if ($L == null)", tmpCollectionVar).apply {
addStatement("$L = new $T()", tmpCollectionVar, relationTypeName)
addStatement("$L.put($L, $L)", varName, tmpVar, tmpCollectionVar)
@@ -113,7 +117,8 @@
}?.indexVar
val tmpvarNameSuffix = if (relationTypeIsCollection) "Collection" else ""
val tmpRelationVar = scope.getTmpVar(
- "_tmp${relation.field.name.stripNonJava().capitalize(Locale.US)}$tmpvarNameSuffix")
+ "_tmp${relation.field.name.stripNonJava().capitalize(Locale.US)}$tmpvarNameSuffix"
+ )
scope.builder().apply {
addStatement("$T $L = null", relationTypeName, tmpRelationVar)
readKey(cursorVarName, indexVar, scope) { tmpVar ->
@@ -131,7 +136,7 @@
fun writeCollectionCode(scope: CodeGenScope) {
val method = scope.writer
- .getOrCreateMethod(RelationCollectorMethodWriter(this))
+ .getOrCreateMethod(RelationCollectorMethodWriter(this))
scope.builder().apply {
addStatement("$N($L)", method, varName)
}
@@ -161,11 +166,15 @@
val tmpVar = scope.getTmpVar("_tmpKey")
fun addKeyReadStatement() {
if (keyTypeName == TypeName.get(ByteBuffer::class.java)) {
- addStatement("final $T $L = $T.wrap($L.$L($L))",
- keyType, tmpVar, keyTypeName, cursorVarName, cursorGetter, indexVar)
+ addStatement(
+ "final $T $L = $T.wrap($L.$L($L))",
+ keyType, tmpVar, keyTypeName, cursorVarName, cursorGetter, indexVar
+ )
} else {
- addStatement("final $T $L = $L.$L($L)",
- keyType, tmpVar, cursorVarName, cursorGetter, indexVar)
+ addStatement(
+ "final $T $L = $L.$L($L)",
+ keyType, tmpVar, cursorVarName, cursorGetter, indexVar
+ )
}
this.postRead(tmpVar)
}
@@ -194,8 +203,10 @@
scope.builder().apply {
val itrIndexVar = "i"
val itrItemVar = scope.getTmpVar("_item")
- beginControlFlow("for (int $L = 0; $L < $L.size(); i++)",
- itrIndexVar, itrIndexVar, inputVarName).apply {
+ beginControlFlow(
+ "for (int $L = 0; $L < $L.size(); i++)",
+ itrIndexVar, itrIndexVar, inputVarName
+ ).apply {
addStatement("long $L = $L.keyAt($L)", itrItemVar, inputVarName, itrIndexVar)
addStatement("$L.bindLong($L, $L)", stmtVarName, startIndexVarName, itrItemVar)
addStatement("$L ++", startIndexVarName)
@@ -209,15 +220,17 @@
outputVarName: String,
scope: CodeGenScope
) {
- scope.builder().addStatement("final $T $L = $L.size()",
- TypeName.INT, outputVarName, inputVarName)
+ scope.builder().addStatement(
+ "final $T $L = $L.size()",
+ TypeName.INT, outputVarName, inputVarName
+ )
}
}
companion object {
private val LONG_SPARSE_ARRAY_KEY_QUERY_PARAM_ADAPTER =
- LongSparseArrayKeyQueryParameterAdapter()
+ LongSparseArrayKeyQueryParameterAdapter()
fun createCollectors(
baseContext: Context,
@@ -226,7 +239,8 @@
return relations.map { relation ->
val context = baseContext.fork(
element = relation.field.element,
- forceSuppressedWarnings = setOf(Warning.CURSOR_MISMATCH))
+ forceSuppressedWarnings = setOf(Warning.CURSOR_MISMATCH)
+ )
val affinity = affinityFor(context, relation)
val keyType = keyTypeFor(context, affinity)
val (relationTypeName, isRelationCollection) = relationTypeFor(relation)
@@ -234,14 +248,18 @@
val loadAllQuery = relation.createLoadAllSql()
val parsedQuery = SqlParser.parse(loadAllQuery)
- context.checker.check(parsedQuery.errors.isEmpty(), relation.field.element,
- parsedQuery.errors.joinToString("\n"))
+ context.checker.check(
+ parsedQuery.errors.isEmpty(), relation.field.element,
+ parsedQuery.errors.joinToString("\n")
+ )
if (parsedQuery.errors.isEmpty()) {
val resultInfo = context.databaseVerifier?.analyze(loadAllQuery)
parsedQuery.resultInfo = resultInfo
if (resultInfo?.error != null) {
- context.logger.e(relation.field.element,
- DatabaseVerificationErrors.cannotVerifyQuery(resultInfo.error))
+ context.logger.e(
+ relation.field.element,
+ DatabaseVerificationErrors.cannotVerifyQuery(resultInfo.error)
+ )
}
}
val resultInfo = parsedQuery.resultInfo
@@ -250,31 +268,36 @@
tmpMapType.rawType == CollectionTypeNames.LONG_SPARSE_ARRAY
val queryParam = if (usingLongSparseArray) {
val longSparseArrayElement = context.processingEnv
- .requireTypeElement(CollectionTypeNames.LONG_SPARSE_ARRAY)
+ .requireTypeElement(CollectionTypeNames.LONG_SPARSE_ARRAY)
QueryParameter(
- name = RelationCollectorMethodWriter.PARAM_MAP_VARIABLE,
- sqlName = RelationCollectorMethodWriter.PARAM_MAP_VARIABLE,
- type = longSparseArrayElement.asDeclaredType(),
- queryParamAdapter = LONG_SPARSE_ARRAY_KEY_QUERY_PARAM_ADAPTER
+ name = RelationCollectorMethodWriter.PARAM_MAP_VARIABLE,
+ sqlName = RelationCollectorMethodWriter.PARAM_MAP_VARIABLE,
+ type = longSparseArrayElement.asDeclaredType(),
+ queryParamAdapter = LONG_SPARSE_ARRAY_KEY_QUERY_PARAM_ADAPTER
)
} else {
val keyTypeMirror = keyTypeMirrorFor(context, affinity)
val set = context.processingEnv.requireTypeElement("java.util.Set")
val keySet = context.processingEnv.getDeclaredType(set, keyTypeMirror)
QueryParameter(
- name = RelationCollectorMethodWriter.KEY_SET_VARIABLE,
- sqlName = RelationCollectorMethodWriter.KEY_SET_VARIABLE,
- type = keySet,
- queryParamAdapter = context.typeAdapterStore.findQueryParameterAdapter(
- keySet)
+ name = RelationCollectorMethodWriter.KEY_SET_VARIABLE,
+ sqlName = RelationCollectorMethodWriter.KEY_SET_VARIABLE,
+ type = keySet,
+ queryParamAdapter = context.typeAdapterStore.findQueryParameterAdapter(
+ keySet
+ )
)
}
val queryWriter = QueryWriter(
- parameters = listOf(queryParam),
- sectionToParamMapping = listOf(Pair(parsedQuery.bindSections.first(),
- queryParam)),
- query = parsedQuery
+ parameters = listOf(queryParam),
+ sectionToParamMapping = listOf(
+ Pair(
+ parsedQuery.bindSections.first(),
+ queryParam
+ )
+ ),
+ query = parsedQuery
)
// row adapter that matches full response
@@ -282,10 +305,12 @@
return context.typeAdapterStore.findRowAdapter(relation.pojoType, parsedQuery)
}
val rowAdapter = if (relation.projection.size == 1 && resultInfo != null &&
- (resultInfo.columns.size == 1 || resultInfo.columns.size == 2)) {
+ (resultInfo.columns.size == 1 || resultInfo.columns.size == 2)
+ ) {
// check for a column adapter first
val cursorReader = context.typeAdapterStore.findCursorValueReader(
- relation.pojoType, resultInfo.columns.first().type)
+ relation.pojoType, resultInfo.columns.first().type
+ )
if (cursorReader == null) {
getDefaultRowAdapter()
} else {
@@ -296,20 +321,22 @@
}
if (rowAdapter == null) {
- context.logger.e(relation.field.element,
- cannotFindQueryResultAdapter(relation.pojoType.toString()))
+ context.logger.e(
+ relation.field.element,
+ cannotFindQueryResultAdapter(relation.pojoType.toString())
+ )
null
} else {
RelationCollector(
- relation = relation,
- affinity = affinity,
- mapTypeName = tmpMapType,
- keyTypeName = keyType,
- relationTypeName = relationTypeName,
- queryWriter = queryWriter,
- rowAdapter = rowAdapter,
- loadAllQuery = parsedQuery,
- relationTypeIsCollection = isRelationCollection
+ relation = relation,
+ affinity = affinity,
+ mapTypeName = tmpMapType,
+ keyTypeName = keyType,
+ relationTypeName = relationTypeName,
+ queryWriter = queryWriter,
+ rowAdapter = rowAdapter,
+ loadAllQuery = parsedQuery,
+ relationTypeIsCollection = isRelationCollection
)
}
}.filterNotNull()
@@ -336,29 +363,38 @@
relation.junction?.entityField?.cursorValueReader?.affinity()
return if (relation.junction != null) {
checkAffinity(childAffinity, junctionChildAffinity) {
- context.logger.w(Warning.RELATION_TYPE_MISMATCH, relation.field.element,
+ context.logger.w(
+ Warning.RELATION_TYPE_MISMATCH, relation.field.element,
relationJunctionChildAffinityMismatch(
childColumn = relation.entityField.columnName,
junctionChildColumn = relation.junction.entityField.columnName,
childAffinity = childAffinity,
- junctionChildAffinity = junctionChildAffinity))
+ junctionChildAffinity = junctionChildAffinity
+ )
+ )
}
checkAffinity(parentAffinity, junctionParentAffinity) {
- context.logger.w(Warning.RELATION_TYPE_MISMATCH, relation.field.element,
+ context.logger.w(
+ Warning.RELATION_TYPE_MISMATCH, relation.field.element,
relationJunctionParentAffinityMismatch(
parentColumn = relation.parentField.columnName,
junctionParentColumn = relation.junction.parentField.columnName,
parentAffinity = parentAffinity,
- junctionParentAffinity = junctionParentAffinity))
+ junctionParentAffinity = junctionParentAffinity
+ )
+ )
}
} else {
checkAffinity(parentAffinity, childAffinity) {
- context.logger.w(Warning.RELATION_TYPE_MISMATCH, relation.field.element,
+ context.logger.w(
+ Warning.RELATION_TYPE_MISMATCH, relation.field.element,
relationAffinityMismatch(
parentColumn = relation.parentField.columnName,
childColumn = relation.entityField.columnName,
parentAffinity = parentAffinity,
- childAffinity = childAffinity))
+ childAffinity = childAffinity
+ )
+ )
}
}
}
@@ -368,14 +404,20 @@
if (relation.field.typeName is ParameterizedTypeName) {
val paramType = relation.field.typeName as ParameterizedTypeName
val paramTypeName = if (paramType.rawType == CommonTypeNames.LIST) {
- ParameterizedTypeName.get(ClassName.get(ArrayList::class.java),
- relation.pojoTypeName)
+ ParameterizedTypeName.get(
+ ClassName.get(ArrayList::class.java),
+ relation.pojoTypeName
+ )
} else if (paramType.rawType == CommonTypeNames.SET) {
- ParameterizedTypeName.get(ClassName.get(HashSet::class.java),
- relation.pojoTypeName)
+ ParameterizedTypeName.get(
+ ClassName.get(HashSet::class.java),
+ relation.pojoTypeName
+ )
} else {
- ParameterizedTypeName.get(ClassName.get(ArrayList::class.java),
- relation.pojoTypeName)
+ ParameterizedTypeName.get(
+ ClassName.get(ArrayList::class.java),
+ relation.pojoTypeName
+ )
}
paramTypeName to true
} else {
@@ -395,16 +437,22 @@
.findTypeElement(CollectionTypeNames.ARRAY_MAP) != null
return when {
canUseLongSparseArray && affinity == SQLTypeAffinity.INTEGER -> {
- ParameterizedTypeName.get(CollectionTypeNames.LONG_SPARSE_ARRAY,
- relationTypeName)
+ ParameterizedTypeName.get(
+ CollectionTypeNames.LONG_SPARSE_ARRAY,
+ relationTypeName
+ )
}
canUseArrayMap -> {
- ParameterizedTypeName.get(CollectionTypeNames.ARRAY_MAP,
- keyType, relationTypeName)
+ ParameterizedTypeName.get(
+ CollectionTypeNames.ARRAY_MAP,
+ keyType, relationTypeName
+ )
}
else -> {
- ParameterizedTypeName.get(ClassName.get(java.util.HashMap::class.java),
- keyType, relationTypeName)
+ ParameterizedTypeName.get(
+ ClassName.get(java.util.HashMap::class.java),
+ keyType, relationTypeName
+ )
}
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt
index 46267c5a..23b04c1 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt
@@ -20,6 +20,7 @@
import androidx.room.ext.S
import androidx.room.ext.typeName
import androidx.room.compiler.processing.XProcessingEnv
+import androidx.room.compiler.processing.writeTo
import androidx.room.solver.CodeGenScope.Companion.CLASS_PROPERTY_PREFIX
import com.squareup.javapoet.AnnotationSpec
import com.squareup.javapoet.ClassName
@@ -114,15 +115,21 @@
}
fun getOrCreateField(sharedField: SharedFieldSpec): FieldSpec {
- return sharedFieldSpecs.getOrPut(sharedField.getUniqueKey(), {
- sharedField.build(this, makeUnique(sharedFieldNames, sharedField.baseName))
- })
+ return sharedFieldSpecs.getOrPut(
+ sharedField.getUniqueKey(),
+ {
+ sharedField.build(this, makeUnique(sharedFieldNames, sharedField.baseName))
+ }
+ )
}
fun getOrCreateMethod(sharedMethod: SharedMethodSpec): MethodSpec {
- return sharedMethodSpecs.getOrPut(sharedMethod.getUniqueKey(), {
- sharedMethod.build(this, makeUnique(sharedMethodNames, sharedMethod.baseName))
- })
+ return sharedMethodSpecs.getOrPut(
+ sharedMethod.getUniqueKey(),
+ {
+ sharedMethod.build(this, makeUnique(sharedMethodNames, sharedMethod.baseName))
+ }
+ )
}
abstract class SharedFieldSpec(val baseName: String, val type: TypeName) {
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
index 6dde9b3..ee30de2 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
@@ -78,13 +78,13 @@
const val GET_LIST_OF_TYPE_CONVERTERS_METHOD = "getRequiredConverters"
// TODO nothing prevents this from conflicting, we should fix.
val dbField: FieldSpec = FieldSpec
- .builder(RoomTypeNames.ROOM_DB, "__db", PRIVATE, FINAL)
- .build()
+ .builder(RoomTypeNames.ROOM_DB, "__db", PRIVATE, FINAL)
+ .build()
private fun shortcutEntityFieldNamePart(shortcutEntity: ShortcutEntity): String {
return if (shortcutEntity.isPartialEntity) {
typeNameToFieldName(shortcutEntity.pojo.typeName) + "As" +
- typeNameToFieldName(shortcutEntity.entityTypeName)
+ typeNameToFieldName(shortcutEntity.entityTypeName)
} else {
typeNameToFieldName(shortcutEntity.entityTypeName)
}
@@ -107,15 +107,15 @@
* This requires more work but creates good performance.
*/
val groupedPreparedQueries = dao.queryMethods
- .filterIsInstance<WriteQueryMethod>()
- .groupBy { it.parameters.any { it.queryParamAdapter?.isMultiple ?: true } }
+ .filterIsInstance<WriteQueryMethod>()
+ .groupBy { it.parameters.any { it.queryParamAdapter?.isMultiple ?: true } }
// queries that can be prepared ahead of time
val preparedQueries = groupedPreparedQueries[false] ?: emptyList()
// queries that must be rebuilt every single time
val oneOffPreparedQueries = groupedPreparedQueries[true] ?: emptyList()
val shortcutMethods = createInsertionMethods() +
- createDeletionMethods() + createUpdateMethods() + createTransactionMethods() +
- createPreparedQueries(preparedQueries)
+ createDeletionMethods() + createUpdateMethods() + createTransactionMethods() +
+ createPreparedQueries(preparedQueries)
builder.apply {
addOriginatingElement(dbElement)
@@ -128,7 +128,7 @@
}
addField(dbField)
val dbParam = ParameterSpec
- .builder(dao.constructorParamType ?: dbField.type, dbField.name).build()
+ .builder(dao.constructorParamType ?: dbField.type, dbField.name).build()
addMethod(createConstructor(dbParam, shortcutMethods, dao.constructorParamType != null))
@@ -191,11 +191,16 @@
val fieldSpec = getOrCreateField(PreparedStatementField(method))
val queryWriter = QueryWriter(method)
val fieldImpl = PreparedStatementWriter(queryWriter)
- .createAnonymous(this@DaoWriter, dbField)
+ .createAnonymous(this@DaoWriter, dbField)
val methodBody =
createPreparedQueryMethodBody(method, fieldSpec, queryWriter)
- PreparedStmtQuery(mapOf(PreparedStmtQuery.NO_PARAM_FIELD
- to (fieldSpec to fieldImpl)), methodBody)
+ PreparedStmtQuery(
+ mapOf(
+ PreparedStmtQuery.NO_PARAM_FIELD
+ to (fieldSpec to fieldImpl)
+ ),
+ methodBody
+ )
}
}
@@ -209,15 +214,18 @@
prepareQueryStmtBlock = {
val stmtName = getTmpVar("_stmt")
builder().apply {
- addStatement("final $T $L = $N.acquire()",
- SupportDbTypeNames.SQLITE_STMT, stmtName, preparedStmtField)
+ addStatement(
+ "final $T $L = $N.acquire()",
+ SupportDbTypeNames.SQLITE_STMT, stmtName, preparedStmtField
+ )
}
queryWriter.bindArgs(stmtName, emptyList(), this)
stmtName
},
preparedStmtField = preparedStmtField.name,
dbField = dbField,
- scope = scope)
+ scope = scope
+ )
return overrideWithoutAnnotations(method.element, declaredDao)
.addCode(scope.generate())
.build()
@@ -237,7 +245,8 @@
daoName = dao.typeName,
daoImplName = dao.implTypeName,
dbField = dbField,
- scope = scope)
+ scope = scope
+ )
return overrideWithoutAnnotations(method.element, declaredDao)
.addCode(scope.generate())
.build()
@@ -286,42 +295,49 @@
queryParam?.isString() == true -> {
roomSQLiteQueryVar = scope.getTmpVar("_statement")
shouldReleaseQuery = true
- addStatement("$T $L = $T.acquire($L, 0)",
- RoomTypeNames.ROOM_SQL_QUERY,
- roomSQLiteQueryVar,
- RoomTypeNames.ROOM_SQL_QUERY,
- queryParam.paramName)
+ addStatement(
+ "$T $L = $T.acquire($L, 0)",
+ RoomTypeNames.ROOM_SQL_QUERY,
+ roomSQLiteQueryVar,
+ RoomTypeNames.ROOM_SQL_QUERY,
+ queryParam.paramName
+ )
}
queryParam?.isSupportQuery() == true -> {
shouldReleaseQuery = false
roomSQLiteQueryVar = scope.getTmpVar("_internalQuery")
// move it to a final variable so that the generated code can use it inside
// callback blocks in java 7
- addStatement("final $T $L = $N",
- queryParam.type,
- roomSQLiteQueryVar,
- queryParam.paramName)
+ addStatement(
+ "final $T $L = $N",
+ queryParam.type,
+ roomSQLiteQueryVar,
+ queryParam.paramName
+ )
}
else -> {
// try to generate compiling code. we would've already reported this error
roomSQLiteQueryVar = scope.getTmpVar("_statement")
shouldReleaseQuery = false
- addStatement("$T $L = $T.acquire($L, 0)",
- RoomTypeNames.ROOM_SQL_QUERY,
- roomSQLiteQueryVar,
- RoomTypeNames.ROOM_SQL_QUERY,
- "missing query parameter")
+ addStatement(
+ "$T $L = $T.acquire($L, 0)",
+ RoomTypeNames.ROOM_SQL_QUERY,
+ roomSQLiteQueryVar,
+ RoomTypeNames.ROOM_SQL_QUERY,
+ "missing query parameter"
+ )
}
}
if (method.returnsValue) {
// don't generate code because it will create 1 more error. The original error is
// already reported by the processor.
method.queryResultBinder.convertAndReturn(
- roomSQLiteQueryVar = roomSQLiteQueryVar,
- canReleaseQuery = shouldReleaseQuery,
- dbField = dbField,
- inTransaction = method.inTransaction,
- scope = scope)
+ roomSQLiteQueryVar = roomSQLiteQueryVar,
+ canReleaseQuery = shouldReleaseQuery,
+ dbField = dbField,
+ inTransaction = method.inTransaction,
+ scope = scope
+ )
}
addCode(scope.builder().build())
}.build()
@@ -339,22 +355,24 @@
*/
private fun createInsertionMethods(): List<PreparedStmtQuery> {
return dao.insertionMethods
- .map { insertionMethod ->
- val onConflict = OnConflictProcessor.onConflictText(insertionMethod.onConflict)
- val entities = insertionMethod.entities
+ .map { insertionMethod ->
+ val onConflict = OnConflictProcessor.onConflictText(insertionMethod.onConflict)
+ val entities = insertionMethod.entities
- val fields = entities.mapValues {
- val spec = getOrCreateField(InsertionMethodField(it.value, onConflict))
- val impl = EntityInsertionAdapterWriter.create(it.value, onConflict)
- .createAnonymous(this@DaoWriter, dbField.name)
- spec to impl
- }
- val methodImpl = overrideWithoutAnnotations(insertionMethod.element,
- declaredDao).apply {
- addCode(createInsertionMethodBody(insertionMethod, fields))
- }.build()
- PreparedStmtQuery(fields, methodImpl)
+ val fields = entities.mapValues {
+ val spec = getOrCreateField(InsertionMethodField(it.value, onConflict))
+ val impl = EntityInsertionAdapterWriter.create(it.value, onConflict)
+ .createAnonymous(this@DaoWriter, dbField.name)
+ spec to impl
}
+ val methodImpl = overrideWithoutAnnotations(
+ insertionMethod.element,
+ declaredDao
+ ).apply {
+ addCode(createInsertionMethodBody(insertionMethod, fields))
+ }.build()
+ PreparedStmtQuery(fields, methodImpl)
+ }
}
private fun createInsertionMethodBody(
@@ -368,10 +386,10 @@
val scope = CodeGenScope(this)
method.methodBinder.convertAndReturn(
- parameters = method.parameters,
- insertionAdapters = insertionAdapters,
- dbField = dbField,
- scope = scope
+ parameters = method.parameters,
+ insertionAdapters = insertionAdapters,
+ dbField = dbField,
+ scope = scope
)
return scope.builder().build()
}
@@ -382,7 +400,7 @@
private fun createDeletionMethods(): List<PreparedStmtQuery> {
return createShortcutMethods(dao.deletionMethods, "deletion") { _, entity ->
EntityDeletionAdapterWriter.create(entity)
- .createAnonymous(this@DaoWriter, dbField.name)
+ .createAnonymous(this@DaoWriter, dbField.name)
}
}
@@ -393,7 +411,7 @@
return createShortcutMethods(dao.updateMethods, "update") { update, entity ->
val onConflict = OnConflictProcessor.onConflictText(update.onConflictStrategy)
EntityUpdateAdapterWriter.create(entity, onConflict)
- .createAnonymous(this@DaoWriter, dbField.name)
+ .createAnonymous(this@DaoWriter, dbField.name)
}
}
@@ -430,10 +448,10 @@
val scope = CodeGenScope(this)
method.methodBinder.convertAndReturn(
- parameters = method.parameters,
- adapters = adapters,
- dbField = dbField,
- scope = scope
+ parameters = method.parameters,
+ adapters = adapters,
+ dbField = dbField,
+ scope = scope
)
return scope.builder().build()
}
@@ -457,7 +475,8 @@
},
preparedStmtField = null,
dbField = dbField,
- scope = scope)
+ scope = scope
+ )
return scope.generate()
}
@@ -468,11 +487,12 @@
val roomSQLiteQueryVar = scope.getTmpVar("_statement")
queryWriter.prepareReadAndBind(sqlVar, roomSQLiteQueryVar, scope)
method.queryResultBinder.convertAndReturn(
- roomSQLiteQueryVar = roomSQLiteQueryVar,
- canReleaseQuery = true,
- dbField = dbField,
- inTransaction = method.inTransaction,
- scope = scope)
+ roomSQLiteQueryVar = roomSQLiteQueryVar,
+ canReleaseQuery = true,
+ dbField = dbField,
+ inTransaction = method.inTransaction,
+ scope = scope
+ )
return scope.builder().build()
}
@@ -485,7 +505,8 @@
methodName = method.element.name,
returnType = method.element.returnType,
parameterNames = method.element.parameters.map { it.name },
- scope = scope)
+ scope = scope
+ )
addCode(scope.builder().build())
}.build()
}
@@ -541,7 +562,8 @@
) : SharedFieldSpec(
baseName = "insertionAdapterOf${shortcutEntityFieldNamePart(shortcutEntity)}",
type = ParameterizedTypeName.get(
- RoomTypeNames.INSERTION_ADAPTER, shortcutEntity.pojo.typeName)
+ RoomTypeNames.INSERTION_ADAPTER, shortcutEntity.pojo.typeName
+ )
) {
override fun getUniqueKey(): String {
return "${shortcutEntity.pojo.typeName}-${shortcutEntity.entityTypeName}$onConflictText"
@@ -558,7 +580,8 @@
) : SharedFieldSpec(
baseName = "${methodPrefix}AdapterOf${shortcutEntityFieldNamePart(shortcutEntity)}",
type = ParameterizedTypeName.get(
- RoomTypeNames.DELETE_OR_UPDATE_ADAPTER, shortcutEntity.pojo.typeName)
+ RoomTypeNames.DELETE_OR_UPDATE_ADAPTER, shortcutEntity.pojo.typeName
+ )
) {
override fun prepare(writer: ClassWriter, builder: FieldSpec.Builder) {
builder.addModifiers(PRIVATE, FINAL)
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
index 6b07453..9902227 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
@@ -72,20 +72,22 @@
return MethodSpec.methodBuilder("getRequiredTypeConverters").apply {
addAnnotation(Override::class.java)
addModifiers(PROTECTED)
- returns(ParameterizedTypeName.get(
- CommonTypeNames.MAP,
+ returns(
ParameterizedTypeName.get(
- ClassName.get(Class::class.java),
- WildcardTypeName.subtypeOf(Object::class.java)
- ),
- ParameterizedTypeName.get(
- CommonTypeNames.LIST,
+ CommonTypeNames.MAP,
ParameterizedTypeName.get(
ClassName.get(Class::class.java),
WildcardTypeName.subtypeOf(Object::class.java)
+ ),
+ ParameterizedTypeName.get(
+ CommonTypeNames.LIST,
+ ParameterizedTypeName.get(
+ ClassName.get(Class::class.java),
+ WildcardTypeName.subtypeOf(Object::class.java)
+ )
)
)
- ))
+ )
val typeConvertersVar = scope.getTmpVar("_typeConvertersMap")
val typeConvertersTypeName = ParameterizedTypeName.get(
ClassName.get(HashMap::class.java),
@@ -108,11 +110,13 @@
typeConvertersTypeName
)
database.daoMethods.forEach {
- addStatement("$L.put($T.class, $T.$L())",
- typeConvertersVar,
- it.dao.typeName,
- it.dao.implTypeName,
- DaoWriter.GET_LIST_OF_TYPE_CONVERTERS_METHOD)
+ addStatement(
+ "$L.put($T.class, $T.$L())",
+ typeConvertersVar,
+ it.dao.typeName,
+ it.dao.implTypeName,
+ DaoWriter.GET_LIST_OF_TYPE_CONVERTERS_METHOD
+ )
}
addStatement("return $L", typeConvertersVar)
}.build()
@@ -123,12 +127,16 @@
return MethodSpec.methodBuilder("clearAllTables").apply {
addStatement("super.assertNotMainThread()")
val dbVar = scope.getTmpVar("_db")
- addStatement("final $T $L = super.getOpenHelper().getWritableDatabase()",
- SupportDbTypeNames.DB, dbVar)
+ addStatement(
+ "final $T $L = super.getOpenHelper().getWritableDatabase()",
+ SupportDbTypeNames.DB, dbVar
+ )
val deferVar = scope.getTmpVar("_supportsDeferForeignKeys")
if (database.enableForeignKeys) {
- addStatement("boolean $L = $L.VERSION.SDK_INT >= $L.VERSION_CODES.LOLLIPOP",
- deferVar, AndroidTypeNames.BUILD, AndroidTypeNames.BUILD)
+ addStatement(
+ "boolean $L = $L.VERSION.SDK_INT >= $L.VERSION_CODES.LOLLIPOP",
+ deferVar, AndroidTypeNames.BUILD, AndroidTypeNames.BUILD
+ )
}
addAnnotation(Override::class.java)
addModifiers(PUBLIC)
@@ -177,8 +185,10 @@
addModifiers(PROTECTED)
returns(RoomTypeNames.INVALIDATION_TRACKER)
val shadowTablesVar = "_shadowTablesMap"
- val shadowTablesTypeName = ParameterizedTypeName.get(HashMap::class.typeName,
- CommonTypeNames.STRING, CommonTypeNames.STRING)
+ val shadowTablesTypeName = ParameterizedTypeName.get(
+ HashMap::class.typeName,
+ CommonTypeNames.STRING, CommonTypeNames.STRING
+ )
val tableNames = database.entities.joinToString(",") {
"\"${it.tableName}\""
}
@@ -187,32 +197,48 @@
}.map {
it.tableName to it.shadowTableName
}
- addStatement("final $T $L = new $T($L)", shadowTablesTypeName, shadowTablesVar,
- shadowTablesTypeName, shadowTableNames.size)
+ addStatement(
+ "final $T $L = new $T($L)", shadowTablesTypeName, shadowTablesVar,
+ shadowTablesTypeName, shadowTableNames.size
+ )
shadowTableNames.forEach { (tableName, shadowTableName) ->
addStatement("$L.put($S, $S)", shadowTablesVar, tableName, shadowTableName)
}
val viewTablesVar = scope.getTmpVar("_viewTables")
- val tablesType = ParameterizedTypeName.get(HashSet::class.typeName,
- CommonTypeNames.STRING)
- val viewTablesType = ParameterizedTypeName.get(HashMap::class.typeName,
- CommonTypeNames.STRING,
- ParameterizedTypeName.get(CommonTypeNames.SET,
- CommonTypeNames.STRING))
- addStatement("$T $L = new $T($L)", viewTablesType, viewTablesVar, viewTablesType,
- database.views.size)
+ val tablesType = ParameterizedTypeName.get(
+ HashSet::class.typeName,
+ CommonTypeNames.STRING
+ )
+ val viewTablesType = ParameterizedTypeName.get(
+ HashMap::class.typeName,
+ CommonTypeNames.STRING,
+ ParameterizedTypeName.get(
+ CommonTypeNames.SET,
+ CommonTypeNames.STRING
+ )
+ )
+ addStatement(
+ "$T $L = new $T($L)", viewTablesType, viewTablesVar, viewTablesType,
+ database.views.size
+ )
for (view in database.views) {
val tablesVar = scope.getTmpVar("_tables")
- addStatement("$T $L = new $T($L)", tablesType, tablesVar, tablesType,
- view.tables.size)
+ addStatement(
+ "$T $L = new $T($L)", tablesType, tablesVar, tablesType,
+ view.tables.size
+ )
for (table in view.tables) {
addStatement("$L.add($S)", tablesVar, table)
}
- addStatement("$L.put($S, $L)", viewTablesVar,
- view.viewName.toLowerCase(Locale.US), tablesVar)
+ addStatement(
+ "$L.put($S, $L)", viewTablesVar,
+ view.viewName.toLowerCase(Locale.US), tablesVar
+ )
}
- addStatement("return new $T(this, $L, $L, $L)",
- RoomTypeNames.INVALIDATION_TRACKER, shadowTablesVar, viewTablesVar, tableNames)
+ addStatement(
+ "return new $T(this, $L, $L, $L)",
+ RoomTypeNames.INVALIDATION_TRACKER, shadowTablesVar, viewTablesVar, tableNames
+ )
}.build()
}
@@ -222,8 +248,10 @@
database.daoMethods.forEach { method ->
val name = method.dao.typeName.simpleName().decapitalize(Locale.US).stripNonJava()
val fieldName = scope.getTmpVar("_$name")
- val field = FieldSpec.builder(method.dao.typeName, fieldName,
- PRIVATE, VOLATILE).build()
+ val field = FieldSpec.builder(
+ method.dao.typeName, fieldName,
+ PRIVATE, VOLATILE
+ ).build()
addField(field)
addMethod(createDaoGetter(field, method))
}
@@ -259,14 +287,16 @@
addAnnotation(Override::class.java)
returns(SupportDbTypeNames.SQLITE_OPEN_HELPER)
- val configParam = ParameterSpec.builder(RoomTypeNames.ROOM_DB_CONFIG,
- "configuration").build()
+ val configParam = ParameterSpec.builder(
+ RoomTypeNames.ROOM_DB_CONFIG,
+ "configuration"
+ ).build()
addParameter(configParam)
val openHelperVar = scope.getTmpVar("_helper")
val openHelperCode = scope.fork()
SQLiteOpenHelperWriter(database)
- .write(openHelperVar, configParam, openHelperCode)
+ .write(openHelperVar, configParam, openHelperCode)
addCode(openHelperCode.builder().build())
addStatement("return $L", openHelperVar)
}.build()
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/EntityCursorConverterWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/EntityCursorConverterWriter.kt
index 9a3b80f..da0f924 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/EntityCursorConverterWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/EntityCursorConverterWriter.kt
@@ -34,7 +34,8 @@
import javax.lang.model.element.Modifier.PRIVATE
class EntityCursorConverterWriter(val entity: Entity) : ClassWriter.SharedMethodSpec(
- "entityCursorConverter_${entity.typeName.toString().stripNonJava()}") {
+ "entityCursorConverter_${entity.typeName.toString().stripNonJava()}"
+) {
override fun getUniqueKey(): String {
return "generic_entity_converter_of_${entity.element.qualifiedName}"
}
@@ -42,7 +43,7 @@
override fun prepare(methodName: String, writer: ClassWriter, builder: MethodSpec.Builder) {
builder.apply {
val cursorParam = ParameterSpec
- .builder(AndroidTypeNames.CURSOR, "cursor").build()
+ .builder(AndroidTypeNames.CURSOR, "cursor").build()
addParameter(cursorParam)
addModifiers(PRIVATE)
returns(entity.typeName)
@@ -57,20 +58,26 @@
scope.builder().addStatement("final $T $L", entity.typeName, entityVar)
val fieldsWithIndices = entity.fields.map {
val indexVar = scope.getTmpVar(
- "_cursorIndexOf${it.name.stripNonJava().capitalize(Locale.US)}")
- scope.builder().addStatement("final $T $L = $N.getColumnIndex($S)",
- TypeName.INT, indexVar, cursorParam, it.columnName)
- FieldWithIndex(field = it,
- indexVar = indexVar,
- alwaysExists = false)
+ "_cursorIndexOf${it.name.stripNonJava().capitalize(Locale.US)}"
+ )
+ scope.builder().addStatement(
+ "final $T $L = $N.getColumnIndex($S)",
+ TypeName.INT, indexVar, cursorParam, it.columnName
+ )
+ FieldWithIndex(
+ field = it,
+ indexVar = indexVar,
+ alwaysExists = false
+ )
}
FieldReadWriteWriter.readFromCursor(
- outVar = entityVar,
- outPojo = entity,
- cursorVar = cursorParam.name,
- fieldsWithIndices = fieldsWithIndices,
- relationCollectors = emptyList(), // no relationship for entities
- scope = scope)
+ outVar = entityVar,
+ outPojo = entity,
+ cursorVar = cursorParam.name,
+ fieldsWithIndices = fieldsWithIndices,
+ relationCollectors = emptyList(), // no relationship for entities
+ scope = scope
+ )
addStatement("return $L", entityVar)
}
return scope.builder().build()
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/EntityDeletionAdapterWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/EntityDeletionAdapterWriter.kt
index 72de740..9be1753 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/EntityDeletionAdapterWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/EntityDeletionAdapterWriter.kt
@@ -49,41 +49,55 @@
return EntityDeletionAdapterWriter(
tableName = entity.tableName,
pojoTypeName = entity.pojo.typeName,
- fields = fieldsToUse)
+ fields = fieldsToUse
+ )
}
}
fun createAnonymous(classWriter: ClassWriter, dbParam: String): TypeSpec {
@Suppress("RemoveSingleExpressionStringTemplate")
return TypeSpec.anonymousClassBuilder("$L", dbParam).apply {
- superclass(ParameterizedTypeName.get(RoomTypeNames.DELETE_OR_UPDATE_ADAPTER,
- pojoTypeName)
+ superclass(
+ ParameterizedTypeName.get(
+ RoomTypeNames.DELETE_OR_UPDATE_ADAPTER,
+ pojoTypeName
+ )
)
- addMethod(MethodSpec.methodBuilder("createQuery").apply {
- addAnnotation(Override::class.java)
- returns(ClassName.get("java.lang", "String"))
- addModifiers(PUBLIC)
- val query = "DELETE FROM `$tableName` WHERE " +
+ addMethod(
+ MethodSpec.methodBuilder("createQuery").apply {
+ addAnnotation(Override::class.java)
+ returns(ClassName.get("java.lang", "String"))
+ addModifiers(PUBLIC)
+ val query = "DELETE FROM `$tableName` WHERE " +
fields.columnNames.joinToString(" AND ") { "`$it` = ?" }
- addStatement("return $S", query)
- }.build())
- addMethod(MethodSpec.methodBuilder("bind").apply {
- val bindScope = CodeGenScope(classWriter)
- addAnnotation(Override::class.java)
- val stmtParam = "stmt"
- addParameter(ParameterSpec.builder(SupportDbTypeNames.SQLITE_STMT,
- stmtParam).build())
- val valueParam = "value"
- addParameter(ParameterSpec.builder(pojoTypeName, valueParam).build())
- returns(TypeName.VOID)
- addModifiers(PUBLIC)
- val mapped = FieldWithIndex.byOrder(fields)
- FieldReadWriteWriter.bindToStatement(ownerVar = valueParam,
+ addStatement("return $S", query)
+ }.build()
+ )
+ addMethod(
+ MethodSpec.methodBuilder("bind").apply {
+ val bindScope = CodeGenScope(classWriter)
+ addAnnotation(Override::class.java)
+ val stmtParam = "stmt"
+ addParameter(
+ ParameterSpec.builder(
+ SupportDbTypeNames.SQLITE_STMT,
+ stmtParam
+ ).build()
+ )
+ val valueParam = "value"
+ addParameter(ParameterSpec.builder(pojoTypeName, valueParam).build())
+ returns(TypeName.VOID)
+ addModifiers(PUBLIC)
+ val mapped = FieldWithIndex.byOrder(fields)
+ FieldReadWriteWriter.bindToStatement(
+ ownerVar = valueParam,
stmtParamVar = stmtParam,
fieldsWithIndices = mapped,
- scope = bindScope)
- addCode(bindScope.builder().build())
- }.build())
+ scope = bindScope
+ )
+ addCode(bindScope.builder().build())
+ }.build()
+ )
}.build()
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/EntityInsertionAdapterWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/EntityInsertionAdapterWriter.kt
index 0878fd6..27fb45e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/EntityInsertionAdapterWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/EntityInsertionAdapterWriter.kt
@@ -61,7 +61,8 @@
tableName = entity.tableName,
pojo = entity.pojo,
primitiveAutoGenerateColumn = primitiveAutoGenerateField?.columnName,
- onConflict = onConflict)
+ onConflict = onConflict
+ )
}
}
@@ -69,44 +70,54 @@
@Suppress("RemoveSingleExpressionStringTemplate")
return TypeSpec.anonymousClassBuilder("$L", dbParam).apply {
superclass(ParameterizedTypeName.get(RoomTypeNames.INSERTION_ADAPTER, pojo.typeName))
- addMethod(MethodSpec.methodBuilder("createQuery").apply {
- addAnnotation(Override::class.java)
- addModifiers(PUBLIC)
- returns(ClassName.get("java.lang", "String"))
- val query = buildString {
- append("INSERT OR $onConflict INTO `$tableName`")
- append(" (${pojo.columnNames.joinToString(",") { "`$it`" }})")
- append(" VALUES (")
- append(pojo.fields.joinToString(",") {
- if (it.columnName == primitiveAutoGenerateColumn) {
- "nullif(?, 0)"
- } else {
- "?"
+ addMethod(
+ MethodSpec.methodBuilder("createQuery").apply {
+ addAnnotation(Override::class.java)
+ addModifiers(PUBLIC)
+ returns(ClassName.get("java.lang", "String"))
+ val query = buildString {
+ append("INSERT OR $onConflict INTO `$tableName`")
+ append(" (${pojo.columnNames.joinToString(",") { "`$it`" }})")
+ append(" VALUES (")
+ append(
+ pojo.fields.joinToString(",") {
+ if (it.columnName == primitiveAutoGenerateColumn) {
+ "nullif(?, 0)"
+ } else {
+ "?"
+ }
}
- })
- append(")")
- }
- addStatement("return $S", query)
- }.build())
- addMethod(MethodSpec.methodBuilder("bind").apply {
- val bindScope = CodeGenScope(classWriter)
- addAnnotation(Override::class.java)
- addModifiers(PUBLIC)
- returns(TypeName.VOID)
- val stmtParam = "stmt"
- addParameter(ParameterSpec.builder(SupportDbTypeNames.SQLITE_STMT,
- stmtParam).build())
- val valueParam = "value"
- addParameter(ParameterSpec.builder(pojo.typeName, valueParam).build())
- val mapped = FieldWithIndex.byOrder(pojo.fields)
- FieldReadWriteWriter.bindToStatement(
+ )
+ append(")")
+ }
+ addStatement("return $S", query)
+ }.build()
+ )
+ addMethod(
+ MethodSpec.methodBuilder("bind").apply {
+ val bindScope = CodeGenScope(classWriter)
+ addAnnotation(Override::class.java)
+ addModifiers(PUBLIC)
+ returns(TypeName.VOID)
+ val stmtParam = "stmt"
+ addParameter(
+ ParameterSpec.builder(
+ SupportDbTypeNames.SQLITE_STMT,
+ stmtParam
+ ).build()
+ )
+ val valueParam = "value"
+ addParameter(ParameterSpec.builder(pojo.typeName, valueParam).build())
+ val mapped = FieldWithIndex.byOrder(pojo.fields)
+ FieldReadWriteWriter.bindToStatement(
ownerVar = valueParam,
stmtParamVar = stmtParam,
fieldsWithIndices = mapped,
scope = bindScope
- )
- addCode(bindScope.builder().build())
- }.build())
+ )
+ addCode(bindScope.builder().build())
+ }.build()
+ )
}.build()
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/EntityUpdateAdapterWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/EntityUpdateAdapterWriter.kt
index ef9a6e5..bc8422e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/EntityUpdateAdapterWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/EntityUpdateAdapterWriter.kt
@@ -42,59 +42,73 @@
) {
companion object {
fun create(entity: ShortcutEntity, onConflict: String) =
- EntityUpdateAdapterWriter(
- tableName = entity.tableName,
- pojo = entity.pojo,
- primaryKeyFields = entity.primaryKey.fields,
- onConflict = onConflict)
+ EntityUpdateAdapterWriter(
+ tableName = entity.tableName,
+ pojo = entity.pojo,
+ primaryKeyFields = entity.primaryKey.fields,
+ onConflict = onConflict
+ )
}
fun createAnonymous(classWriter: ClassWriter, dbParam: String): TypeSpec {
@Suppress("RemoveSingleExpressionStringTemplate")
return TypeSpec.anonymousClassBuilder("$L", dbParam).apply {
- superclass(ParameterizedTypeName.get(RoomTypeNames.DELETE_OR_UPDATE_ADAPTER,
- pojo.typeName)
+ superclass(
+ ParameterizedTypeName.get(
+ RoomTypeNames.DELETE_OR_UPDATE_ADAPTER,
+ pojo.typeName
+ )
)
- addMethod(MethodSpec.methodBuilder("createQuery").apply {
- addAnnotation(Override::class.java)
- addModifiers(PUBLIC)
- returns(ClassName.get("java.lang", "String"))
- val query = "UPDATE OR $onConflict `$tableName` SET " +
+ addMethod(
+ MethodSpec.methodBuilder("createQuery").apply {
+ addAnnotation(Override::class.java)
+ addModifiers(PUBLIC)
+ returns(ClassName.get("java.lang", "String"))
+ val query = "UPDATE OR $onConflict `$tableName` SET " +
pojo.columnNames.joinToString(",") { "`$it` = ?" } + " WHERE " +
primaryKeyFields.columnNames.joinToString(" AND ") { "`$it` = ?" }
- addStatement("return $S", query)
- }.build())
- addMethod(MethodSpec.methodBuilder("bind").apply {
- val bindScope = CodeGenScope(classWriter)
- addAnnotation(Override::class.java)
- addModifiers(PUBLIC)
- returns(TypeName.VOID)
- val stmtParam = "stmt"
- addParameter(ParameterSpec.builder(SupportDbTypeNames.SQLITE_STMT,
- stmtParam).build())
- val valueParam = "value"
- addParameter(ParameterSpec.builder(pojo.typeName, valueParam).build())
- val mappedField = FieldWithIndex.byOrder(pojo.fields)
- FieldReadWriteWriter.bindToStatement(
+ addStatement("return $S", query)
+ }.build()
+ )
+ addMethod(
+ MethodSpec.methodBuilder("bind").apply {
+ val bindScope = CodeGenScope(classWriter)
+ addAnnotation(Override::class.java)
+ addModifiers(PUBLIC)
+ returns(TypeName.VOID)
+ val stmtParam = "stmt"
+ addParameter(
+ ParameterSpec.builder(
+ SupportDbTypeNames.SQLITE_STMT,
+ stmtParam
+ ).build()
+ )
+ val valueParam = "value"
+ addParameter(ParameterSpec.builder(pojo.typeName, valueParam).build())
+ val mappedField = FieldWithIndex.byOrder(pojo.fields)
+ FieldReadWriteWriter.bindToStatement(
ownerVar = valueParam,
stmtParamVar = stmtParam,
fieldsWithIndices = mappedField,
scope = bindScope
- )
- val pkeyStart = pojo.fields.size
- val mappedPrimaryKeys = primaryKeyFields.mapIndexed { index, field ->
- FieldWithIndex(field = field,
+ )
+ val pkeyStart = pojo.fields.size
+ val mappedPrimaryKeys = primaryKeyFields.mapIndexed { index, field ->
+ FieldWithIndex(
+ field = field,
indexVar = "${pkeyStart + index + 1}",
- alwaysExists = true)
- }
- FieldReadWriteWriter.bindToStatement(
+ alwaysExists = true
+ )
+ }
+ FieldReadWriteWriter.bindToStatement(
ownerVar = valueParam,
stmtParamVar = stmtParam,
fieldsWithIndices = mappedPrimaryKeys,
scope = bindScope
- )
- addCode(bindScope.builder().build())
- }.build())
+ )
+ addCode(bindScope.builder().build())
+ }.build()
+ )
}.build()
}
}
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 8296746..b0d477e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt
@@ -74,9 +74,13 @@
val rootNode = Node(rootVar, null)
rootNode.directFields = fieldsWithIndices.filter { it.field.parent == null }
val parentNodes = allParents.associate {
- Pair(it, Node(
+ Pair(
+ it,
+ Node(
varName = scope.getTmpVar("_tmp${it.field.name.capitalize(Locale.US)}"),
- fieldParent = it))
+ fieldParent = it
+ )
+ )
}
parentNodes.values.forEach { node ->
val fieldParent = node.fieldParent!!
@@ -101,9 +105,9 @@
fun bindWithDescendants() {
node.directFields.forEach {
FieldReadWriteWriter(it).bindToStatement(
- ownerVar = node.varName,
- stmtParamVar = stmtParamVar,
- scope = scope
+ ownerVar = node.varName,
+ stmtParamVar = stmtParamVar,
+ scope = scope
)
}
node.subNodes.forEach(::visitNode)
@@ -112,9 +116,9 @@
val fieldParent = node.fieldParent
if (fieldParent != null) {
fieldParent.getter.writeGet(
- ownerVar = node.parentNode!!.varName,
- outVar = node.varName,
- builder = scope.builder()
+ ownerVar = node.parentNode!!.varName,
+ outVar = node.varName,
+ builder = scope.builder()
)
scope.builder().apply {
beginControlFlow("if($L != null)", node.varName).apply {
@@ -193,7 +197,8 @@
FieldReadWriteWriter(fwi).readIntoTmpVar(
cursorVar,
fwi.field.setter.type.typeName,
- scope)
+ scope
+ )
}
// read decomposed fields (e.g. embedded)
node.subNodes.forEach(::visitNode)
@@ -202,37 +207,43 @@
relation.field.parent === fieldParent
}.associate {
it.writeReadCollectionIntoTmpVar(
- cursorVarName = cursorVar,
- fieldsWithIndices = fieldsWithIndices,
- scope = scope)
+ cursorVarName = cursorVar,
+ fieldsWithIndices = fieldsWithIndices,
+ scope = scope
+ )
}
// construct the object
if (fieldParent != null) {
- construct(outVar = node.varName,
- constructor = fieldParent.pojo.constructor,
- typeName = fieldParent.field.typeName,
- localEmbeddeds = node.subNodes,
- localRelations = relationFields,
- localVariableNames = constructorFields,
- scope = scope)
+ construct(
+ outVar = node.varName,
+ constructor = fieldParent.pojo.constructor,
+ typeName = fieldParent.field.typeName,
+ localEmbeddeds = node.subNodes,
+ localRelations = relationFields,
+ localVariableNames = constructorFields,
+ scope = scope
+ )
} else {
- construct(outVar = node.varName,
- constructor = outPojo.constructor,
- typeName = outPojo.typeName,
- localEmbeddeds = node.subNodes,
- localRelations = relationFields,
- localVariableNames = constructorFields,
- scope = scope)
+ construct(
+ outVar = node.varName,
+ constructor = outPojo.constructor,
+ typeName = outPojo.typeName,
+ localEmbeddeds = node.subNodes,
+ localRelations = relationFields,
+ localVariableNames = constructorFields,
+ scope = scope
+ )
}
// ready any field that was not part of the constructor
node.directFields.filterNot {
it.field.setter.callType == CallType.CONSTRUCTOR
}.forEach { fwi ->
FieldReadWriteWriter(fwi).readFromCursor(
- ownerVar = node.varName,
- cursorVar = cursorVar,
- scope = scope)
+ ownerVar = node.varName,
+ cursorVar = cursorVar,
+ scope = scope
+ )
}
// assign sub nodes to fields if they were not part of the constructor.
node.subNodes.mapNotNull {
@@ -244,18 +255,20 @@
}
}.forEach { (varName, setter) ->
setter.writeSet(
- ownerVar = node.varName,
- inVar = varName,
- builder = scope.builder())
+ ownerVar = node.varName,
+ inVar = varName,
+ builder = scope.builder()
+ )
}
// assign relation fields that were not part of the constructor
relationFields.filterNot { (_, field) ->
field.setter.callType == CallType.CONSTRUCTOR
}.forEach { (varName, field) ->
field.setter.writeSet(
- ownerVar = node.varName,
- inVar = varName,
- builder = scope.builder())
+ ownerVar = node.varName,
+ inVar = varName,
+ builder = scope.builder()
+ )
}
}
if (fieldParent == null) {
@@ -264,8 +277,10 @@
readNode()
} else {
// always declare, we'll set below
- scope.builder().addStatement("final $T $L", fieldParent.pojo.typeName,
- node.varName)
+ scope.builder().addStatement(
+ "final $T $L", fieldParent.pojo.typeName,
+ node.varName
+ )
if (fieldParent.nonNull) {
readNode()
} else {
@@ -322,12 +337,15 @@
scope.builder().apply {
when (field.setter.callType) {
CallType.FIELD -> {
- reader.readFromCursor("$ownerVar.${field.setter.name}", cursorVar,
- indexVar, scope)
+ reader.readFromCursor(
+ "$ownerVar.${field.setter.name}", cursorVar,
+ indexVar, scope
+ )
}
CallType.METHOD -> {
val tmpField = scope.getTmpVar(
- "_tmp${field.name.capitalize(Locale.US)}")
+ "_tmp${field.name.capitalize(Locale.US)}"
+ )
addStatement("final $T $L", field.setter.type.typeName, tmpField)
reader.readFromCursor(tmpField, cursorVar, indexVar, scope)
addStatement("$L.$L($L)", ownerVar, field.setter.name, tmpField)
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/FtsTableInfoValidationWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/FtsTableInfoValidationWriter.kt
index e76424b..819906a 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/FtsTableInfoValidationWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/FtsTableInfoValidationWriter.kt
@@ -36,29 +36,39 @@
val expectedInfoVar = scope.getTmpVar("_info$suffix")
scope.builder().apply {
val columnListVar = scope.getTmpVar("_columns$suffix")
- val columnListType = ParameterizedTypeName.get(HashSet::class.typeName,
- CommonTypeNames.STRING)
+ val columnListType = ParameterizedTypeName.get(
+ HashSet::class.typeName,
+ CommonTypeNames.STRING
+ )
- addStatement("final $T $L = new $T($L)", columnListType, columnListVar,
- columnListType, entity.fields.size)
+ addStatement(
+ "final $T $L = new $T($L)", columnListType, columnListVar,
+ columnListType, entity.fields.size
+ )
entity.nonHiddenFields.forEach {
addStatement("$L.add($S)", columnListVar, it.columnName)
}
- addStatement("final $T $L = new $T($S, $L, $S)",
- RoomTypeNames.FTS_TABLE_INFO, expectedInfoVar, RoomTypeNames.FTS_TABLE_INFO,
- entity.tableName, columnListVar, entity.createTableQuery)
+ addStatement(
+ "final $T $L = new $T($S, $L, $S)",
+ RoomTypeNames.FTS_TABLE_INFO, expectedInfoVar, RoomTypeNames.FTS_TABLE_INFO,
+ entity.tableName, columnListVar, entity.createTableQuery
+ )
val existingVar = scope.getTmpVar("_existing$suffix")
- addStatement("final $T $L = $T.read($N, $S)",
- RoomTypeNames.FTS_TABLE_INFO, existingVar, RoomTypeNames.FTS_TABLE_INFO,
- dbParam, entity.tableName)
+ addStatement(
+ "final $T $L = $T.read($N, $S)",
+ RoomTypeNames.FTS_TABLE_INFO, existingVar, RoomTypeNames.FTS_TABLE_INFO,
+ dbParam, entity.tableName
+ )
beginControlFlow("if (!$L.equals($L))", expectedInfoVar, existingVar).apply {
- addStatement("return new $T(false, $S + $L + $S + $L)",
- RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT,
- "${entity.tableName}(${entity.element.qualifiedName}).\n Expected:\n",
- expectedInfoVar, "\n Found:\n", existingVar)
+ addStatement(
+ "return new $T(false, $S + $L + $S + $L)",
+ RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT,
+ "${entity.tableName}(${entity.element.qualifiedName}).\n Expected:\n",
+ expectedInfoVar, "\n Found:\n", existingVar
+ )
}
endControlFlow()
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/PreparedStatementWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/PreparedStatementWriter.kt
index e035f8f..53e3f57 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/PreparedStatementWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/PreparedStatementWriter.kt
@@ -34,16 +34,18 @@
@Suppress("RemoveSingleExpressionStringTemplate")
return TypeSpec.anonymousClassBuilder("$N", dbParam).apply {
superclass(RoomTypeNames.SHARED_SQLITE_STMT)
- addMethod(MethodSpec.methodBuilder("createQuery").apply {
- addAnnotation(Override::class.java)
- returns(ClassName.get("java.lang", "String"))
- addModifiers(Modifier.PUBLIC)
- val queryName = scope.getTmpVar("_query")
- val queryGenScope = scope.fork()
- queryWriter.prepareQuery(queryName, queryGenScope)
- addCode(queryGenScope.builder().build())
- addStatement("return $L", queryName)
- }.build())
+ addMethod(
+ MethodSpec.methodBuilder("createQuery").apply {
+ addAnnotation(Override::class.java)
+ returns(ClassName.get("java.lang", "String"))
+ addModifiers(Modifier.PUBLIC)
+ val queryName = scope.getTmpVar("_query")
+ val queryGenScope = scope.fork()
+ queryWriter.prepareQuery(queryName, queryGenScope)
+ addCode(queryGenScope.builder().build())
+ addStatement("return $L", queryName)
+ }.build()
+ )
}.build()
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/QueryWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/QueryWriter.kt
index 8b27b53..8662e74 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/QueryWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/QueryWriter.kt
@@ -40,8 +40,10 @@
val query: ParsedQuery
) {
- constructor(queryMethod: QueryMethod) : this(queryMethod.parameters,
- queryMethod.sectionToParamMapping, queryMethod.query)
+ constructor(queryMethod: QueryMethod) : this(
+ queryMethod.parameters,
+ queryMethod.sectionToParamMapping, queryMethod.query
+ )
fun prepareReadAndBind(
outSqlQueryName: String,
@@ -66,7 +68,7 @@
): List<Pair<QueryParameter, String>> {
val listSizeVars = arrayListOf<Pair<QueryParameter, String>>()
val varargParams = parameters
- .filter { it.queryParamAdapter?.isMultiple ?: false }
+ .filter { it.queryParamAdapter?.isMultiple ?: false }
val sectionToParamMapping = sectionToParamMapping
val knownQueryArgsCount = sectionToParamMapping.filterNot {
it.second?.queryParamAdapter?.isMultiple ?: false
@@ -74,12 +76,17 @@
scope.builder().apply {
if (varargParams.isNotEmpty()) {
val stringBuilderVar = scope.getTmpVar("_stringBuilder")
- addStatement("$T $L = $T.newStringBuilder()",
- ClassName.get(StringBuilder::class.java), stringBuilderVar, STRING_UTIL)
+ addStatement(
+ "$T $L = $T.newStringBuilder()",
+ ClassName.get(StringBuilder::class.java), stringBuilderVar, STRING_UTIL
+ )
query.sections.forEach {
when (it.type) {
- SectionType.TEXT -> addStatement("$L.append($S)", stringBuilderVar, it
- .text)
+ SectionType.TEXT -> addStatement(
+ "$L.append($S)", stringBuilderVar,
+ it
+ .text
+ )
SectionType.NEWLINE -> addStatement("$L.append($S)", stringBuilderVar, "\n")
SectionType.BIND_VAR -> {
// If it is null, will be reported as error before. We just try out
@@ -91,10 +98,12 @@
val tmpCount = scope.getTmpVar("_inputSize")
listSizeVars.add(Pair(pair.second!!, tmpCount))
pair.second
- ?.queryParamAdapter
- ?.getArgCount(pair.second!!.name, tmpCount, scope)
- addStatement("$T.appendPlaceholders($L, $L)",
- STRING_UTIL, stringBuilderVar, tmpCount)
+ ?.queryParamAdapter
+ ?.getArgCount(pair.second!!.name, tmpCount, scope)
+ addStatement(
+ "$T.appendPlaceholders($L, $L)",
+ STRING_UTIL, stringBuilderVar, tmpCount
+ )
} else {
addStatement("$L.append($S)", stringBuilderVar, "?")
}
@@ -103,23 +112,33 @@
}
}
- addStatement("final $T $L = $L.toString()", String::class.typeName,
- outSqlQueryName, stringBuilderVar)
+ addStatement(
+ "final $T $L = $L.toString()", String::class.typeName,
+ outSqlQueryName, stringBuilderVar
+ )
if (outArgsName != null) {
val argCount = scope.getTmpVar("_argCount")
- addStatement("final $T $L = $L$L", TypeName.INT, argCount, knownQueryArgsCount,
- listSizeVars.joinToString("") { " + ${it.second}" })
- addStatement("final $T $L = $T.acquire($L, $L)",
- ROOM_SQL_QUERY, outArgsName, ROOM_SQL_QUERY, outSqlQueryName,
- argCount)
+ addStatement(
+ "final $T $L = $L$L", TypeName.INT, argCount, knownQueryArgsCount,
+ listSizeVars.joinToString("") { " + ${it.second}" }
+ )
+ addStatement(
+ "final $T $L = $T.acquire($L, $L)",
+ ROOM_SQL_QUERY, outArgsName, ROOM_SQL_QUERY, outSqlQueryName,
+ argCount
+ )
}
} else {
- addStatement("final $T $L = $S", String::class.typeName,
- outSqlQueryName, query.queryWithReplacedBindParams)
+ addStatement(
+ "final $T $L = $S", String::class.typeName,
+ outSqlQueryName, query.queryWithReplacedBindParams
+ )
if (outArgsName != null) {
- addStatement("final $T $L = $T.acquire($L, $L)",
- ROOM_SQL_QUERY, outArgsName, ROOM_SQL_QUERY, outSqlQueryName,
- knownQueryArgsCount)
+ addStatement(
+ "final $T $L = $T.acquire($L, $L)",
+ ROOM_SQL_QUERY, outArgsName, ROOM_SQL_QUERY, outSqlQueryName,
+ knownQueryArgsCount
+ )
}
}
}
@@ -144,9 +163,11 @@
sectionToParamMapping.forEach { pair ->
// reset the argIndex to the correct start index
if (constInputs > 0 || varInputs.isNotEmpty()) {
- addStatement("$L = $L$L", argIndex,
- if (constInputs > 0) (1 + constInputs) else "1",
- varInputs.joinToString("") { " + $it" })
+ addStatement(
+ "$L = $L$L", argIndex,
+ if (constInputs > 0) (1 + constInputs) else "1",
+ varInputs.joinToString("") { " + $it" }
+ )
}
val param = pair.second
param?.let {
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/RelationCollectorMethodWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/RelationCollectorMethodWriter.kt
index 1ca5dba..82f6592 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/RelationCollectorMethodWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/RelationCollectorMethodWriter.kt
@@ -42,7 +42,8 @@
class RelationCollectorMethodWriter(private val collector: RelationCollector) :
ClassWriter.SharedMethodSpec(
"fetchRelationship${collector.relation.entity.tableName.stripNonJava()}" +
- "As${collector.relation.pojoTypeName.toString().stripNonJava()}") {
+ "As${collector.relation.pojoTypeName.toString().stripNonJava()}"
+ ) {
companion object {
const val PARAM_MAP_VARIABLE = "_map"
const val KEY_SET_VARIABLE = "__mapKeySet"
@@ -50,11 +51,11 @@
override fun getUniqueKey(): String {
val relation = collector.relation
return "RelationCollectorMethodWriter" +
- "-${collector.mapTypeName}" +
- "-${relation.entity.typeName}" +
- "-${relation.entityField.columnName}" +
- "-${relation.pojoTypeName}" +
- "-${relation.createLoadAllSql()}"
+ "-${collector.mapTypeName}" +
+ "-${relation.entity.typeName}" +
+ "-${relation.entityField.columnName}" +
+ "-${relation.pojoTypeName}" +
+ "-${relation.createLoadAllSql()}"
}
override fun prepare(methodName: String, writer: ClassWriter, builder: MethodSpec.Builder) {
@@ -62,8 +63,8 @@
val relation = collector.relation
val param = ParameterSpec.builder(collector.mapTypeName, PARAM_MAP_VARIABLE)
- .addModifiers(Modifier.FINAL)
- .build()
+ .addModifiers(Modifier.FINAL)
+ .build()
val sqlQueryVar = scope.getTmpVar("_sql")
val cursorVar = "_cursor"
@@ -71,19 +72,23 @@
val stmtVar = scope.getTmpVar("_stmt")
scope.builder().apply {
val usingLongSparseArray =
- collector.mapTypeName.rawType == CollectionTypeNames.LONG_SPARSE_ARRAY
+ collector.mapTypeName.rawType == CollectionTypeNames.LONG_SPARSE_ARRAY
val usingArrayMap =
- collector.mapTypeName.rawType == CollectionTypeNames.ARRAY_MAP
+ collector.mapTypeName.rawType == CollectionTypeNames.ARRAY_MAP
fun CodeBlock.Builder.addBatchPutAllStatement(tmpMapVar: String) {
if (usingArrayMap) {
// When using ArrayMap there is ambiguity in the putAll() method, clear the
// confusion by casting the temporary map.
val disambiguityTypeName =
- ParameterizedTypeName.get(CommonTypeNames.MAP,
+ ParameterizedTypeName.get(
+ CommonTypeNames.MAP,
collector.mapTypeName.typeArguments[0],
- collector.mapTypeName.typeArguments[1])
- addStatement("$N.putAll(($T) $L)",
- param, disambiguityTypeName, tmpMapVar)
+ collector.mapTypeName.typeArguments[1]
+ )
+ addStatement(
+ "$N.putAll(($T) $L)",
+ param, disambiguityTypeName, tmpMapVar
+ )
} else {
addStatement("$N.putAll($L)", param, tmpMapVar)
}
@@ -92,7 +97,8 @@
beginControlFlow("if ($N.isEmpty())", param)
} else {
val keySetType = ParameterizedTypeName.get(
- ClassName.get(Set::class.java), collector.keyTypeName)
+ ClassName.get(Set::class.java), collector.keyTypeName
+ )
addStatement("final $T $L = $N.keySet()", keySetType, KEY_SET_VARIABLE, param)
beginControlFlow("if ($L.isEmpty())", KEY_SET_VARIABLE)
}.apply {
@@ -100,13 +106,17 @@
}
endControlFlow()
addStatement("// check if the size is too big, if so divide")
- beginControlFlow("if($N.size() > $T.MAX_BIND_PARAMETER_CNT)",
- param, RoomTypeNames.ROOM_DB).apply {
+ beginControlFlow(
+ "if($N.size() > $T.MAX_BIND_PARAMETER_CNT)",
+ param, RoomTypeNames.ROOM_DB
+ ).apply {
// divide it into chunks
val tmpMapVar = scope.getTmpVar("_tmpInnerMap")
- addStatement("$T $L = new $T($L.MAX_BIND_PARAMETER_CNT)",
- collector.mapTypeName, tmpMapVar,
- collector.mapTypeName, RoomTypeNames.ROOM_DB)
+ addStatement(
+ "$T $L = new $T($L.MAX_BIND_PARAMETER_CNT)",
+ collector.mapTypeName, tmpMapVar,
+ collector.mapTypeName, RoomTypeNames.ROOM_DB
+ )
val tmpIndexVar = scope.getTmpVar("_tmpIndex")
addStatement("$T $L = 0", TypeName.INT, tmpIndexVar)
if (usingLongSparseArray || usingArrayMap) {
@@ -116,29 +126,39 @@
addStatement("final $T $L = $N.size()", TypeName.INT, limitVar, param)
beginControlFlow("while($L < $L)", mapIndexVar, limitVar).apply {
if (collector.relationTypeIsCollection) {
- addStatement("$L.put($N.keyAt($L), $N.valueAt($L))",
- tmpMapVar, param, mapIndexVar, param, mapIndexVar)
+ addStatement(
+ "$L.put($N.keyAt($L), $N.valueAt($L))",
+ tmpMapVar, param, mapIndexVar, param, mapIndexVar
+ )
} else {
- addStatement("$L.put($N.keyAt($L), null)",
- tmpMapVar, param, mapIndexVar)
+ addStatement(
+ "$L.put($N.keyAt($L), null)",
+ tmpMapVar, param, mapIndexVar
+ )
}
addStatement("$L++", mapIndexVar)
}
} else {
val mapKeyVar = scope.getTmpVar("_mapKey")
- beginControlFlow("for($T $L : $L)",
- collector.keyTypeName, mapKeyVar, KEY_SET_VARIABLE).apply {
+ beginControlFlow(
+ "for($T $L : $L)",
+ collector.keyTypeName, mapKeyVar, KEY_SET_VARIABLE
+ ).apply {
if (collector.relationTypeIsCollection) {
- addStatement("$L.put($L, $N.get($L))",
- tmpMapVar, mapKeyVar, param, mapKeyVar)
+ addStatement(
+ "$L.put($L, $N.get($L))",
+ tmpMapVar, mapKeyVar, param, mapKeyVar
+ )
} else {
addStatement("$L.put($L, null)", tmpMapVar, mapKeyVar)
}
}
}.apply {
addStatement("$L++", tmpIndexVar)
- beginControlFlow("if($L == $T.MAX_BIND_PARAMETER_CNT)",
- tmpIndexVar, RoomTypeNames.ROOM_DB).apply {
+ beginControlFlow(
+ "if($L == $T.MAX_BIND_PARAMETER_CNT)",
+ tmpIndexVar, RoomTypeNames.ROOM_DB
+ ).apply {
// recursively load that batch
addStatement("$L($L)", methodName, tmpMapVar)
// for non collection relation, put the loaded batch in the original map,
@@ -147,8 +167,10 @@
addBatchPutAllStatement(tmpMapVar)
}
// clear nukes the backing data hence we create a new one
- addStatement("$L = new $T($T.MAX_BIND_PARAMETER_CNT)",
- tmpMapVar, collector.mapTypeName, RoomTypeNames.ROOM_DB)
+ addStatement(
+ "$L = new $T($T.MAX_BIND_PARAMETER_CNT)",
+ tmpMapVar, collector.mapTypeName, RoomTypeNames.ROOM_DB
+ )
addStatement("$L = 0", tmpIndexVar)
}.endControlFlow()
}.endControlFlow()
@@ -167,14 +189,16 @@
val shouldCopyCursor = collector.rowAdapter.let {
it is PojoRowAdapter && it.relationCollectors.isNotEmpty()
}
- addStatement("final $T $L = $T.query($N, $L, $L, $L)",
- AndroidTypeNames.CURSOR,
- cursorVar,
- RoomTypeNames.DB_UTIL,
- DaoWriter.dbField,
- stmtVar,
- if (shouldCopyCursor) "true" else "false",
- "null")
+ addStatement(
+ "final $T $L = $T.query($N, $L, $L, $L)",
+ AndroidTypeNames.CURSOR,
+ cursorVar,
+ RoomTypeNames.DB_UTIL,
+ DaoWriter.dbField,
+ stmtVar,
+ if (shouldCopyCursor) "true" else "false",
+ "null"
+ )
beginControlFlow("try").apply {
if (relation.junction != null) {
@@ -183,13 +207,17 @@
// clause, this column is the rightmost column in the generated SELECT
// clause.
val junctionParentColumnIndex = relation.projection.size
- addStatement("final $T $L = $L; // _junction.$L",
+ addStatement(
+ "final $T $L = $L; // _junction.$L",
TypeName.INT, itemKeyIndexVar, junctionParentColumnIndex,
- relation.junction.parentField.columnName)
+ relation.junction.parentField.columnName
+ )
} else {
- addStatement("final $T $L = $T.getColumnIndex($L, $S)",
+ addStatement(
+ "final $T $L = $T.getColumnIndex($L, $S)",
TypeName.INT, itemKeyIndexVar, RoomTypeNames.CURSOR_UTIL, cursorVar,
- relation.entityField.columnName)
+ relation.entityField.columnName
+ )
}
beginControlFlow("if ($L == -1)", itemKeyIndexVar).apply {
@@ -202,14 +230,16 @@
beginControlFlow("while($L.moveToNext())", cursorVar).apply {
// read key from the cursor
collector.readKey(
- cursorVarName = cursorVar,
- indexVar = itemKeyIndexVar,
- scope = scope
+ cursorVarName = cursorVar,
+ indexVar = itemKeyIndexVar,
+ scope = scope
) { keyVar ->
if (collector.relationTypeIsCollection) {
val relationVar = scope.getTmpVar("_tmpRelation")
- addStatement("$T $L = $N.get($L)", collector.relationTypeName,
- relationVar, param, keyVar)
+ addStatement(
+ "$T $L = $N.get($L)", collector.relationTypeName,
+ relationVar, param, keyVar
+ )
beginControlFlow("if ($L != null)", relationVar)
addStatement("final $T $L", relation.pojoTypeName, tmpVarName)
collector.rowAdapter.convert(tmpVarName, cursorVar, scope)
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/SQLiteOpenHelperWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/SQLiteOpenHelperWriter.kt
index 302944f..600612d 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/SQLiteOpenHelperWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/SQLiteOpenHelperWriter.kt
@@ -50,24 +50,29 @@
scope.builder().apply {
val sqliteConfigVar = scope.getTmpVar("_sqliteConfig")
val callbackVar = scope.getTmpVar("_openCallback")
- addStatement("final $T $L = new $T($N, $L, $S, $S)",
- SupportDbTypeNames.SQLITE_OPEN_HELPER_CALLBACK,
- callbackVar, RoomTypeNames.OPEN_HELPER, configuration,
- createOpenCallback(scope), database.identityHash, database.legacyIdentityHash)
+ addStatement(
+ "final $T $L = new $T($N, $L, $S, $S)",
+ SupportDbTypeNames.SQLITE_OPEN_HELPER_CALLBACK,
+ callbackVar, RoomTypeNames.OPEN_HELPER, configuration,
+ createOpenCallback(scope), database.identityHash, database.legacyIdentityHash
+ )
// build configuration
addStatement(
- """
+ """
final $T $L = $T.builder($N.context)
.name($N.name)
.callback($L)
.build()
- """.trimIndent(),
- SupportDbTypeNames.SQLITE_OPEN_HELPER_CONFIG, sqliteConfigVar,
- SupportDbTypeNames.SQLITE_OPEN_HELPER_CONFIG,
- configuration, configuration, callbackVar)
- addStatement("final $T $N = $N.sqliteOpenHelperFactory.create($L)",
- SupportDbTypeNames.SQLITE_OPEN_HELPER, outVar,
- configuration, sqliteConfigVar)
+ """.trimIndent(),
+ SupportDbTypeNames.SQLITE_OPEN_HELPER_CONFIG, sqliteConfigVar,
+ SupportDbTypeNames.SQLITE_OPEN_HELPER_CONFIG,
+ configuration, configuration, callbackVar
+ )
+ addStatement(
+ "final $T $N = $N.sqliteOpenHelperFactory.create($L)",
+ SupportDbTypeNames.SQLITE_OPEN_HELPER, outVar,
+ configuration, sqliteConfigVar
+ )
}
}
@@ -96,40 +101,44 @@
} else {
"onValidateSchema${methodSpecs.size + 1}"
}
- methodSpecs.add(MethodSpec.methodBuilder(methodName).apply {
- if (isPrimaryMethod) {
- addModifiers(PROTECTED)
- addAnnotation(Override::class.java)
- } else {
- addModifiers(PRIVATE)
- }
- returns(RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT)
- addParameter(dbParam)
- var statementCount = 0
- while (!entities.isEmpty() && statementCount < VALIDATE_CHUNK_SIZE) {
- val methodScope = scope.fork()
- val entity = entities.poll()
- val validationWriter = when (entity) {
- is FtsEntity -> FtsTableInfoValidationWriter(entity)
- else -> TableInfoValidationWriter(entity)
+ methodSpecs.add(
+ MethodSpec.methodBuilder(methodName).apply {
+ if (isPrimaryMethod) {
+ addModifiers(PROTECTED)
+ addAnnotation(Override::class.java)
+ } else {
+ addModifiers(PRIVATE)
}
- validationWriter.write(dbParam, methodScope)
- addCode(methodScope.builder().build())
- statementCount += validationWriter.statementCount()
- }
- while (!views.isEmpty() && statementCount < VALIDATE_CHUNK_SIZE) {
- val methodScope = scope.fork()
- val view = views.poll()
- val validationWriter = ViewInfoValidationWriter(view)
- validationWriter.write(dbParam, methodScope)
- addCode(methodScope.builder().build())
- statementCount += validationWriter.statementCount()
- }
- if (!isPrimaryMethod) {
- addStatement("return new $T(true, null)",
- RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT)
- }
- }.build())
+ returns(RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT)
+ addParameter(dbParam)
+ var statementCount = 0
+ while (!entities.isEmpty() && statementCount < VALIDATE_CHUNK_SIZE) {
+ val methodScope = scope.fork()
+ val entity = entities.poll()
+ val validationWriter = when (entity) {
+ is FtsEntity -> FtsTableInfoValidationWriter(entity)
+ else -> TableInfoValidationWriter(entity)
+ }
+ validationWriter.write(dbParam, methodScope)
+ addCode(methodScope.builder().build())
+ statementCount += validationWriter.statementCount()
+ }
+ while (!views.isEmpty() && statementCount < VALIDATE_CHUNK_SIZE) {
+ val methodScope = scope.fork()
+ val view = views.poll()
+ val validationWriter = ViewInfoValidationWriter(view)
+ validationWriter.write(dbParam, methodScope)
+ addCode(methodScope.builder().build())
+ statementCount += validationWriter.statementCount()
+ }
+ if (!isPrimaryMethod) {
+ addStatement(
+ "return new $T(true, null)",
+ RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT
+ )
+ }
+ }.build()
+ )
}
// If there are secondary validate methods then add invocation statements to all of them
@@ -144,13 +153,17 @@
addStatement("return $L", resultVar)
endControlFlow()
}
- addStatement("return new $T(true, null)",
- RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT)
+ addStatement(
+ "return new $T(true, null)",
+ RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT
+ )
}.build()
} else if (methodSpecs.size == 1) {
methodSpecs[0] = methodSpecs[0].toBuilder().apply {
- addStatement("return new $T(true, null)",
- RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT)
+ addStatement(
+ "return new $T(true, null)",
+ RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT
+ )
}.build()
}
@@ -221,11 +234,11 @@
addAnnotation(Override::class.java)
addParameter(SupportDbTypeNames.DB, "_db")
database.entities.filterIsInstance(FtsEntity::class.java)
- .filter { it.ftsOptions.contentEntity != null }
- .flatMap { it.contentSyncTriggerCreateQueries }
- .forEach { syncTriggerQuery ->
- addStatement("_db.execSQL($S)", syncTriggerQuery)
- }
+ .filter { it.ftsOptions.contentEntity != null }
+ .flatMap { it.contentSyncTriggerCreateQueries }
+ .forEach { syncTriggerQuery ->
+ addStatement("_db.execSQL($S)", syncTriggerQuery)
+ }
}.build()
}
@@ -233,8 +246,10 @@
val iVar = scope.getTmpVar("_i")
val sizeVar = scope.getTmpVar("_size")
beginControlFlow("if (mCallbacks != null)").apply {
- beginControlFlow("for (int $N = 0, $N = mCallbacks.size(); $N < $N; $N++)",
- iVar, sizeVar, iVar, sizeVar, iVar).apply {
+ beginControlFlow(
+ "for (int $N = 0, $N = mCallbacks.size(); $N < $N; $N++)",
+ iVar, sizeVar, iVar, sizeVar, iVar
+ ).apply {
addStatement("mCallbacks.get($N).$N(_db)", iVar, methodName)
}
endControlFlow()
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/TableInfoValidationWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/TableInfoValidationWriter.kt
index 69923a9..ee2ef50 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/TableInfoValidationWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/TableInfoValidationWriter.kt
@@ -46,74 +46,99 @@
val expectedInfoVar = scope.getTmpVar("_info$suffix")
scope.builder().apply {
val columnListVar = scope.getTmpVar("_columns$suffix")
- val columnListType = ParameterizedTypeName.get(HashMap::class.typeName,
- CommonTypeNames.STRING, RoomTypeNames.TABLE_INFO_COLUMN)
+ val columnListType = ParameterizedTypeName.get(
+ HashMap::class.typeName,
+ CommonTypeNames.STRING, RoomTypeNames.TABLE_INFO_COLUMN
+ )
- addStatement("final $T $L = new $T($L)", columnListType, columnListVar,
- columnListType, entity.fields.size)
+ addStatement(
+ "final $T $L = new $T($L)", columnListType, columnListVar,
+ columnListType, entity.fields.size
+ )
entity.fields.forEach { field ->
- addStatement("$L.put($S, new $T($S, $S, $L, $L, $S, $T.$L))",
- columnListVar, field.columnName, RoomTypeNames.TABLE_INFO_COLUMN,
- /*name*/ field.columnName,
- /*type*/ field.affinity?.name ?: SQLTypeAffinity.TEXT.name,
- /*nonNull*/ field.nonNull,
- /*pkeyPos*/ entity.primaryKey.fields.indexOf(field) + 1,
- /*defaultValue*/ field.defaultValue,
- /*createdFrom*/ RoomTypeNames.TABLE_INFO, CREATED_FROM_ENTITY)
+ addStatement(
+ "$L.put($S, new $T($S, $S, $L, $L, $S, $T.$L))",
+ columnListVar, field.columnName, RoomTypeNames.TABLE_INFO_COLUMN,
+ /*name*/ field.columnName,
+ /*type*/ field.affinity?.name ?: SQLTypeAffinity.TEXT.name,
+ /*nonNull*/ field.nonNull,
+ /*pkeyPos*/ entity.primaryKey.fields.indexOf(field) + 1,
+ /*defaultValue*/ field.defaultValue,
+ /*createdFrom*/ RoomTypeNames.TABLE_INFO, CREATED_FROM_ENTITY
+ )
}
val foreignKeySetVar = scope.getTmpVar("_foreignKeys$suffix")
- val foreignKeySetType = ParameterizedTypeName.get(HashSet::class.typeName,
- RoomTypeNames.TABLE_INFO_FOREIGN_KEY)
- addStatement("final $T $L = new $T($L)", foreignKeySetType, foreignKeySetVar,
- foreignKeySetType, entity.foreignKeys.size)
+ val foreignKeySetType = ParameterizedTypeName.get(
+ HashSet::class.typeName,
+ RoomTypeNames.TABLE_INFO_FOREIGN_KEY
+ )
+ addStatement(
+ "final $T $L = new $T($L)", foreignKeySetType, foreignKeySetVar,
+ foreignKeySetType, entity.foreignKeys.size
+ )
entity.foreignKeys.forEach {
val myColumnNames = it.childFields
- .joinToString(",") { "\"${it.columnName}\"" }
+ .joinToString(",") { "\"${it.columnName}\"" }
val refColumnNames = it.parentColumns
- .joinToString(",") { "\"$it\"" }
- addStatement("$L.add(new $T($S, $S, $S," +
- "$T.asList($L), $T.asList($L)))", foreignKeySetVar,
- RoomTypeNames.TABLE_INFO_FOREIGN_KEY,
- /*parent table*/ it.parentTable,
- /*on delete*/ it.onDelete.sqlName,
- /*on update*/ it.onUpdate.sqlName,
- Arrays::class.typeName,
- /*parent names*/ myColumnNames,
- Arrays::class.typeName,
- /*parent column names*/ refColumnNames)
+ .joinToString(",") { "\"$it\"" }
+ addStatement(
+ "$L.add(new $T($S, $S, $S," +
+ "$T.asList($L), $T.asList($L)))",
+ foreignKeySetVar,
+ RoomTypeNames.TABLE_INFO_FOREIGN_KEY,
+ /*parent table*/ it.parentTable,
+ /*on delete*/ it.onDelete.sqlName,
+ /*on update*/ it.onUpdate.sqlName,
+ Arrays::class.typeName,
+ /*parent names*/ myColumnNames,
+ Arrays::class.typeName,
+ /*parent column names*/ refColumnNames
+ )
}
val indicesSetVar = scope.getTmpVar("_indices$suffix")
- val indicesType = ParameterizedTypeName.get(HashSet::class.typeName,
- RoomTypeNames.TABLE_INFO_INDEX)
- addStatement("final $T $L = new $T($L)", indicesType, indicesSetVar,
- indicesType, entity.indices.size)
+ val indicesType = ParameterizedTypeName.get(
+ HashSet::class.typeName,
+ RoomTypeNames.TABLE_INFO_INDEX
+ )
+ addStatement(
+ "final $T $L = new $T($L)", indicesType, indicesSetVar,
+ indicesType, entity.indices.size
+ )
entity.indices.forEach { index ->
val columnNames = index.columnNames.joinToString(",") { "\"$it\"" }
- addStatement("$L.add(new $T($S, $L, $T.asList($L)))",
- indicesSetVar,
- RoomTypeNames.TABLE_INFO_INDEX,
- index.name,
- index.unique,
- Arrays::class.typeName,
- columnNames)
+ addStatement(
+ "$L.add(new $T($S, $L, $T.asList($L)))",
+ indicesSetVar,
+ RoomTypeNames.TABLE_INFO_INDEX,
+ index.name,
+ index.unique,
+ Arrays::class.typeName,
+ columnNames
+ )
}
- addStatement("final $T $L = new $T($S, $L, $L, $L)",
- RoomTypeNames.TABLE_INFO, expectedInfoVar, RoomTypeNames.TABLE_INFO,
- entity.tableName, columnListVar, foreignKeySetVar, indicesSetVar)
+ addStatement(
+ "final $T $L = new $T($S, $L, $L, $L)",
+ RoomTypeNames.TABLE_INFO, expectedInfoVar, RoomTypeNames.TABLE_INFO,
+ entity.tableName, columnListVar, foreignKeySetVar, indicesSetVar
+ )
val existingVar = scope.getTmpVar("_existing$suffix")
- addStatement("final $T $L = $T.read($N, $S)",
- RoomTypeNames.TABLE_INFO, existingVar, RoomTypeNames.TABLE_INFO,
- dbParam, entity.tableName)
+ addStatement(
+ "final $T $L = $T.read($N, $S)",
+ RoomTypeNames.TABLE_INFO, existingVar, RoomTypeNames.TABLE_INFO,
+ dbParam, entity.tableName
+ )
beginControlFlow("if (! $L.equals($L))", expectedInfoVar, existingVar).apply {
- addStatement("return new $T(false, $S + $L + $S + $L)",
- RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT,
- "${entity.tableName}(${entity.element.qualifiedName}).\n Expected:\n",
- expectedInfoVar, "\n Found:\n", existingVar)
+ addStatement(
+ "return new $T(false, $S + $L + $S + $L)",
+ RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT,
+ "${entity.tableName}(${entity.element.qualifiedName}).\n Expected:\n",
+ expectedInfoVar, "\n Found:\n", existingVar
+ )
}
endControlFlow()
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/ViewInfoValidationWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/ViewInfoValidationWriter.kt
index 16d68a5..6f5759b 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/ViewInfoValidationWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/ViewInfoValidationWriter.kt
@@ -33,20 +33,26 @@
val suffix = view.viewName.stripNonJava().capitalize(Locale.US)
scope.builder().apply {
val expectedInfoVar = scope.getTmpVar("_info$suffix")
- addStatement("final $T $L = new $T($S, $S)",
- RoomTypeNames.VIEW_INFO, expectedInfoVar, RoomTypeNames.VIEW_INFO,
- view.viewName, view.createViewQuery)
+ addStatement(
+ "final $T $L = new $T($S, $S)",
+ RoomTypeNames.VIEW_INFO, expectedInfoVar, RoomTypeNames.VIEW_INFO,
+ view.viewName, view.createViewQuery
+ )
val existingVar = scope.getTmpVar("_existing$suffix")
- addStatement("final $T $L = $T.read($N, $S)",
- RoomTypeNames.VIEW_INFO, existingVar, RoomTypeNames.VIEW_INFO,
- dbParam, view.viewName)
+ addStatement(
+ "final $T $L = $T.read($N, $S)",
+ RoomTypeNames.VIEW_INFO, existingVar, RoomTypeNames.VIEW_INFO,
+ dbParam, view.viewName
+ )
beginControlFlow("if (! $L.equals($L))", expectedInfoVar, existingVar).apply {
- addStatement("return new $T(false, $S + $L + $S + $L)",
- RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT,
- "${view.viewName}(${view.element.qualifiedName}).\n Expected:\n",
- expectedInfoVar, "\n Found:\n", existingVar)
+ addStatement(
+ "return new $T(false, $S + $L + $S + $L)",
+ RoomTypeNames.OPEN_HELPER_VALIDATION_RESULT,
+ "${view.viewName}(${view.element.qualifiedName}).\n Expected:\n",
+ expectedInfoVar, "\n Found:\n", existingVar
+ )
}
endControlFlow()
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt b/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
index 6d95c42..b839373 100644
--- a/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
@@ -31,7 +31,8 @@
@Test
fun methodsInClass() {
val parentCode = JavaFileObjects.forSourceLines(
- "foo.bar.Parent", """
+ "foo.bar.Parent",
+ """
package foo.bar;
public class Parent {
@@ -42,10 +43,11 @@
private static void parentStaticPrivate() {}
public static void parentStaticPublic() {}
}
- """.trimIndent()
+ """.trimIndent()
)
val childCode = JavaFileObjects.forSourceLines(
- "foo.bar.Child", """
+ "foo.bar.Child",
+ """
package foo.bar;
public class Child extends Parent {
@@ -56,7 +58,7 @@
private static void childStaticPrivate() {}
public static void childStaticPublic() {}
}
- """.trimIndent()
+ """.trimIndent()
)
simpleRun(
jfos = arrayOf(parentCode, childCode)
@@ -81,7 +83,7 @@
assertThat(parent.getAllNonPrivateInstanceMethods())
.containsExactlyElementsIn(
parentMethods + objectMethods -
- listOf("parentPrivate", "parentStaticPrivate", "parentStaticPublic")
+ listOf("parentPrivate", "parentStaticPrivate", "parentStaticPublic")
)
assertThat(child.getDeclaredMethods()).containsExactlyElementsIn(
@@ -89,17 +91,17 @@
)
assertThat(child.getAllMethods()).containsExactlyElementsIn(
childMethods + parentMethods + objectMethods -
- listOf("parentPrivate", "parentStaticPrivate", "overridden") +
- "overridden" // add 1 overridden back
+ listOf("parentPrivate", "parentStaticPrivate", "overridden") +
+ "overridden" // add 1 overridden back
)
assertThat(child.getAllNonPrivateInstanceMethods())
.containsExactlyElementsIn(
childMethods + parentMethods + objectMethods -
- listOf(
- "parentPrivate", "parentStaticPrivate", "parentStaticPublic",
- "childPrivate", "childStaticPrivate", "childStaticPublic",
- "overridden"
- ) + "overridden" // add 1 overridden back
+ listOf(
+ "parentPrivate", "parentStaticPrivate", "parentStaticPublic",
+ "childPrivate", "childStaticPrivate", "childStaticPublic",
+ "overridden"
+ ) + "overridden" // add 1 overridden back
)
assertThat(child.getConstructors()).hasSize(1)
@@ -110,7 +112,8 @@
@Test
fun methodsInInterface() {
val parentCode = JavaFileObjects.forSourceLines(
- "foo.bar.Parent", """
+ "foo.bar.Parent",
+ """
package foo.bar;
public interface Parent {
@@ -119,10 +122,11 @@
private static void parentStaticPrivate() {}
public static void parentStaticPublic() {}
}
- """.trimIndent()
+ """.trimIndent()
)
val childCode = JavaFileObjects.forSourceLines(
- "foo.bar.Child", """
+ "foo.bar.Child",
+ """
package foo.bar;
public interface Child extends Parent {
@@ -131,7 +135,7 @@
private static void childStaticPrivate() {}
public static void childStaticPublic() {}
}
- """.trimIndent()
+ """.trimIndent()
)
simpleRun(
jfos = arrayOf(parentCode, childCode)
@@ -158,8 +162,8 @@
.containsExactlyElementsIn(childMethods)
assertThat(child.getAllMethods()).containsExactlyElementsIn(
childMethods + parentMethods -
- listOf("parentStaticPrivate", "parentStaticPublic", "overridden") +
- "overridden" // add 1 overridden back
+ listOf("parentStaticPrivate", "parentStaticPublic", "overridden") +
+ "overridden" // add 1 overridden back
)
assertThat(child.getAllNonPrivateInstanceMethods())
.containsExactly(
@@ -174,7 +178,8 @@
@Test
fun types() {
val testCode = JavaFileObjects.forSourceLines(
- "foo.bar.Baz", """
+ "foo.bar.Baz",
+ """
package foo.bar;
public class Baz {
@@ -183,7 +188,7 @@
return 3;
}
}
- """.trimIndent()
+ """.trimIndent()
)
simpleRun(
jfos = arrayOf(testCode)
diff --git a/room/compiler/src/test/kotlin/androidx/room/parser/ExpandableSqlParserTest.kt b/room/compiler/src/test/kotlin/androidx/room/parser/ExpandableSqlParserTest.kt
index 2f0f74f..0a030e4 100644
--- a/room/compiler/src/test/kotlin/androidx/room/parser/ExpandableSqlParserTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/parser/ExpandableSqlParserTest.kt
@@ -78,8 +78,8 @@
fun upsertQuery() {
val parsed = ExpandableSqlParser.parse(
"INSERT INTO notes (id, content) VALUES (:id, :content) " +
- "ON CONFLICT (id) DO UPDATE SET content = excluded.content, " +
- "revision = revision + 1, modifiedTime = strftime('%s','now')"
+ "ON CONFLICT (id) DO UPDATE SET content = excluded.content, " +
+ "revision = revision + 1, modifiedTime = strftime('%s','now')"
)
assertThat(parsed.errors, `is`(emptyList()))
assertThat(parsed.type, `is`(QueryType.INSERT))
@@ -115,7 +115,7 @@
fun projection() {
val query = ExpandableSqlParser.parse(
"SELECT * FROM User WHERE teamId IN " +
- "(SELECT * FROM Team WHERE active != 0)"
+ "(SELECT * FROM Team WHERE active != 0)"
)
assertThat(query.errors, `is`(emptyList()))
assertThat(query.projections.size, `is`(1))
@@ -239,7 +239,8 @@
val query = ExpandableSqlParser.parse("SELECT a.name, b.last_name from user a, book b")
assertThat(query.errors, `is`(emptyList()))
assertThat(
- query.tables, `is`(
+ query.tables,
+ `is`(
setOf(
Table("user", "a"),
Table("book", "b")
@@ -252,11 +253,12 @@
fun tablePrefixInSelect_where() {
val query = ExpandableSqlParser.parse(
"SELECT a.name, b.last_name from user a, book b" +
- " WHERE a.name = b.name"
+ " WHERE a.name = b.name"
)
assertThat(query.errors, `is`(emptyList()))
assertThat(
- query.tables, `is`(
+ query.tables,
+ `is`(
setOf(
Table("user", "a"),
Table("book", "b")
diff --git a/room/compiler/src/test/kotlin/androidx/room/parser/SqlParserTest.kt b/room/compiler/src/test/kotlin/androidx/room/parser/SqlParserTest.kt
index b7b8472..6b2e31d 100644
--- a/room/compiler/src/test/kotlin/androidx/room/parser/SqlParserTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/parser/SqlParserTest.kt
@@ -72,8 +72,8 @@
fun upsertQuery() {
val parsed = SqlParser.parse(
"INSERT INTO notes (id, content) VALUES (:id, :content) " +
- "ON CONFLICT (id) DO UPDATE SET content = excluded.content, " +
- "revision = revision + 1, modifiedTime = strftime('%s','now')"
+ "ON CONFLICT (id) DO UPDATE SET content = excluded.content, " +
+ "revision = revision + 1, modifiedTime = strftime('%s','now')"
)
assertThat(parsed.errors, `is`(emptyList()))
assertThat(parsed.type, `is`(QueryType.INSERT))
@@ -159,7 +159,8 @@
val query = SqlParser.parse("SELECT a.name, b.last_name from user a, book b")
assertThat(query.errors, `is`(emptyList()))
assertThat(
- query.tables, `is`(
+ query.tables,
+ `is`(
setOf(
Table("user", "a"),
Table("book", "b")
@@ -172,11 +173,12 @@
fun tablePrefixInSelect_where() {
val query = SqlParser.parse(
"SELECT a.name, b.last_name from user a, book b" +
- " WHERE a.name = b.name"
+ " WHERE a.name = b.name"
)
assertThat(query.errors, `is`(emptyList()))
assertThat(
- query.tables, `is`(
+ query.tables,
+ `is`(
setOf(
Table("user", "a"),
Table("book", "b")
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt
index d549ae8..fe49774 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt
@@ -21,120 +21,144 @@
@Test
fun insert() {
- baseDao("""
+ baseDao(
+ """
@Insert
void insertMe(T t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.insertionMethods.size, `is`(1))
}
}
@Test
fun insertArray() {
- baseDao("""
+ baseDao(
+ """
@Insert
void insertMe(T[] t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.insertionMethods.size, `is`(1))
}
}
@Test
fun insertVarArg() {
- baseDao("""
+ baseDao(
+ """
@Insert
void insertMe(T... t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.insertionMethods.size, `is`(1))
}
}
@Test
fun insertList() {
- baseDao("""
+ baseDao(
+ """
@Insert
void insertMe(List<T> t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.insertionMethods.size, `is`(1))
}
}
@Test
fun delete() {
- baseDao("""
+ baseDao(
+ """
@Delete
void deleteMe(T t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.deletionMethods.size, `is`(1))
}
}
@Test
fun deleteArray() {
- baseDao("""
+ baseDao(
+ """
@Delete
void deleteMe(T[] t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.deletionMethods.size, `is`(1))
}
}
@Test
fun deleteVarArg() {
- baseDao("""
+ baseDao(
+ """
@Delete
void deleteMe(T... t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.deletionMethods.size, `is`(1))
}
}
@Test
fun deleteList() {
- baseDao("""
+ baseDao(
+ """
@Delete
void deleteMe(List<T> t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.deletionMethods.size, `is`(1))
}
}
@Test
fun update() {
- baseDao("""
+ baseDao(
+ """
@Update
void updateMe(T t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.updateMethods.size, `is`(1))
}
}
@Test
fun updateArray() {
- baseDao("""
+ baseDao(
+ """
@Update
void updateMe(T[] t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.updateMethods.size, `is`(1))
}
}
@Test
fun updateVarArg() {
- baseDao("""
+ baseDao(
+ """
@Update
void updateMe(T... t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.updateMethods.size, `is`(1))
}
}
@Test
fun updateList() {
- baseDao("""
+ baseDao(
+ """
@Update
void updateMe(List<T> t);
- """) { dao ->
+ """
+ ) { dao ->
assertThat(dao.updateMethods.size, `is`(1))
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/BaseEntityParserTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/BaseEntityParserTest.kt
index 3520da9..03c14fd 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/BaseEntityParserTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/BaseEntityParserTest.kt
@@ -54,8 +54,8 @@
attributesReplacement = ""
} else {
attributesReplacement = "(" +
- attributes.entries.joinToString(",") { "${it.key} = ${it.value}" } +
- ")".trimIndent()
+ attributes.entries.joinToString(",") { "${it.key} = ${it.value}" } +
+ ")".trimIndent()
}
val baseClassReplacement: String
if (baseClass == "") {
@@ -64,35 +64,44 @@
baseClassReplacement = " extends $baseClass"
}
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(jfos + JavaFileObjects.forSourceString("foo.bar.MyEntity",
- ENTITY_PREFIX.format(attributesReplacement, baseClassReplacement) +
- input + ENTITY_SUFFIX
- ))
- .apply {
- if (classpathFiles.isNotEmpty()) {
- withClasspath(classpathFiles)
- }
+ .that(
+ jfos + JavaFileObjects.forSourceString(
+ "foo.bar.MyEntity",
+ ENTITY_PREFIX.format(attributesReplacement, baseClassReplacement) +
+ input + ENTITY_SUFFIX
+ )
+ )
+ .apply {
+ if (classpathFiles.isNotEmpty()) {
+ withClasspath(classpathFiles)
}
- .processedWith(TestProcessor.builder()
- .forAnnotations(
- java.lang.SuppressWarnings::class,
- androidx.room.Entity::class,
- androidx.room.PrimaryKey::class,
- androidx.room.Ignore::class,
- Embedded::class,
- androidx.room.ColumnInfo::class,
- NonNull::class)
- .nextRunHandler { invocation ->
- val entity = invocation.roundEnv
- .getElementsAnnotatedWith(
- androidx.room.Entity::class.java)
- .first { it.toString() == "foo.bar.MyEntity" }
- val parser = TableEntityProcessor(invocation.context,
- entity.asTypeElement())
- val parsedQuery = parser.process()
- handler(parsedQuery, invocation)
- true
- }
- .build())
+ }
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(
+ java.lang.SuppressWarnings::class,
+ androidx.room.Entity::class,
+ androidx.room.PrimaryKey::class,
+ androidx.room.Ignore::class,
+ Embedded::class,
+ androidx.room.ColumnInfo::class,
+ NonNull::class
+ )
+ .nextRunHandler { invocation ->
+ val entity = invocation.roundEnv
+ .getElementsAnnotatedWith(
+ androidx.room.Entity::class.java
+ )
+ .first { it.toString() == "foo.bar.MyEntity" }
+ val parser = TableEntityProcessor(
+ invocation.context,
+ entity.asTypeElement()
+ )
+ val parsedQuery = parser.process()
+ handler(parsedQuery, invocation)
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/BaseFtsEntityParserTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/BaseFtsEntityParserTest.kt
index 91c53cb..4a29c48 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/BaseFtsEntityParserTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/BaseFtsEntityParserTest.kt
@@ -70,39 +70,51 @@
" extends $baseClass"
}
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(jfos + JavaFileObjects.forSourceString("foo.bar.MyEntity",
- ENTITY_PREFIX.format(entityAttributesReplacement, ftsVersion,
- ftsAttributesReplacement, baseClassReplacement) + input +
- ENTITY_SUFFIX))
- .apply {
- if (classpathFiles.isNotEmpty()) {
- withClasspath(classpathFiles)
- }
+ .that(
+ jfos + JavaFileObjects.forSourceString(
+ "foo.bar.MyEntity",
+ ENTITY_PREFIX.format(
+ entityAttributesReplacement, ftsVersion,
+ ftsAttributesReplacement, baseClassReplacement
+ ) + input +
+ ENTITY_SUFFIX
+ )
+ )
+ .apply {
+ if (classpathFiles.isNotEmpty()) {
+ withClasspath(classpathFiles)
}
- .processedWith(TestProcessor.builder()
- .forAnnotations(androidx.room.Entity::class,
- Fts3::class,
- Fts4::class,
- androidx.room.PrimaryKey::class,
- androidx.room.Ignore::class,
- Embedded::class,
- androidx.room.ColumnInfo::class,
- NonNull::class)
- .nextRunHandler { invocation ->
- val fts3AnnotatedElements = invocation.roundEnv
- .getElementsAnnotatedWith(Fts3::class.java)
- val fts4AnnotatedElements = invocation.roundEnv
- .getElementsAnnotatedWith(Fts4::class.java)
- val entity = (fts3AnnotatedElements + fts4AnnotatedElements).first {
- it.toString() == "foo.bar.MyEntity"
- }
- val processor = FtsTableEntityProcessor(invocation.context,
- entity.asTypeElement())
- val processedEntity = processor.process()
- handler(processedEntity, invocation)
- true
+ }
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(
+ androidx.room.Entity::class,
+ Fts3::class,
+ Fts4::class,
+ androidx.room.PrimaryKey::class,
+ androidx.room.Ignore::class,
+ Embedded::class,
+ androidx.room.ColumnInfo::class,
+ NonNull::class
+ )
+ .nextRunHandler { invocation ->
+ val fts3AnnotatedElements = invocation.roundEnv
+ .getElementsAnnotatedWith(Fts3::class.java)
+ val fts4AnnotatedElements = invocation.roundEnv
+ .getElementsAnnotatedWith(Fts4::class.java)
+ val entity = (fts3AnnotatedElements + fts4AnnotatedElements).first {
+ it.toString() == "foo.bar.MyEntity"
}
- .build())
+ val processor = FtsTableEntityProcessor(
+ invocation.context,
+ entity.asTypeElement()
+ )
+ val processedEntity = processor.process()
+ handler(processedEntity, invocation)
+ true
+ }
+ .build()
+ )
}
abstract fun getFtsVersion(): Int
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt
index fe9215e..77bc8a3 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/CustomConverterProcessorTest.kt
@@ -48,13 +48,15 @@
companion object {
val CONVERTER = ClassName.get("foo.bar", "MyConverter")!!
val CONVERTER_QNAME = CONVERTER.packageName() + "." + CONVERTER.simpleName()
- val CONTAINER = JavaFileObjects.forSourceString("foo.bar.Container",
- """
+ val CONTAINER = JavaFileObjects.forSourceString(
+ "foo.bar.Container",
+ """
package foo.bar;
import androidx.room.*;
@TypeConverters(foo.bar.MyConverter.class)
public class Container {}
- """)
+ """
+ )
}
@Test
@@ -124,18 +126,24 @@
@Test
fun testNoConverters() {
- singleClass(JavaFileObjects.forSourceString(CONVERTER_QNAME,
+ singleClass(
+ JavaFileObjects.forSourceString(
+ CONVERTER_QNAME,
"""
package ${CONVERTER.packageName()};
public class ${CONVERTER.simpleName()} {
}
- """)) { _, _ ->
+ """
+ )
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(TYPE_CONVERTER_EMPTY_CLASS)
}
@Test
fun checkNoArgConstructor() {
- singleClass(JavaFileObjects.forSourceString(CONVERTER_QNAME,
+ singleClass(
+ JavaFileObjects.forSourceString(
+ CONVERTER_QNAME,
"""
package ${CONVERTER.packageName()};
import androidx.room.TypeConverter;
@@ -145,13 +153,17 @@
@TypeConverter
public int x(short y) {return 0;}
}
- """)) { _, _ ->
+ """
+ )
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(TYPE_CONVERTER_MISSING_NOARG_CONSTRUCTOR)
}
@Test
fun checkNoArgConstructor_withStatic() {
- singleClass(JavaFileObjects.forSourceString(CONVERTER_QNAME,
+ singleClass(
+ JavaFileObjects.forSourceString(
+ CONVERTER_QNAME,
"""
package ${CONVERTER.packageName()};
import androidx.room.TypeConverter;
@@ -161,7 +173,9 @@
@TypeConverter
public static int x(short y) {return 0;}
}
- """)) { converter, _ ->
+ """
+ )
+ ) { converter, _ ->
assertThat(converter?.fromTypeName, `is`(TypeName.SHORT))
assertThat(converter?.toTypeName, `is`(TypeName.INT))
assertThat(converter?.isStatic, `is`(true))
@@ -170,7 +184,9 @@
@Test
fun checkPublic() {
- singleClass(JavaFileObjects.forSourceString(CONVERTER_QNAME,
+ singleClass(
+ JavaFileObjects.forSourceString(
+ CONVERTER_QNAME,
"""
package ${CONVERTER.packageName()};
import androidx.room.TypeConverter;
@@ -179,12 +195,14 @@
@TypeConverter static int x(short y) {return 0;}
@TypeConverter private static int y(boolean y) {return 0;}
}
- """)) { converter, _ ->
+ """
+ )
+ ) { converter, _ ->
assertThat(converter?.fromTypeName, `is`(TypeName.SHORT))
assertThat(converter?.toTypeName, `is`(TypeName.INT))
assertThat(converter?.isStatic, `is`(true))
}.failsToCompile().withErrorContaining(TYPE_CONVERTER_MUST_BE_PUBLIC).and()
- .withErrorCount(2)
+ .withErrorCount(2)
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
@@ -197,31 +215,47 @@
val baseConverter = createConverter(list, map, listOf(typeVarT, typeVarK))
val extendingQName = "foo.bar.Extending"
- val extendingClass = JavaFileObjects.forSourceString(extendingQName,
- "package foo.bar;\n" +
- TypeSpec.classBuilder(ClassName.bestGuess(extendingQName)).apply {
- superclass(
- ParameterizedTypeName.get(CONVERTER, String::class.typeName,
- Integer::class.typeName))
- }.build().toString())
+ val extendingClass = JavaFileObjects.forSourceString(
+ extendingQName,
+ "package foo.bar;\n" +
+ TypeSpec.classBuilder(ClassName.bestGuess(extendingQName)).apply {
+ superclass(
+ ParameterizedTypeName.get(
+ CONVERTER, String::class.typeName,
+ Integer::class.typeName
+ )
+ )
+ }.build().toString()
+ )
simpleRun(baseConverter, extendingClass) { invocation ->
val element = invocation.processingEnv.requireTypeElement(extendingQName)
val converter = CustomConverterProcessor(invocation.context, element)
- .process().firstOrNull()
- assertThat(converter?.fromTypeName, `is`(ParameterizedTypeName.get(
- List::class.typeName, String::class.typeName) as TypeName
- ))
- assertThat(converter?.toTypeName, `is`(ParameterizedTypeName.get(Map::class.typeName,
- Integer::class.typeName, String::class.typeName) as TypeName
- ))
+ .process().firstOrNull()
+ assertThat(
+ converter?.fromTypeName,
+ `is`(
+ ParameterizedTypeName.get(
+ List::class.typeName, String::class.typeName
+ ) as TypeName
+ )
+ )
+ assertThat(
+ converter?.toTypeName,
+ `is`(
+ ParameterizedTypeName.get(
+ Map::class.typeName,
+ Integer::class.typeName, String::class.typeName
+ ) as TypeName
+ )
+ )
}.compilesWithoutError()
}
@Test
fun checkDuplicates() {
singleClass(
- createConverter(TypeName.SHORT.box(), TypeName.CHAR.box(), duplicate = true)
+ createConverter(TypeName.SHORT.box(), TypeName.CHAR.box(), duplicate = true)
) { converter, _ ->
assertThat(converter?.fromTypeName, `is`(TypeName.SHORT.box()))
assertThat(converter?.toTypeName, `is`(TypeName.CHAR.box()))
@@ -253,8 +287,10 @@
addMethod(buildMethod("convertF2"))
}
}.build().toString()
- return JavaFileObjects.forSourceString(CONVERTER.toString(),
- "package ${CONVERTER.packageName()};\n$code")
+ return JavaFileObjects.forSourceString(
+ CONVERTER.toString(),
+ "package ${CONVERTER.packageName()};\n$code"
+ )
}
private fun singleClass(
@@ -262,8 +298,10 @@
handler: (CustomTypeConverter?, TestInvocation) -> Unit
): CompileTester {
return simpleRun(*((jfo.toList() + CONTAINER).toTypedArray())) { invocation ->
- val processed = CustomConverterProcessor.findConverters(invocation.context,
- invocation.processingEnv.requireTypeElement("foo.bar.Container"))
+ val processed = CustomConverterProcessor.findConverters(
+ invocation.context,
+ invocation.processingEnv.requireTypeElement("foo.bar.Container")
+ )
handler(processed.converters.firstOrNull()?.custom, invocation)
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
index c290dcc..085b391 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
@@ -52,59 +52,70 @@
@Test
fun testNonAbstract() {
singleDao("@Dao public class MyDao {}") { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.DAO_MUST_BE_AN_ABSTRACT_CLASS_OR_AN_INTERFACE)
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.DAO_MUST_BE_AN_ABSTRACT_CLASS_OR_AN_INTERFACE)
}
@Test
fun testAbstractMethodWithoutQuery() {
- singleDao("""
+ singleDao(
+ """
@Dao public interface MyDao {
int getFoo();
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD)
+ .withErrorContaining(ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD)
}
@Test
fun testAbstractMethodWithoutQueryInLibraryClass() {
val libraryClasspath = compileLibrarySource(
- "test.library.MissingAnnotationsBaseDao",
- """
+ "test.library.MissingAnnotationsBaseDao",
+ """
public interface MissingAnnotationsBaseDao {
int getFoo();
}
- """)
+ """
+ )
singleDao(
- "@Dao public interface MyDao extends test.library.MissingAnnotationsBaseDao {}",
- classpathFiles = libraryClasspath) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD +
- " - getFoo() in test.library.MissingAnnotationsBaseDao")
+ "@Dao public interface MyDao extends test.library.MissingAnnotationsBaseDao {}",
+ classpathFiles = libraryClasspath
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD +
+ " - getFoo() in test.library.MissingAnnotationsBaseDao"
+ )
}
@Test
fun testBothAnnotations() {
- singleDao("""
+ singleDao(
+ """
@Dao public interface MyDao {
@Query("select 1")
@Insert
int getFoo(int x);
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD)
+ ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD
+ )
}
@Test
fun testAbstractClass() {
- singleDao("""
+ singleDao(
+ """
@Dao abstract class MyDao {
@Query("SELECT uid FROM User")
abstract int[] getIds();
}
- """) { dao, _ ->
+ """
+ ) { dao, _ ->
assertThat(dao.queryMethods.size, `is`(1))
val method = dao.queryMethods.first()
assertThat(method.name, `is`("getIds"))
@@ -113,12 +124,14 @@
@Test
fun testInterface() {
- singleDao("""
+ singleDao(
+ """
@Dao interface MyDao {
@Query("SELECT uid FROM User")
abstract int[] getIds();
}
- """) { dao, _ ->
+ """
+ ) { dao, _ ->
assertThat(dao.queryMethods.size, `is`(1))
val method = dao.queryMethods.first()
assertThat(method.name, `is`("getIds"))
@@ -127,14 +140,16 @@
@Test
fun testWithInsertAndQuery() {
- singleDao("""
+ singleDao(
+ """
@Dao abstract class MyDao {
@Query("SELECT uid FROM User")
abstract int[] getIds();
@Insert
abstract void insert(User user);
}
- """) { dao, _ ->
+ """
+ ) { dao, _ ->
assertThat(dao.queryMethods.size, `is`(1))
val method = dao.queryMethods.first()
assertThat(method.name, `is`("getIds"))
@@ -146,12 +161,14 @@
@Test
fun skipQueryVerification() {
- singleDao("""
+ singleDao(
+ """
@Dao @SkipQueryVerification interface MyDao {
@Query("SELECT nonExistingField FROM User")
abstract int[] getIds();
}
- """) { dao, _ ->
+ """
+ ) { dao, _ ->
assertThat(dao.queryMethods.size, `is`(1))
val method = dao.queryMethods.first()
assertThat(method.name, `is`("getIds"))
@@ -160,56 +177,72 @@
@Test
fun suppressedWarnings() {
- singleDao("""
+ singleDao(
+ """
@SuppressWarnings({"ALL", RoomWarnings.CURSOR_MISMATCH})
@Dao interface MyDao {
@Query("SELECT * from user")
abstract User users();
}
- """) { dao, invocation ->
+ """
+ ) { dao, invocation ->
val dbType = invocation.context.processingEnv
- .requireType(RoomTypeNames.ROOM_DB).asDeclaredType()
+ .requireType(RoomTypeNames.ROOM_DB).asDeclaredType()
val daoProcessor =
DaoProcessor(invocation.context, dao.element, dbType, null)
- assertThat(daoProcessor.context.logger
- .suppressedWarnings, `is`(setOf(Warning.ALL, Warning.CURSOR_MISMATCH)))
+ assertThat(
+ daoProcessor.context.logger
+ .suppressedWarnings,
+ `is`(setOf(Warning.ALL, Warning.CURSOR_MISMATCH))
+ )
dao.queryMethods.forEach {
- assertThat(QueryMethodProcessor(
+ assertThat(
+ QueryMethodProcessor(
baseContext = daoProcessor.context,
containing = dao.element.asDeclaredType(),
executableElement = it.element,
- dbVerifier = null).context.logger.suppressedWarnings,
- `is`(setOf(Warning.ALL, Warning.CURSOR_MISMATCH)))
+ dbVerifier = null
+ ).context.logger.suppressedWarnings,
+ `is`(setOf(Warning.ALL, Warning.CURSOR_MISMATCH))
+ )
}
}.compilesWithoutError()
}
@Test
fun suppressedWarningsInheritance() {
- singleDao("""
+ singleDao(
+ """
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
@Dao interface MyDao {
@SuppressWarnings("ALL")
@Query("SELECT * from user")
abstract User users();
}
- """) { dao, invocation ->
+ """
+ ) { dao, invocation ->
val dbType = invocation.context.processingEnv
- .requireType(RoomTypeNames.ROOM_DB).asDeclaredType()
+ .requireType(RoomTypeNames.ROOM_DB).asDeclaredType()
val daoProcessor =
DaoProcessor(invocation.context, dao.element, dbType, null)
- assertThat(daoProcessor.context.logger
- .suppressedWarnings, `is`(setOf(Warning.CURSOR_MISMATCH)))
+ assertThat(
+ daoProcessor.context.logger
+ .suppressedWarnings,
+ `is`(setOf(Warning.CURSOR_MISMATCH))
+ )
dao.queryMethods.forEach {
- assertThat(QueryMethodProcessor(
+ assertThat(
+ QueryMethodProcessor(
baseContext = daoProcessor.context,
containing = dao.element.asDeclaredType(),
executableElement = it.element,
- dbVerifier = null).context.logger.suppressedWarnings,
- `is`(setOf(Warning.ALL, Warning.CURSOR_MISMATCH)))
+ dbVerifier = null
+ ).context.logger.suppressedWarnings,
+ `is`(setOf(Warning.ALL, Warning.CURSOR_MISMATCH))
+ )
}
}.compilesWithoutError()
}
@@ -220,7 +253,7 @@
return
}
singleDao(
- """
+ """
@Dao interface MyDao {
static class Merged extends User {
@Relation(parentColumn = "name", entityColumn = "lastName",
@@ -233,10 +266,12 @@
"""
) { dao, _ ->
assertThat(dao.queryMethods.size, `is`(1))
- assertThat(dao.queryMethods.filterIsInstance<ReadQueryMethod>().first().inTransaction,
- `is`(false))
+ assertThat(
+ dao.queryMethods.filterIsInstance<ReadQueryMethod>().first().inTransaction,
+ `is`(false)
+ )
}.compilesWithoutError()
- .withWarningContaining(ProcessorErrors.TRANSACTION_MISSING_ON_RELATION)
+ .withWarningContaining(ProcessorErrors.TRANSACTION_MISSING_ON_RELATION)
}
@Test
@@ -245,7 +280,7 @@
return
}
singleDao(
- """
+ """
@Dao interface MyDao {
static class Merged extends User {
@Relation(parentColumn = "name", entityColumn = "lastName",
@@ -259,10 +294,12 @@
"""
) { dao, _ ->
assertThat(dao.queryMethods.size, `is`(1))
- assertThat(dao.queryMethods.filterIsInstance<ReadQueryMethod>().first().inTransaction,
- `is`(false))
+ assertThat(
+ dao.queryMethods.filterIsInstance<ReadQueryMethod>().first().inTransaction,
+ `is`(false)
+ )
}.compilesWithoutError()
- .withWarningCount(0)
+ .withWarningCount(0)
}
@Test
@@ -271,7 +308,7 @@
return
}
singleDao(
- """
+ """
@Dao interface MyDao {
static class Merged extends User {
@Relation(parentColumn = "name", entityColumn = "lastName",
@@ -286,10 +323,12 @@
) { dao, _ ->
// test sanity
assertThat(dao.queryMethods.size, `is`(1))
- assertThat(dao.queryMethods.filterIsInstance<ReadQueryMethod>().first().inTransaction,
- `is`(true))
+ assertThat(
+ dao.queryMethods.filterIsInstance<ReadQueryMethod>().first().inTransaction,
+ `is`(true)
+ )
}.compilesWithoutError()
- .withWarningCount(0)
+ .withWarningCount(0)
}
fun singleDao(
@@ -298,44 +337,56 @@
handler: (Dao, TestInvocation) -> Unit
): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(listOf(JavaFileObjects.forSourceString("foo.bar.MyDao",
+ .that(
+ listOf(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyDao",
DAO_PREFIX + inputs.joinToString("\n")
- ), COMMON.USER))
- .apply {
- if (classpathFiles.isNotEmpty()) {
- withClasspath(classpathFiles)
- }
+ ),
+ COMMON.USER
+ )
+ )
+ .apply {
+ if (classpathFiles.isNotEmpty()) {
+ withClasspath(classpathFiles)
}
- .processedWith(TestProcessor.builder()
- .forAnnotations(
- java.lang.SuppressWarnings::class,
- androidx.room.Dao::class,
- androidx.room.Entity::class,
- androidx.room.Relation::class,
- androidx.room.Transaction::class,
- androidx.room.ColumnInfo::class,
- androidx.room.PrimaryKey::class,
- androidx.room.Query::class)
- .nextRunHandler { invocation ->
- val dao = invocation.roundEnv
- .getElementsAnnotatedWith(
- androidx.room.Dao::class.java)
- .first()
- val dbVerifier = if (enableVerification) {
- createVerifierFromEntitiesAndViews(invocation)
- } else {
- null
- }
- val dbType = invocation.context.processingEnv
- .requireType(RoomTypeNames.ROOM_DB)
- .asDeclaredType()
- val parser = DaoProcessor(invocation.context,
- dao.asTypeElement(), dbType, dbVerifier)
-
- val parsedDao = parser.process()
- handler(parsedDao, invocation)
- true
+ }
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(
+ java.lang.SuppressWarnings::class,
+ androidx.room.Dao::class,
+ androidx.room.Entity::class,
+ androidx.room.Relation::class,
+ androidx.room.Transaction::class,
+ androidx.room.ColumnInfo::class,
+ androidx.room.PrimaryKey::class,
+ androidx.room.Query::class
+ )
+ .nextRunHandler { invocation ->
+ val dao = invocation.roundEnv
+ .getElementsAnnotatedWith(
+ androidx.room.Dao::class.java
+ )
+ .first()
+ val dbVerifier = if (enableVerification) {
+ createVerifierFromEntitiesAndViews(invocation)
+ } else {
+ null
}
- .build())
+ val dbType = invocation.context.processingEnv
+ .requireType(RoomTypeNames.ROOM_DB)
+ .asDeclaredType()
+ val parser = DaoProcessor(
+ invocation.context,
+ dao.asTypeElement(), dbType, dbVerifier
+ )
+
+ val parsedDao = parser.process()
+ handler(parsedDao, invocation)
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt
index 60efa6c..4bfe81c 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt
@@ -60,31 +60,38 @@
package foo.bar;
import androidx.room.*;
"""
- val DB1: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.Db1",
- """
+ val DB1: JavaFileObject = JavaFileObjects.forSourceString(
+ "foo.bar.Db1",
+ """
$DATABASE_PREFIX
@Database(entities = {Book.class}, version = 42)
public abstract class Db1 extends RoomDatabase {
abstract BookDao bookDao();
}
- """)
- val DB2: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.Db2",
"""
+ )
+ val DB2: JavaFileObject = JavaFileObjects.forSourceString(
+ "foo.bar.Db2",
+ """
$DATABASE_PREFIX
@Database(entities = {Book.class}, version = 42)
public abstract class Db2 extends RoomDatabase {
abstract BookDao bookDao();
}
- """)
- val DB3: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.Db3",
"""
+ )
+ val DB3: JavaFileObject = JavaFileObjects.forSourceString(
+ "foo.bar.Db3",
+ """
$DATABASE_PREFIX
@Database(entities = {Book.class}, version = 42)
public abstract class Db3 extends RoomDatabase {
}
- """)
- val USER: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.User",
"""
+ )
+ val USER: JavaFileObject = JavaFileObjects.forSourceString(
+ "foo.bar.User",
+ """
package foo.bar;
import androidx.room.*;
@Entity
@@ -93,9 +100,11 @@
int uid;
String name;
}
- """)
- val USER_DAO: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.UserDao",
"""
+ )
+ val USER_DAO: JavaFileObject = JavaFileObjects.forSourceString(
+ "foo.bar.UserDao",
+ """
package foo.bar;
import androidx.room.*;
@Dao
@@ -132,9 +141,11 @@
public int uid;
}
}
- """)
- val BOOK: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.Book",
"""
+ )
+ val BOOK: JavaFileObject = JavaFileObjects.forSourceString(
+ "foo.bar.Book",
+ """
package foo.bar;
import androidx.room.*;
@Entity
@@ -142,9 +153,11 @@
@PrimaryKey
int bookId;
}
- """)
- val BOOK_DAO: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.BookDao",
"""
+ )
+ val BOOK_DAO: JavaFileObject = JavaFileObjects.forSourceString(
+ "foo.bar.BookDao",
+ """
package foo.bar;
import androidx.room.*;
@Dao
@@ -154,17 +167,21 @@
@Insert
public void insert(Book book);
}
- """)
+ """
+ )
}
@Test
fun simple() {
- singleDb("""
+ singleDb(
+ """
@Database(entities = {User.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
abstract UserDao userDao();
}
- """, USER, USER_DAO) { db, _ ->
+ """,
+ USER, USER_DAO
+ ) { db, _ ->
assertThat(db.daoMethods.size, `is`(1))
assertThat(db.entities.size, `is`(1))
}.compilesWithoutError()
@@ -172,40 +189,51 @@
@Test
fun multiple() {
- singleDb("""
+ singleDb(
+ """
@Database(entities = {User.class, Book.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
abstract UserDao userDao();
abstract BookDao bookDao();
}
- """, USER, USER_DAO, BOOK, BOOK_DAO) { db, _ ->
+ """,
+ USER, USER_DAO, BOOK, BOOK_DAO
+ ) { db, _ ->
assertThat(db.daoMethods.size, `is`(2))
assertThat(db.entities.size, `is`(2))
assertThat(db.daoMethods.map { it.name }, `is`(listOf("userDao", "bookDao")))
- assertThat(db.entities.map { it.type.toString() },
- `is`(listOf("foo.bar.User", "foo.bar.Book")))
+ assertThat(
+ db.entities.map { it.type.toString() },
+ `is`(listOf("foo.bar.User", "foo.bar.Book"))
+ )
}.compilesWithoutError()
}
@Test
fun detectMissingBaseClass() {
- singleDb("""
+ singleDb(
+ """
@Database(entities = {User.class, Book.class}, version = 42)
public abstract class MyDb {
}
- """, USER, BOOK) { _, _ ->
+ """,
+ USER, BOOK
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.DB_MUST_EXTEND_ROOM_DB)
}
@Test
fun detectMissingTable() {
singleDb(
- """
+ """
@Database(entities = {Book.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
abstract BookDao bookDao();
}
- """, BOOK, JavaFileObjects.forSourceString("foo.bar.BookDao",
+ """,
+ BOOK,
+ JavaFileObjects.forSourceString(
+ "foo.bar.BookDao",
"""
package foo.bar;
import androidx.room.*;
@@ -214,18 +242,24 @@
@Query("SELECT * FROM nonExistentTable")
public java.util.List<Book> loadAllBooks();
}
- """)) { _, _ ->
+ """
+ )
+ ) { _, _ ->
}.failsToCompile().withErrorContaining("no such table: nonExistentTable")
}
@Test
fun detectDuplicateTableNames() {
- singleDb("""
+ singleDb(
+ """
@Database(entities = {User.class, AnotherClass.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
abstract UserDao userDao();
}
- """, USER, USER_DAO, JavaFileObjects.forSourceString("foo.bar.AnotherClass",
+ """,
+ USER, USER_DAO,
+ JavaFileObjects.forSourceString(
+ "foo.bar.AnotherClass",
"""
package foo.bar;
import androidx.room.*;
@@ -234,18 +268,22 @@
@PrimaryKey
int uid;
}
- """)) { _, _ ->
+ """
+ )
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.duplicateTableNames("user",
- listOf("foo.bar.User", "foo.bar.AnotherClass"))
+ ProcessorErrors.duplicateTableNames(
+ "user",
+ listOf("foo.bar.User", "foo.bar.AnotherClass")
+ )
)
}
@Test
fun detectMissingEntityAnnotationInLibraryClass() {
val libraryClasspath = compileLibrarySource(
- "test.library.MissingEntityAnnotationPojo",
- """
+ "test.library.MissingEntityAnnotationPojo",
+ """
public class MissingEntityAnnotationPojo {
@PrimaryKey
private long id;
@@ -253,42 +291,52 @@
public void setId(int id) {this.id = id;}
public long getId() {return this.id;}
}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {test.library.MissingEntityAnnotationPojo.class}, version = 1)
public abstract class MyDb extends RoomDatabase {}
""",
- classpathFiles = libraryClasspath) { _, _ ->
+ classpathFiles = libraryClasspath
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY +
- " - test.library.MissingEntityAnnotationPojo")
+ ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY +
+ " - test.library.MissingEntityAnnotationPojo"
+ )
}
@Test
fun detectMissingDaoAnnotationInLibraryClass() {
val libraryClasspath = compileLibrarySource(
- "test.library.MissingAnnotationsBaseDao",
- """
+ "test.library.MissingAnnotationsBaseDao",
+ """
public interface MissingAnnotationsBaseDao {
int getFoo();
}
- """)
+ """
+ )
- singleDb("""
+ singleDb(
+ """
@Database(entities = {User.class}, version = 1)
public abstract class MyDb extends RoomDatabase {
abstract test.library.MissingAnnotationsBaseDao getBadDao();
}
- """, USER, classpathFiles = libraryClasspath) { _, _ ->
+ """,
+ USER, classpathFiles = libraryClasspath
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.DAO_MUST_BE_ANNOTATED_WITH_DAO +
- " - test.library.MissingAnnotationsBaseDao")
+ ProcessorErrors.DAO_MUST_BE_ANNOTATED_WITH_DAO +
+ " - test.library.MissingAnnotationsBaseDao"
+ )
}
@Test
fun detectMissingExternalContentEntity() {
- val userNameFtsSrc = JavaFileObjects.forSourceString("foo.bar.UserNameFts",
- """
+ val userNameFtsSrc = JavaFileObjects.forSourceString(
+ "foo.bar.UserNameFts",
+ """
package foo.bar;
import androidx.room.*;
@@ -297,25 +345,35 @@
public class UserNameFts {
String name;
}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {UserNameFts.class}, version = 1)
public abstract class MyDb extends RoomDatabase {}
- """, USER, userNameFtsSrc) { _, _ ->
- }.failsToCompile().withErrorContaining(ProcessorErrors.missingExternalContentEntity(
- "foo.bar.UserNameFts", "foo.bar.User"))
+ """,
+ USER, userNameFtsSrc
+ ) { _, _ ->
+ }.failsToCompile().withErrorContaining(
+ ProcessorErrors.missingExternalContentEntity(
+ "foo.bar.UserNameFts", "foo.bar.User"
+ )
+ )
}
@Test
fun skipBadQueryVerification() {
singleDb(
- """
+ """
@SkipQueryVerification
@Database(entities = {Book.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
abstract BookDao bookDao();
}
- """, BOOK, JavaFileObjects.forSourceString("foo.bar.BookDao",
+ """,
+ BOOK,
+ JavaFileObjects.forSourceString(
+ "foo.bar.BookDao",
"""
package foo.bar;
import androidx.room.*;
@@ -324,14 +382,17 @@
@Query("SELECT nonExistingField FROM Book")
public java.util.List<Book> loadAllBooks();
}
- """)) { _, _ ->
+ """
+ )
+ ) { _, _ ->
}.compilesWithoutError()
}
@Test
fun multipleDatabases() {
- val db1_2 = JavaFileObjects.forSourceString("foo.barx.Db1",
- """
+ val db1_2 = JavaFileObjects.forSourceString(
+ "foo.barx.Db1",
+ """
package foo.barx;
import androidx.room.*;
import foo.bar.*;
@@ -339,65 +400,82 @@
public abstract class Db1 extends RoomDatabase {
abstract BookDao bookDao();
}
- """)
+ """
+ )
Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(listOf(BOOK, BOOK_DAO, DB1, DB2, db1_2))
- .processedWith(RoomProcessor())
- .compilesWithoutError()
- .and()
- .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar", "Db1_Impl.class")
- .and()
- .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar", "Db2_Impl.class")
- .and()
- .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.barx", "Db1_Impl.class")
- .and()
- .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar",
- "BookDao_Db1_0_Impl.class")
- .and()
- .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar",
- "BookDao_Db1_1_Impl.class")
- .and()
- .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar",
- "BookDao_Db2_Impl.class")
+ .that(listOf(BOOK, BOOK_DAO, DB1, DB2, db1_2))
+ .processedWith(RoomProcessor())
+ .compilesWithoutError()
+ .and()
+ .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar", "Db1_Impl.class")
+ .and()
+ .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar", "Db2_Impl.class")
+ .and()
+ .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.barx", "Db1_Impl.class")
+ .and()
+ .generatesFileNamed(
+ StandardLocation.CLASS_OUTPUT, "foo.bar",
+ "BookDao_Db1_0_Impl.class"
+ )
+ .and()
+ .generatesFileNamed(
+ StandardLocation.CLASS_OUTPUT, "foo.bar",
+ "BookDao_Db1_1_Impl.class"
+ )
+ .and()
+ .generatesFileNamed(
+ StandardLocation.CLASS_OUTPUT, "foo.bar",
+ "BookDao_Db2_Impl.class"
+ )
}
@Test
fun twoDaoMethodsForTheSameDao() {
singleDb(
- """
+ """
@Database(entities = {User.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
abstract UserDao userDao();
abstract UserDao userDao2();
}
- """, USER, USER_DAO) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.DAO_METHOD_CONFLICTS_WITH_OTHERS)
- .and()
- .withErrorContaining(ProcessorErrors.duplicateDao(
- ClassName.get("foo.bar", "UserDao"), listOf("userDao", "userDao2")
- ))
+ """,
+ USER, USER_DAO
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.DAO_METHOD_CONFLICTS_WITH_OTHERS)
+ .and()
+ .withErrorContaining(
+ ProcessorErrors.duplicateDao(
+ ClassName.get("foo.bar", "UserDao"), listOf("userDao", "userDao2")
+ )
+ )
}
@Test
fun suppressedWarnings() {
singleDb(
- """
+ """
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
@Database(entities = {User.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
abstract UserDao userDao();
}
- """, USER, USER_DAO) { db, invocation ->
- assertThat(DatabaseProcessor(invocation.context, db.element)
- .context.logger.suppressedWarnings, `is`(setOf(Warning.CURSOR_MISMATCH)))
+ """,
+ USER, USER_DAO
+ ) { db, invocation ->
+ assertThat(
+ DatabaseProcessor(invocation.context, db.element)
+ .context.logger.suppressedWarnings,
+ `is`(setOf(Warning.CURSOR_MISMATCH))
+ )
}.compilesWithoutError()
}
@Test
fun duplicateIndexNames() {
- val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
- """
+ val entity1 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity1",
+ """
package foo.bar;
import androidx.room.*;
@Entity(indices = {@Index(name ="index_name", value = {"name"})})
@@ -406,10 +484,12 @@
int uid;
String name;
}
- """)
-
- val entity2 = JavaFileObjects.forSourceString("foo.bar.Entity2",
"""
+ )
+
+ val entity2 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity2",
+ """
package foo.bar;
import androidx.room.*;
@Entity(indices = {@Index(name ="index_name", value = {"anotherName"})})
@@ -418,22 +498,29 @@
int uid;
String anotherName;
}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {Entity1.class, Entity2.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
}
- """, entity1, entity2) { _, _ ->
+ """,
+ entity1, entity2
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.duplicateIndexInDatabase("index_name",
- listOf("foo.bar.Entity1 > index_name", "foo.bar.Entity2 > index_name"))
+ ProcessorErrors.duplicateIndexInDatabase(
+ "index_name",
+ listOf("foo.bar.Entity1 > index_name", "foo.bar.Entity2 > index_name")
+ )
)
}
@Test
fun foreignKey_missingParent() {
- val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
- """
+ val entity1 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity1",
+ """
package foo.bar;
import androidx.room.*;
@Entity(foreignKeys = @ForeignKey(entity = ${COMMON.USER_TYPE_NAME}.class,
@@ -444,21 +531,26 @@
int uid;
String name;
}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {Entity1.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
}
- """, entity1, COMMON.USER) { _, _ ->
+ """,
+ entity1, COMMON.USER
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.foreignKeyMissingParentEntityInDatabase("User", "foo.bar.Entity1")
+ ProcessorErrors.foreignKeyMissingParentEntityInDatabase("User", "foo.bar.Entity1")
)
}
@Test
fun foreignKey_missingParentIndex() {
- val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
- """
+ val entity1 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity1",
+ """
package foo.bar;
import androidx.room.*;
@Entity(foreignKeys = @ForeignKey(entity = ${COMMON.USER_TYPE_NAME}.class,
@@ -469,26 +561,31 @@
int uid;
String name;
}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {Entity1.class, User.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
}
- """, entity1, COMMON.USER) { _, _ ->
+ """,
+ entity1, COMMON.USER
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.foreignKeyMissingIndexInParent(
- parentEntity = COMMON.USER_TYPE_NAME.toString(),
- parentColumns = listOf("lastName"),
- childEntity = "foo.bar.Entity1",
- childColumns = listOf("name")
- )
+ ProcessorErrors.foreignKeyMissingIndexInParent(
+ parentEntity = COMMON.USER_TYPE_NAME.toString(),
+ parentColumns = listOf("lastName"),
+ childEntity = "foo.bar.Entity1",
+ childColumns = listOf("name")
+ )
)
}
@Test
fun foreignKey_goodWithPrimaryKey() {
- val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
- """
+ val entity1 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity1",
+ """
package foo.bar;
import androidx.room.*;
@Entity(foreignKeys = @ForeignKey(entity = Entity2.class,
@@ -500,10 +597,12 @@
int parentId;
String name;
}
- """)
-
- val entity2 = JavaFileObjects.forSourceString("foo.bar.Entity2",
"""
+ )
+
+ val entity2 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity2",
+ """
package foo.bar;
import androidx.room.*;
@Entity
@@ -512,19 +611,24 @@
int uid;
String anotherName;
}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {Entity1.class, Entity2.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
}
- """, entity1, entity2) { _, _ ->
+ """,
+ entity1, entity2
+ ) { _, _ ->
}.compilesWithoutError()
}
@Test
fun foreignKey_missingParentColumn() {
- val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
- """
+ val entity1 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity1",
+ """
package foo.bar;
import androidx.room.*;
@Entity(foreignKeys = @ForeignKey(entity = Entity2.class,
@@ -536,10 +640,12 @@
String name;
String name2;
}
- """)
-
- val entity2 = JavaFileObjects.forSourceString("foo.bar.Entity2",
"""
+ )
+
+ val entity2 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity2",
+ """
package foo.bar;
import androidx.room.*;
@Entity
@@ -548,22 +654,29 @@
int uid;
String anotherName;
}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {Entity1.class, Entity2.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
}
- """, entity1, entity2) { _, _ ->
+ """,
+ entity1, entity2
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.foreignKeyParentColumnDoesNotExist("foo.bar.Entity2",
- "anotherName2", listOf("uid", "anotherName"))
+ ProcessorErrors.foreignKeyParentColumnDoesNotExist(
+ "foo.bar.Entity2",
+ "anotherName2", listOf("uid", "anotherName")
+ )
)
}
@Test
fun foreignKey_goodWithIndex() {
- val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
- """
+ val entity1 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity1",
+ """
package foo.bar;
import androidx.room.*;
@Entity(foreignKeys = @ForeignKey(entity = Entity2.class,
@@ -575,10 +688,12 @@
String name;
String name2;
}
- """)
-
- val entity2 = JavaFileObjects.forSourceString("foo.bar.Entity2",
"""
+ )
+
+ val entity2 = JavaFileObjects.forSourceString(
+ "foo.bar.Entity2",
+ """
package foo.bar;
import androidx.room.*;
@Entity(indices = @Index(value = {"anotherName2", "anotherName"}, unique = true))
@@ -588,35 +703,43 @@
String anotherName;
String anotherName2;
}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {Entity1.class, Entity2.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
}
- """, entity1, entity2) { _, _ ->
+ """,
+ entity1, entity2
+ ) { _, _ ->
}.compilesWithoutError()
}
@Test
fun insertNotAReferencedEntity() {
- singleDb("""
+ singleDb(
+ """
@Database(entities = {User.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
abstract BookDao bookDao();
}
- """, USER, USER_DAO, BOOK, BOOK_DAO) { _, _ ->
+ """,
+ USER, USER_DAO, BOOK, BOOK_DAO
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.shortcutEntityIsNotInDatabase(
- database = "foo.bar.MyDb",
- dao = "foo.bar.BookDao",
- entity = "foo.bar.Book"
- )
+ ProcessorErrors.shortcutEntityIsNotInDatabase(
+ database = "foo.bar.MyDb",
+ dao = "foo.bar.BookDao",
+ entity = "foo.bar.Book"
+ )
)
}
@Test
fun cache_entity() {
- singleDb("""
+ singleDb(
+ """
@Database(entities = {User.class}, version = 42)
@SkipQueryVerification
public abstract class MyDb extends RoomDatabase {
@@ -638,7 +761,9 @@
public static java.util.Date foo(Long input) {return null;}
}
}
- """, USER, USER_DAO) { db, _ ->
+ """,
+ USER, USER_DAO
+ ) { db, _ ->
val userDao = db.daoMethods.first().dao
val insertionMethod = userDao.insertionMethods.find { it.name == "insert" }
assertThat(insertionMethod, notNullValue())
@@ -649,8 +774,10 @@
val adapter = loadOne?.queryResultBinder?.adapter?.rowAdapter
assertThat("test sanity", adapter, instanceOf(EntityRowAdapter::class.java))
val adapterEntity = (adapter as EntityRowAdapter).entity
- assertThat(adapterEntity,
- sameInstance(insertionMethod?.entities?.values?.first()?.pojo))
+ assertThat(
+ adapterEntity,
+ sameInstance(insertionMethod?.entities?.values?.first()?.pojo)
+ )
val withConverter = userDao.queryMethods
.filterIsInstance<ReadQueryMethod>()
@@ -659,8 +786,10 @@
val convAdapter = withConverter?.queryResultBinder?.adapter?.rowAdapter
assertThat("test sanity", adapter, instanceOf(EntityRowAdapter::class.java))
val convAdapterEntity = (convAdapter as EntityRowAdapter).entity
- assertThat(convAdapterEntity,
- not(sameInstance(insertionMethod?.entities?.values?.first()?.pojo)))
+ assertThat(
+ convAdapterEntity,
+ not(sameInstance(insertionMethod?.entities?.values?.first()?.pojo))
+ )
assertThat(convAdapterEntity, notNullValue())
assertThat(adapterEntity, notNullValue())
@@ -669,12 +798,15 @@
@Test
fun cache_pojo() {
- singleDb("""
+ singleDb(
+ """
@Database(entities = {User.class}, version = 42)
public abstract class MyDb extends RoomDatabase {
public abstract UserDao userDao();
}
- """, USER, USER_DAO) { db, _ ->
+ """,
+ USER, USER_DAO
+ ) { db, _ ->
val userDao = db.daoMethods.first().dao
val loadOne = userDao.queryMethods
.filterIsInstance<ReadQueryMethod>()
@@ -709,139 +841,182 @@
@Test
fun daoConstructor_RoomDatabase() {
assertConstructor(listOf(DB1), "BookDao(RoomDatabase db) {}")
- .compilesWithoutError()
+ .compilesWithoutError()
}
@Test
fun daoConstructor_specificDatabase() {
assertConstructor(listOf(DB1), "BookDao(Db1 db) {}")
- .compilesWithoutError()
+ .compilesWithoutError()
}
@Test
fun daoConstructor_wrongDatabase() {
assertConstructor(listOf(DB1, DB3), "BookDao(Db3 db) {}")
- .failsToCompile()
- .withErrorContaining(ProcessorErrors
- .daoMustHaveMatchingConstructor("foo.bar.BookDao", "foo.bar.Db1"))
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors
+ .daoMustHaveMatchingConstructor("foo.bar.BookDao", "foo.bar.Db1")
+ )
}
@Test
fun daoConstructor_multipleDatabases_RoomDatabase() {
assertConstructor(listOf(DB1, DB2), "BookDao(RoomDatabase db) {}")
- .compilesWithoutError()
+ .compilesWithoutError()
}
@Test
fun daoConstructor_multipleDatabases_specificDatabases() {
- assertConstructor(listOf(DB1, DB2), """
+ assertConstructor(
+ listOf(DB1, DB2),
+ """
BookDao(Db1 db) {}
BookDao(Db2 db) {}
- """)
- .compilesWithoutError()
+ """
+ )
+ .compilesWithoutError()
}
@Test
fun daoConstructor_multipleDatabases_empty() {
- assertConstructor(listOf(DB1, DB2), """
+ assertConstructor(
+ listOf(DB1, DB2),
+ """
BookDao(Db1 db) {}
BookDao() {} // Db2 uses this
- """)
- .compilesWithoutError()
+ """
+ )
+ .compilesWithoutError()
}
@Test
fun daoConstructor_multipleDatabases_noMatch() {
- assertConstructor(listOf(DB1, DB2), """
+ assertConstructor(
+ listOf(DB1, DB2),
+ """
BookDao(Db1 db) {}
- """)
- .failsToCompile()
- .withErrorContaining(ProcessorErrors
- .daoMustHaveMatchingConstructor("foo.bar.BookDao", "foo.bar.Db2"))
+ """
+ )
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors
+ .daoMustHaveMatchingConstructor("foo.bar.BookDao", "foo.bar.Db2")
+ )
}
@Test
fun view_duplicateNames() {
- val view1 = JavaFileObjects.forSourceString("foo.bar.View1",
- """
+ val view1 = JavaFileObjects.forSourceString(
+ "foo.bar.View1",
+ """
package foo.bar;
import androidx.room.*;
@DatabaseView(value = "SELECT * FROM User", viewName = "SameName")
public class View1 {}
- """)
- val view2 = JavaFileObjects.forSourceString("foo.bar.View2",
"""
+ )
+ val view2 = JavaFileObjects.forSourceString(
+ "foo.bar.View2",
+ """
package foo.bar;
import androidx.room.*;
@DatabaseView(value = "SELECT * FROM User", viewName = "SameName")
public class View2 {}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {User.class},
views = {View1.class, View2.class},
version = 42)
public abstract class MyDb extends RoomDatabase {
}
- """, USER, view1, view2) { _, _ ->
- }.failsToCompile().withErrorContaining(ProcessorErrors.duplicateTableNames("samename",
- listOf("foo.bar.View1", "foo.bar.View2")))
+ """,
+ USER, view1, view2
+ ) { _, _ ->
+ }.failsToCompile().withErrorContaining(
+ ProcessorErrors.duplicateTableNames(
+ "samename",
+ listOf("foo.bar.View1", "foo.bar.View2")
+ )
+ )
}
@Test
fun view_duplicateNamesWithEntity() {
- val view1 = JavaFileObjects.forSourceString("foo.bar.View1",
- """
+ val view1 = JavaFileObjects.forSourceString(
+ "foo.bar.View1",
+ """
package foo.bar;
import androidx.room.*;
@DatabaseView(value = "SELECT * FROM User", viewName = "Book")
public class View1 {}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {User.class, Book.class},
views = {View1.class},
version = 42)
public abstract class MyDb extends RoomDatabase {
}
- """, USER, BOOK, view1) { _, _ ->
- }.failsToCompile().withErrorContaining(ProcessorErrors.duplicateTableNames("book",
- listOf("foo.bar.Book", "foo.bar.View1")))
+ """,
+ USER, BOOK, view1
+ ) { _, _ ->
+ }.failsToCompile().withErrorContaining(
+ ProcessorErrors.duplicateTableNames(
+ "book",
+ listOf("foo.bar.Book", "foo.bar.View1")
+ )
+ )
}
@Test
fun view_circularReference() {
- val view1 = JavaFileObjects.forSourceString("foo.bar.View1",
- """
+ val view1 = JavaFileObjects.forSourceString(
+ "foo.bar.View1",
+ """
package foo.bar;
import androidx.room.*;
@DatabaseView("SELECT * FROM View2")
public class View1 {}
- """)
- val view2 = JavaFileObjects.forSourceString("foo.bar.View2",
"""
+ )
+ val view2 = JavaFileObjects.forSourceString(
+ "foo.bar.View2",
+ """
package foo.bar;
import androidx.room.*;
@DatabaseView("SELECT * FROM View1")
public class View2 {}
- """)
- singleDb("""
+ """
+ )
+ singleDb(
+ """
@Database(entities = {User.class},
views = {View1.class, View2.class},
version = 42)
public abstract class MyDb extends RoomDatabase {
}
- """, USER, view1, view2) { _, _ ->
+ """,
+ USER, view1, view2
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.viewCircularReferenceDetected(listOf("View1", "View2")))
+ ProcessorErrors.viewCircularReferenceDetected(listOf("View1", "View2"))
+ )
}
@Test
fun resolveDatabaseViews_nested() {
- resolveDatabaseViews(mapOf(
+ resolveDatabaseViews(
+ mapOf(
"Q" to setOf("B", "P"),
"P" to setOf("A"),
"S" to setOf("A", "Q"),
"R" to setOf("C", "Q")
- )) { views ->
+ )
+ ) { views ->
assertThat(views.size, `is`(4))
views[0].let {
assertThat(it.viewName, `is`(equalTo("P")))
@@ -881,14 +1056,17 @@
@Test
fun resolveDatabaseViews_circular() {
- resolveDatabaseViews(mapOf(
+ resolveDatabaseViews(
+ mapOf(
"P" to setOf("Q"),
"Q" to setOf("P"),
"R" to setOf("A"),
"S" to setOf("R", "B")
- )) { _ ->
+ )
+ ) { _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.viewCircularReferenceDetected(listOf("P", "Q")))
+ ProcessorErrors.viewCircularReferenceDetected(listOf("P", "Q"))
+ )
}
private fun resolveDatabaseViews(
@@ -897,54 +1075,58 @@
): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
.that(listOf(DB3, BOOK))
- .processedWith(TestProcessor.builder()
- .forAnnotations(androidx.room.Database::class)
- .nextRunHandler { invocation ->
- val database = invocation.roundEnv
- .getElementsAnnotatedWith(
- androidx.room.Database::class.java
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(androidx.room.Database::class)
+ .nextRunHandler { invocation ->
+ val database = invocation.roundEnv
+ .getElementsAnnotatedWith(
+ androidx.room.Database::class.java
+ )
+ .first()
+ val processor = DatabaseProcessor(
+ invocation.context,
+ database.asTypeElement()
)
- .first()
- val processor = DatabaseProcessor(
- invocation.context,
- database.asTypeElement()
- )
- val list = views.map { (viewName, names) ->
- DatabaseView(
- element = mock(XTypeElement::class.java),
- viewName = viewName,
- query = ParsedQuery(
- "", QueryType.SELECT, emptyList(),
- names.map { Table(it, it) }.toSet(),
- emptyList(), false
- ),
- type = mock(XDeclaredType::class.java),
- fields = emptyList(),
- embeddedFields = emptyList(),
- constructor = null
- )
+ val list = views.map { (viewName, names) ->
+ DatabaseView(
+ element = mock(XTypeElement::class.java),
+ viewName = viewName,
+ query = ParsedQuery(
+ "", QueryType.SELECT, emptyList(),
+ names.map { Table(it, it) }.toSet(),
+ emptyList(), false
+ ),
+ type = mock(XDeclaredType::class.java),
+ fields = emptyList(),
+ embeddedFields = emptyList(),
+ constructor = null
+ )
+ }
+ val resolvedViews = processor.resolveDatabaseViews(list)
+ body(resolvedViews)
+ true
}
- val resolvedViews = processor.resolveDatabaseViews(list)
- body(resolvedViews)
- true
- }
- .build())
+ .build()
+ )
}
fun assertConstructor(dbs: List<JavaFileObject>, constructor: String): CompileTester {
- val bookDao = JavaFileObjects.forSourceString("foo.bar.BookDao",
- """
+ val bookDao = JavaFileObjects.forSourceString(
+ "foo.bar.BookDao",
+ """
package foo.bar;
import androidx.room.*;
@Dao
public abstract class BookDao {
$constructor
}
- """)
+ """
+ )
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(listOf(BOOK, bookDao) + dbs)
- .processedWith(RoomProcessor())
+ .that(listOf(BOOK, bookDao) + dbs)
+ .processedWith(RoomProcessor())
}
fun singleDb(
@@ -954,28 +1136,36 @@
handler: (Database, TestInvocation) -> Unit
): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(otherFiles.toMutableList() +
- JavaFileObjects.forSourceString("foo.bar.MyDb",
+ .that(
+ otherFiles.toMutableList() +
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyDb",
DATABASE_PREFIX + input
- ))
- .apply {
- if (classpathFiles.isNotEmpty()) {
- withClasspath(classpathFiles)
- }
+ )
+ )
+ .apply {
+ if (classpathFiles.isNotEmpty()) {
+ withClasspath(classpathFiles)
}
- .processedWith(TestProcessor.builder()
- .forAnnotations(androidx.room.Database::class)
- .nextRunHandler { invocation ->
- val entity = invocation.roundEnv
- .getElementsAnnotatedWith(
- androidx.room.Database::class.java)
- .first()
- val parser = DatabaseProcessor(invocation.context,
- entity.asTypeElement())
- val parsedDb = parser.process()
- handler(parsedDb, invocation)
- true
- }
- .build())
+ }
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(androidx.room.Database::class)
+ .nextRunHandler { invocation ->
+ val entity = invocation.roundEnv
+ .getElementsAnnotatedWith(
+ androidx.room.Database::class.java
+ )
+ .first()
+ val parser = DatabaseProcessor(
+ invocation.context,
+ entity.asTypeElement()
+ )
+ val parsedDb = parser.process()
+ handler(parsedDb, invocation)
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/DatabaseViewProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/DatabaseViewProcessorTest.kt
index 94b3f84..7821b23 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/DatabaseViewProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/DatabaseViewProcessorTest.kt
@@ -46,15 +46,20 @@
"""
val ENTITIES = listOf(
- JavaFileObjects.forSourceString("foo.bar.Team", DATABASE_PREFIX + """
+ JavaFileObjects.forSourceString(
+ "foo.bar.Team",
+ DATABASE_PREFIX + """
@Entity
public class Team {
@PrimaryKey
public int id;
public String name;
}
- """),
- JavaFileObjects.forSourceString("foo.bar.Employee", DATABASE_PREFIX + """
+ """
+ ),
+ JavaFileObjects.forSourceString(
+ "foo.bar.Employee",
+ DATABASE_PREFIX + """
@Entity
public class Employee {
@PrimaryKey
@@ -64,17 +69,21 @@
public int teamId;
public Integer managerId;
}
- """)
+ """
+ )
)
}
@Test
fun basic() {
- singleView("foo.bar.MyView", """
+ singleView(
+ "foo.bar.MyView",
+ """
@DatabaseView("SELECT * FROM Team")
public class MyView {
}
- """) { view, _ ->
+ """
+ ) { view, _ ->
assertThat(view.query.original).isEqualTo("SELECT * FROM Team")
assertThat(view.query.errors).isEmpty()
assertThat(view.query.tables).hasSize(1)
@@ -85,91 +94,122 @@
val resultInfo = view.query.resultInfo!!
assertThat(resultInfo.columns).hasSize(2)
assertThat(resultInfo.columns).containsAtLeast(
- ColumnInfo("id", SQLTypeAffinity.INTEGER),
- ColumnInfo("name", SQLTypeAffinity.TEXT))
+ ColumnInfo("id", SQLTypeAffinity.INTEGER),
+ ColumnInfo("name", SQLTypeAffinity.TEXT)
+ )
assertThat(view.viewName).isEqualTo("MyView")
}.compilesWithoutError()
}
@Test
fun viewName() {
- singleView("foo.bar.MyView", """
+ singleView(
+ "foo.bar.MyView",
+ """
@DatabaseView(value = "SELECT * FROM Team", viewName = "abc")
public class MyView {
}
- """) { view, _ ->
+ """
+ ) { view, _ ->
assertThat(view.viewName).isEqualTo("abc")
}.compilesWithoutError()
}
@Test
fun viewName_sqlite() {
- singleView("foo.bar.MyView", """
+ singleView(
+ "foo.bar.MyView",
+ """
@DatabaseView(value = "SELECT * FROM Team", viewName = "sqlite_bad_name")
public class MyView {
}
- """, verify = false) { _, _ ->
+ """,
+ verify = false
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.VIEW_NAME_CANNOT_START_WITH_SQLITE)
}
@Test
fun nonSelect() {
- singleView("foo.bar.MyView", """
+ singleView(
+ "foo.bar.MyView",
+ """
@DatabaseView("DELETE FROM Team")
public class MyView {
}
- """, verify = false) { _, _ ->
+ """,
+ verify = false
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.VIEW_QUERY_MUST_BE_SELECT)
}
@Test
fun arguments() {
- singleView("foo.bar.MyView", """
+ singleView(
+ "foo.bar.MyView",
+ """
@DatabaseView("SELECT * FROM Team WHERE id = :id")
public class MyView {
}
- """, verify = false) { _, _ ->
+ """,
+ verify = false
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.VIEW_QUERY_CANNOT_TAKE_ARGUMENTS)
}
@Test
fun emptyQuery() {
- singleView("foo.bar.MyView", """
+ singleView(
+ "foo.bar.MyView",
+ """
@DatabaseView("")
public class MyView {
}
- """, verify = false) { _, _ ->
+ """,
+ verify = false
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ParserErrors.NOT_ONE_QUERY)
}
@Test
fun missingAnnotation() {
- singleView("foo.bar.MyView", """
+ singleView(
+ "foo.bar.MyView",
+ """
public class MyView {
}
- """, verify = false) { _, _ ->
+ """,
+ verify = false
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.VIEW_MUST_BE_ANNOTATED_WITH_DATABASE_VIEW)
+ ProcessorErrors.VIEW_MUST_BE_ANNOTATED_WITH_DATABASE_VIEW
+ )
}
@Test
fun referenceOtherView() {
- val summary = JavaFileObjects.forSourceString("foo.bar.EmployeeSummary",
- DATABASE_PREFIX + """
+ val summary = JavaFileObjects.forSourceString(
+ "foo.bar.EmployeeSummary",
+ DATABASE_PREFIX + """
@DatabaseView("SELECT id, name, managerId FROM Employee")
public class EmployeeSummary {
public int id;
public String name;
public Integer managerId;
}
- """)
- singleView("foo.bar.EmployeeName", """
+ """
+ )
+ singleView(
+ "foo.bar.EmployeeName",
+ """
@DatabaseView("SELECT id, name FROM EmployeeSummary")
public class EmployeeName {
public int id;
public String name;
}
- """, ENTITIES + summary) { view, _ ->
+ """,
+ ENTITIES + summary
+ ) { view, _ ->
assertThat(view.viewName).isEqualTo("EmployeeName")
}.compilesWithoutError()
}
@@ -182,30 +222,35 @@
handler: (view: DatabaseView, invocation: TestInvocation) -> Unit
): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(jfos + JavaFileObjects.forSourceString(name, DATABASE_PREFIX + input))
- .processedWith(TestProcessor.builder()
- .forAnnotations(
- androidx.room.DatabaseView::class,
- androidx.room.Entity::class,
- androidx.room.PrimaryKey::class,
- androidx.room.Embedded::class,
- androidx.room.ColumnInfo::class,
- NonNull::class)
- .nextRunHandler { invocation ->
- val view = invocation.roundEnv
- .rootElements
- .first { it.toString() == name }
- val verifier = if (verify) {
- createVerifierFromEntitiesAndViews(invocation)
- } else null
- val processor = DatabaseViewProcessor(invocation.context,
- view.asTypeElement())
- val processedView = processor.process()
- processedView.query.resultInfo =
- verifier?.analyze(processedView.query.original)
- handler(processedView, invocation)
- true
- }
- .build())
+ .that(jfos + JavaFileObjects.forSourceString(name, DATABASE_PREFIX + input))
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(
+ androidx.room.DatabaseView::class,
+ androidx.room.Entity::class,
+ androidx.room.PrimaryKey::class,
+ androidx.room.Embedded::class,
+ androidx.room.ColumnInfo::class,
+ NonNull::class
+ )
+ .nextRunHandler { invocation ->
+ val view = invocation.roundEnv
+ .rootElements
+ .first { it.toString() == name }
+ val verifier = if (verify) {
+ createVerifierFromEntitiesAndViews(invocation)
+ } else null
+ val processor = DatabaseViewProcessor(
+ invocation.context,
+ view.asTypeElement()
+ )
+ val processedView = processor.process()
+ processedView.query.resultInfo =
+ verifier?.analyze(processedView.query.original)
+ handler(processedView, invocation)
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/EntityNameMatchingVariationsTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/EntityNameMatchingVariationsTest.kt
index f8cf008..753a1d7 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/EntityNameMatchingVariationsTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/EntityNameMatchingVariationsTest.kt
@@ -30,7 +30,7 @@
@RunWith(Parameterized::class)
class EntityNameMatchingVariationsTest(triple: Triple<String, String, String>) :
- BaseEntityParserTest() {
+ BaseEntityParserTest() {
val fieldName = triple.first
val getterName = triple.second
val setterName = triple.third
@@ -53,22 +53,30 @@
@Test
fun testSuccessfulParamToMethodMatching() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int $fieldName;
public int $getterName() { return $fieldName; }
public void $setterName(int id) { this.$fieldName = id; }
- """) { entity, invocation ->
+ """
+ ) { entity, invocation ->
assertThat(entity.type.toString(), `is`("foo.bar.MyEntity"))
assertThat(entity.fields.size, `is`(1))
val field = entity.fields.first()
val intType = invocation.processingEnv.requireType(TypeName.INT)
- assertThat(field, `is`(Field(
- element = field.element,
- name = fieldName,
- type = intType,
- columnName = fieldName,
- affinity = SQLTypeAffinity.INTEGER)))
+ assertThat(
+ field,
+ `is`(
+ Field(
+ element = field.element,
+ name = fieldName,
+ type = intType,
+ columnName = fieldName,
+ affinity = SQLTypeAffinity.INTEGER
+ )
+ )
+ )
assertThat(field.setter, `is`(FieldSetter(setterName, intType, CallType.METHOD)))
assertThat(field.getter, `is`(FieldGetter(getterName, intType, CallType.METHOD)))
}.compilesWithoutError()
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt
index 5def604..737e1d8 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/FieldProcessorTest.kt
@@ -61,27 +61,29 @@
TypeName.FLOAT,
TypeName.DOUBLE
)
- val ARRAY_CONVERTER = JavaFileObjects.forSourceLines("foo.bar.MyConverter",
- """
+ val ARRAY_CONVERTER = JavaFileObjects.forSourceLines(
+ "foo.bar.MyConverter",
+ """
package foo.bar;
import androidx.room.*;
public class MyConverter {
${ALL_PRIMITIVES.joinToString("\n") {
- val arrayDef = "$it[]"
- "@TypeConverter public static String" +
- " arrayIntoString($arrayDef input) { return null;}" +
- "@TypeConverter public static $arrayDef" +
- " stringIntoArray$it(String input) { return null;}"
- }}
+ val arrayDef = "$it[]"
+ "@TypeConverter public static String" +
+ " arrayIntoString($arrayDef input) { return null;}" +
+ "@TypeConverter public static $arrayDef" +
+ " stringIntoArray$it(String input) { return null;}"
+ }}
${ALL_PRIMITIVES.joinToString("\n") {
- val arrayDef = "${it.box()}[]"
- "@TypeConverter public static String" +
- " arrayIntoString($arrayDef input) { return null;}" +
- "@TypeConverter public static $arrayDef" +
- " stringIntoArray${it}Boxed(String input) { return null;}"
- }}
+ val arrayDef = "${it.box()}[]"
+ "@TypeConverter public static String" +
+ " arrayIntoString($arrayDef input) { return null;}" +
+ "@TypeConverter public static $arrayDef" +
+ " stringIntoArray${it}Boxed(String input) { return null;}"
+ }}
}
- """)
+ """
+ )
private fun TypeName.affinity(): SQLTypeAffinity {
return when (this) {
@@ -101,12 +103,17 @@
fun primitives() {
ALL_PRIMITIVES.forEach { primitive ->
singleEntity("$primitive x;") { field, invocation ->
- assertThat(field, `is`(
- Field(name = "x",
- type = primitive.typeMirror(invocation),
- element = field.element,
- affinity = primitive.affinity()
- )))
+ assertThat(
+ field,
+ `is`(
+ Field(
+ name = "x",
+ type = primitive.typeMirror(invocation),
+ element = field.element,
+ affinity = primitive.affinity()
+ )
+ )
+ )
}.compilesWithoutError()
}
}
@@ -115,83 +122,126 @@
fun boxed() {
ALL_PRIMITIVES.forEach { primitive ->
singleEntity("${primitive.box()} y;") { field, invocation ->
- assertThat(field, `is`(
- Field(name = "y",
- type = primitive.box(invocation),
- element = field.element,
- affinity = primitive.affinity())))
+ assertThat(
+ field,
+ `is`(
+ Field(
+ name = "y",
+ type = primitive.box(invocation),
+ element = field.element,
+ affinity = primitive.affinity()
+ )
+ )
+ )
}.compilesWithoutError()
}
}
@Test
fun columnName() {
- singleEntity("""
+ singleEntity(
+ """
@ColumnInfo(name = "foo")
@PrimaryKey
int x;
- """) { field, invocation ->
- assertThat(field, `is`(
- Field(name = "x",
- type = TypeName.INT.typeMirror(invocation),
- element = field.element,
- columnName = "foo",
- affinity = SQLTypeAffinity.INTEGER)))
+ """
+ ) { field, invocation ->
+ assertThat(
+ field,
+ `is`(
+ Field(
+ name = "x",
+ type = TypeName.INT.typeMirror(invocation),
+ element = field.element,
+ columnName = "foo",
+ affinity = SQLTypeAffinity.INTEGER
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun indexed() {
- singleEntity("""
+ singleEntity(
+ """
@ColumnInfo(name = "foo", index = true)
int x;
- """) { field, invocation ->
- assertThat(field, `is`(
- Field(name = "x",
- type = TypeName.INT.typeMirror(invocation),
- element = field.element,
- columnName = "foo",
- affinity = SQLTypeAffinity.INTEGER,
- indexed = true)))
+ """
+ ) { field, invocation ->
+ assertThat(
+ field,
+ `is`(
+ Field(
+ name = "x",
+ type = TypeName.INT.typeMirror(invocation),
+ element = field.element,
+ columnName = "foo",
+ affinity = SQLTypeAffinity.INTEGER,
+ indexed = true
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun emptyColumnName() {
- singleEntity("""
+ singleEntity(
+ """
@ColumnInfo(name = "")
int x;
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.COLUMN_NAME_CANNOT_BE_EMPTY)
}
@Test
fun byteArrayWithEnforcedType() {
- singleEntity("@TypeConverters(foo.bar.MyConverter.class)" +
- "@ColumnInfo(typeAffinity = ColumnInfo.TEXT) byte[] arr;") { field, invocation ->
- assertThat(field, `is`(Field(name = "arr",
- type = invocation.processingEnv.getArrayType(TypeName.BYTE),
- element = field.element,
- affinity = SQLTypeAffinity.TEXT)))
- assertThat((field.cursorValueReader as? ColumnTypeAdapter)?.typeAffinity,
- `is`(SQLTypeAffinity.TEXT))
+ singleEntity(
+ "@TypeConverters(foo.bar.MyConverter.class)" +
+ "@ColumnInfo(typeAffinity = ColumnInfo.TEXT) byte[] arr;"
+ ) { field, invocation ->
+ assertThat(
+ field,
+ `is`(
+ Field(
+ name = "arr",
+ type = invocation.processingEnv.getArrayType(TypeName.BYTE),
+ element = field.element,
+ affinity = SQLTypeAffinity.TEXT
+ )
+ )
+ )
+ assertThat(
+ (field.cursorValueReader as? ColumnTypeAdapter)?.typeAffinity,
+ `is`(SQLTypeAffinity.TEXT)
+ )
}.compilesWithoutError()
}
@Test
fun primitiveArray() {
ALL_PRIMITIVES.forEach { primitive ->
- singleEntity("@TypeConverters(foo.bar.MyConverter.class) " +
- "${primitive.toString().toLowerCase(Locale.US)}[] arr;") { field, invocation ->
- assertThat(field, `is`(
- Field(name = "arr",
- type = invocation.processingEnv.getArrayType(primitive),
- element = field.element,
- affinity = if (primitive == TypeName.BYTE) {
- SQLTypeAffinity.BLOB
- } else {
- SQLTypeAffinity.TEXT
- })))
+ singleEntity(
+ "@TypeConverters(foo.bar.MyConverter.class) " +
+ "${primitive.toString().toLowerCase(Locale.US)}[] arr;"
+ ) { field, invocation ->
+ assertThat(
+ field,
+ `is`(
+ Field(
+ name = "arr",
+ type = invocation.processingEnv.getArrayType(primitive),
+ element = field.element,
+ affinity = if (primitive == TypeName.BYTE) {
+ SQLTypeAffinity.BLOB
+ } else {
+ SQLTypeAffinity.TEXT
+ }
+ )
+ )
+ )
}.compilesWithoutError()
}
}
@@ -199,57 +249,92 @@
@Test
fun boxedArray() {
ALL_PRIMITIVES.forEach { primitive ->
- singleEntity("@TypeConverters(foo.bar.MyConverter.class) " +
- "${primitive.box()}[] arr;") { field, invocation ->
- assertThat(field, `is`(
- Field(name = "arr",
- type = invocation.processingEnv.getArrayType(
- primitive.box()),
- element = field.element,
- affinity = SQLTypeAffinity.TEXT)))
+ singleEntity(
+ "@TypeConverters(foo.bar.MyConverter.class) " +
+ "${primitive.box()}[] arr;"
+ ) { field, invocation ->
+ assertThat(
+ field,
+ `is`(
+ Field(
+ name = "arr",
+ type = invocation.processingEnv.getArrayType(
+ primitive.box()
+ ),
+ element = field.element,
+ affinity = SQLTypeAffinity.TEXT
+ )
+ )
+ )
}.compilesWithoutError()
}
}
@Test
fun generic() {
- singleEntity("""
+ singleEntity(
+ """
static class BaseClass<T> {
T item;
}
@Entity
static class Extending extends BaseClass<java.lang.Integer> {
}
- """) { field, invocation ->
- assertThat(field, `is`(Field(name = "item",
- type = TypeName.INT.box(invocation),
- element = field.element,
- affinity = SQLTypeAffinity.INTEGER)))
+ """
+ ) { field, invocation ->
+ assertThat(
+ field,
+ `is`(
+ Field(
+ name = "item",
+ type = TypeName.INT.box(invocation),
+ element = field.element,
+ affinity = SQLTypeAffinity.INTEGER
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun unboundGeneric() {
- singleEntity("""
+ singleEntity(
+ """
@Entity
static class BaseClass<T> {
T item;
}
- """) { _, _ -> }.failsToCompile()
- .withErrorContaining(ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_ENTITY_FIELDS)
+ """
+ ) { _, _ -> }.failsToCompile()
+ .withErrorContaining(ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_ENTITY_FIELDS)
}
@Test
fun nameVariations() {
simpleRun {
val fieldElement = mock(XFieldElement::class.java)
- assertThat(Field(fieldElement, "x", TypeName.INT.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("x")))
- assertThat(Field(fieldElement, "x", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("x")))
- assertThat(Field(fieldElement, "xAll",
- TypeName.BOOLEAN.typeMirror(it), SQLTypeAffinity.INTEGER)
- .nameWithVariations, `is`(arrayListOf("xAll")))
+ assertThat(
+ Field(
+ fieldElement, "x", TypeName.INT.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("x"))
+ )
+ assertThat(
+ Field(
+ fieldElement, "x", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("x"))
+ )
+ assertThat(
+ Field(
+ fieldElement, "xAll",
+ TypeName.BOOLEAN.typeMirror(it), SQLTypeAffinity.INTEGER
+ )
+ .nameWithVariations,
+ `is`(arrayListOf("xAll"))
+ )
}
}
@@ -257,15 +342,34 @@
fun nameVariations_is() {
val elm = mock(XFieldElement::class.java)
simpleRun {
- assertThat(Field(elm, "isX", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("isX", "x")))
- assertThat(Field(elm, "isX", TypeName.INT.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("isX")))
- assertThat(Field(elm, "is", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("is")))
- assertThat(Field(elm, "isAllItems", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations,
- `is`(arrayListOf("isAllItems", "allItems")))
+ assertThat(
+ Field(
+ elm, "isX", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("isX", "x"))
+ )
+ assertThat(
+ Field(
+ elm, "isX", TypeName.INT.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("isX"))
+ )
+ assertThat(
+ Field(
+ elm, "is", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("is"))
+ )
+ assertThat(
+ Field(
+ elm, "isAllItems", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("isAllItems", "allItems"))
+ )
}
}
@@ -273,15 +377,34 @@
fun nameVariations_has() {
val elm = mock(XFieldElement::class.java)
simpleRun {
- assertThat(Field(elm, "hasX", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("hasX", "x")))
- assertThat(Field(elm, "hasX", TypeName.INT.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("hasX")))
- assertThat(Field(elm, "has", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("has")))
- assertThat(Field(elm, "hasAllItems", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations,
- `is`(arrayListOf("hasAllItems", "allItems")))
+ assertThat(
+ Field(
+ elm, "hasX", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("hasX", "x"))
+ )
+ assertThat(
+ Field(
+ elm, "hasX", TypeName.INT.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("hasX"))
+ )
+ assertThat(
+ Field(
+ elm, "has", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("has"))
+ )
+ assertThat(
+ Field(
+ elm, "hasAllItems", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("hasAllItems", "allItems"))
+ )
}
}
@@ -289,20 +412,48 @@
fun nameVariations_m() {
val elm = mock(XFieldElement::class.java)
simpleRun {
- assertThat(Field(elm, "mall", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("mall")))
- assertThat(Field(elm, "mallVars", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("mallVars")))
- assertThat(Field(elm, "mAll", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("mAll", "all")))
- assertThat(Field(elm, "m", TypeName.INT.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("m")))
- assertThat(Field(elm, "mallItems", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations,
- `is`(arrayListOf("mallItems")))
- assertThat(Field(elm, "mAllItems", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations,
- `is`(arrayListOf("mAllItems", "allItems")))
+ assertThat(
+ Field(
+ elm, "mall", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("mall"))
+ )
+ assertThat(
+ Field(
+ elm, "mallVars", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("mallVars"))
+ )
+ assertThat(
+ Field(
+ elm, "mAll", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("mAll", "all"))
+ )
+ assertThat(
+ Field(
+ elm, "m", TypeName.INT.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("m"))
+ )
+ assertThat(
+ Field(
+ elm, "mallItems", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("mallItems"))
+ )
+ assertThat(
+ Field(
+ elm, "mAllItems", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("mAllItems", "allItems"))
+ )
}
}
@@ -310,31 +461,53 @@
fun nameVariations_underscore() {
val elm = mock(XFieldElement::class.java)
simpleRun {
- assertThat(Field(elm, "_all", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("_all", "all")))
- assertThat(Field(elm, "_", TypeName.INT.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations, `is`(arrayListOf("_")))
- assertThat(Field(elm, "_allItems", TypeName.BOOLEAN.typeMirror(it),
- SQLTypeAffinity.INTEGER).nameWithVariations,
- `is`(arrayListOf("_allItems", "allItems")))
+ assertThat(
+ Field(
+ elm, "_all", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("_all", "all"))
+ )
+ assertThat(
+ Field(
+ elm, "_", TypeName.INT.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("_"))
+ )
+ assertThat(
+ Field(
+ elm, "_allItems", TypeName.BOOLEAN.typeMirror(it),
+ SQLTypeAffinity.INTEGER
+ ).nameWithVariations,
+ `is`(arrayListOf("_allItems", "allItems"))
+ )
}
}
@Test
fun collate() {
Collate.values().forEach { collate ->
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(collate = ColumnInfo.${collate.name})
String code;
- """) { field, invocation ->
- assertThat(field, `is`(
- Field(name = "code",
- type = invocation.context.COMMON_TYPES.STRING,
- element = field.element,
- columnName = "code",
- collate = collate,
- affinity = SQLTypeAffinity.TEXT)))
+ """
+ ) { field, invocation ->
+ assertThat(
+ field,
+ `is`(
+ Field(
+ name = "code",
+ type = invocation.context.COMMON_TYPES.STRING,
+ element = field.element,
+ columnName = "code",
+ collate = collate,
+ affinity = SQLTypeAffinity.TEXT
+ )
+ )
+ )
}.compilesWithoutError()
}
}
@@ -413,38 +586,50 @@
}
fun singleEntity(vararg input: String, handler: (Field, invocation: TestInvocation) -> Unit):
- CompileTester {
- return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(listOf(JavaFileObjects.forSourceString("foo.bar.MyEntity",
- ENTITY_PREFIX + input.joinToString("\n") + ENTITY_SUFFIX
- ), ARRAY_CONVERTER))
- .processedWith(TestProcessor.builder()
+ CompileTester {
+ return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
+ .that(
+ listOf(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyEntity",
+ ENTITY_PREFIX + input.joinToString("\n") + ENTITY_SUFFIX
+ ),
+ ARRAY_CONVERTER
+ )
+ )
+ .processedWith(
+ TestProcessor.builder()
.forAnnotations(androidx.room.Entity::class)
.nextRunHandler { invocation ->
val (owner, fieldElement) = invocation.roundEnv
- .getElementsAnnotatedWith(Entity::class.java)
- .map {
- Pair(it, it.asTypeElement()
- .getAllFieldsIncludingPrivateSupers().firstOrNull())
- }
- .first { it.second != null }
- val entityContext =
- TableEntityProcessor(
- baseContext = invocation.context,
- element = owner.asTypeElement()
- ).context
- val parser = FieldProcessor(
- baseContext = entityContext,
- containing = owner.asDeclaredType(),
- element = fieldElement!!,
- bindingScope = FieldProcessor.BindingScope.TWO_WAY,
- fieldParent = null,
- onBindingError = { field, errorMsg ->
- invocation.context.logger.e(field.element, errorMsg) }
+ .getElementsAnnotatedWith(Entity::class.java)
+ .map {
+ Pair(
+ it,
+ it.asTypeElement()
+ .getAllFieldsIncludingPrivateSupers().firstOrNull()
)
+ }
+ .first { it.second != null }
+ val entityContext =
+ TableEntityProcessor(
+ baseContext = invocation.context,
+ element = owner.asTypeElement()
+ ).context
+ val parser = FieldProcessor(
+ baseContext = entityContext,
+ containing = owner.asDeclaredType(),
+ element = fieldElement!!,
+ bindingScope = FieldProcessor.BindingScope.TWO_WAY,
+ fieldParent = null,
+ onBindingError = { field, errorMsg ->
+ invocation.context.logger.e(field.element, errorMsg)
+ }
+ )
handler(parser.process(), invocation)
true
}
- .build())
- }
+ .build()
+ )
+ }
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/Fts3TableEntityProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/Fts3TableEntityProcessorTest.kt
index 144e045..75e3206 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/Fts3TableEntityProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/Fts3TableEntityProcessorTest.kt
@@ -54,7 +54,8 @@
@Test
fun simple() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
private int rowId;
@@ -66,12 +67,17 @@
assertThat(entity.fields.size, `is`(1))
val field = entity.fields.first()
val intType = invocation.processingEnv.requireType(TypeName.INT)
- assertThat(field, `is`(Field(
- element = field.element,
- name = "rowId",
- type = intType,
- columnName = "rowid",
- affinity = SQLTypeAffinity.INTEGER))
+ assertThat(
+ field,
+ `is`(
+ Field(
+ element = field.element,
+ name = "rowId",
+ type = intType,
+ columnName = "rowid",
+ affinity = SQLTypeAffinity.INTEGER
+ )
+ )
)
assertThat(field.setter, `is`(FieldSetter("setRowId", intType, CallType.METHOD)))
assertThat(field.getter, `is`(FieldGetter("getRowId", intType, CallType.METHOD)))
@@ -83,7 +89,8 @@
@Test
fun omittedRowId() {
- singleEntity("""
+ singleEntity(
+ """
private String content;
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
@@ -93,63 +100,72 @@
@Test
fun missingPrimaryKeyAnnotation() {
- singleEntity("""
+ singleEntity(
+ """
@ColumnInfo(name = "rowid")
private int rowId;
public int getRowId(){ return rowId; }
public void setRowId(int rowId) { this.rowId = rowId; }
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.MISSING_PRIMARY_KEYS_ANNOTATION_IN_ROW_ID)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.MISSING_PRIMARY_KEYS_ANNOTATION_IN_ROW_ID)
}
@Test
fun badPrimaryKeyName() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public int getId(){ return id; }
public void setId(int id) { this.id = id; }
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_NAME)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_NAME)
}
@Test
fun badPrimaryKeyAffinity() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
private String rowId;
public String getRowId(){ return rowId; }
public void setRowId(String rowId) { this.rowId = rowId; }
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_AFFINITY)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_AFFINITY)
}
@Test
fun multiplePrimaryKeys() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
public int oneId;
@PrimaryKey
public int twoId;
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.TOO_MANY_PRIMARY_KEYS_IN_FTS_ENTITY)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.TOO_MANY_PRIMARY_KEYS_IN_FTS_ENTITY)
}
@Test
fun nonDefaultTokenizer() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
private int rowId;
public int getRowId() { return rowId; }
public void setRowId(int id) { this.rowId = rowId; }
""",
- ftsAttributes = hashMapOf("tokenizer" to "FtsOptions.TOKENIZER_PORTER")
+ ftsAttributes = hashMapOf("tokenizer" to "FtsOptions.TOKENIZER_PORTER")
) { entity, _ ->
assertThat(entity.ftsOptions.tokenizer, `is`(FtsOptions.TOKENIZER_PORTER))
}.compilesWithoutError()
@@ -157,7 +173,8 @@
@Test
fun customTokenizer() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
private int rowId;
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/Fts4TableEntityProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/Fts4TableEntityProcessorTest.kt
index 7686775..6818d25 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/Fts4TableEntityProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/Fts4TableEntityProcessorTest.kt
@@ -41,7 +41,8 @@
@Test
fun simple() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
private int rowId;
@@ -53,12 +54,17 @@
assertThat(entity.fields.size, `is`(1))
val field = entity.fields.first()
val intType = invocation.processingEnv.requireType(TypeName.INT)
- assertThat(field, `is`(Field(
- element = field.element,
- name = "rowId",
- type = intType,
- columnName = "rowid",
- affinity = SQLTypeAffinity.INTEGER))
+ assertThat(
+ field,
+ `is`(
+ Field(
+ element = field.element,
+ name = "rowId",
+ type = intType,
+ columnName = "rowid",
+ affinity = SQLTypeAffinity.INTEGER
+ )
+ )
)
assertThat(field.setter, `is`(FieldSetter("setRowId", intType, CallType.METHOD)))
assertThat(field.getter, `is`(FieldGetter("getRowId", intType, CallType.METHOD)))
@@ -70,7 +76,9 @@
@Test
fun missingEntityAnnotation() {
- simpleRun(JavaFileObjects.forSourceString("foo.bar.MyEntity",
+ simpleRun(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyEntity",
"""
package foo.bar;
import androidx.room.*;
@@ -78,32 +86,36 @@
public class MyEntity {
public String content;
}
- """)) { invocation ->
- val entity = invocation.roundEnv.getElementsAnnotatedWith(Fts4::class.java)
- .first { it.toString() == "foo.bar.MyEntity" }
- FtsTableEntityProcessor(invocation.context, entity.asTypeElement())
- .process()
- }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY)
+ """
+ )
+ ) { invocation ->
+ val entity = invocation.roundEnv.getElementsAnnotatedWith(Fts4::class.java)
+ .first { it.toString() == "foo.bar.MyEntity" }
+ FtsTableEntityProcessor(invocation.context, entity.asTypeElement())
+ .process()
+ }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY)
}
@Test
fun notAllowedIndex() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
public int rowId;
public String content;
""",
- entityAttributes = mapOf("indices" to "{@Index(\"content\")}")
+ entityAttributes = mapOf("indices" to "{@Index(\"content\")}")
) { _, _ -> }.failsToCompile().withErrorContaining(ProcessorErrors.INDICES_IN_FTS_ENTITY)
}
@Test
fun notAllowedForeignKeys() {
- val foreignEntity = JavaFileObjects.forSourceString("foo.bar.FKEntity",
- """
+ val foreignEntity = JavaFileObjects.forSourceString(
+ "foo.bar.FKEntity",
+ """
package foo.bar;
import androidx.room.*;
@Entity
@@ -111,23 +123,28 @@
@PrimaryKey
public long id;
}
- """)
- singleEntity("""
+ """
+ )
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
public int rowId;
public String content;
""",
- entityAttributes = mapOf("foreignKeys" to "{@ForeignKey(entity=FKEntity.class, " +
- "parentColumns=\"id\", childColumns=\"rowid\")}"),
- jfos = listOf(foreignEntity)
+ entityAttributes = mapOf(
+ "foreignKeys" to "{@ForeignKey(entity=FKEntity.class, " +
+ "parentColumns=\"id\", childColumns=\"rowid\")}"
+ ),
+ jfos = listOf(foreignEntity)
) { _, _ -> }.failsToCompile()
- .withErrorContaining(ProcessorErrors.FOREIGN_KEYS_IN_FTS_ENTITY)
+ .withErrorContaining(ProcessorErrors.FOREIGN_KEYS_IN_FTS_ENTITY)
}
@Test
fun omittedRowId() {
- singleEntity("""
+ singleEntity(
+ """
private String content;
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
@@ -137,86 +154,97 @@
@Test
fun primaryKeyInEntityAnnotation() {
- singleEntity("""
+ singleEntity(
+ """
@ColumnInfo(name = "rowid")
public int rowId;
public String content;
""",
- entityAttributes = mapOf("primaryKeys" to "\"rowid\"")
+ entityAttributes = mapOf("primaryKeys" to "\"rowid\"")
) { _, _ -> }.compilesWithoutError()
}
@Test
fun missingPrimaryKeyAnnotation() {
- singleEntity("""
+ singleEntity(
+ """
@ColumnInfo(name = "rowid")
private int rowId;
public int getRowId(){ return rowId; }
public void setRowId(int rowId) { this.rowId = rowId; }
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.MISSING_PRIMARY_KEYS_ANNOTATION_IN_ROW_ID)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.MISSING_PRIMARY_KEYS_ANNOTATION_IN_ROW_ID)
}
@Test
fun badPrimaryKeyName() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public int getId(){ return id; }
public void setId(int id) { this.id = id; }
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_NAME)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_NAME)
}
@Test
fun badPrimaryKeyAffinity() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
private String rowId;
public String getRowId(){ return rowId; }
public void setRowId(String rowId) { this.rowId = rowId; }
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_AFFINITY)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PRIMARY_KEY_AFFINITY)
}
@Test
fun multiplePrimaryKeyAnnotations() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
public int oneId;
@PrimaryKey
public int twoId;
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.TOO_MANY_PRIMARY_KEYS_IN_FTS_ENTITY)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.TOO_MANY_PRIMARY_KEYS_IN_FTS_ENTITY)
}
@Test
fun multiplePrimaryKeysInEntityAnnotation() {
- singleEntity("""
+ singleEntity(
+ """
public int oneId;
public int twoId;
""",
- entityAttributes = mapOf("primaryKeys" to "{\"oneId\",\"twoId\"}")
+ entityAttributes = mapOf("primaryKeys" to "{\"oneId\",\"twoId\"}")
) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.TOO_MANY_PRIMARY_KEYS_IN_FTS_ENTITY)
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.TOO_MANY_PRIMARY_KEYS_IN_FTS_ENTITY)
}
@Test
fun nonDefaultTokenizer() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
private int rowId;
public int getRowId() { return rowId; }
public void setRowId(int id) { this.rowId = rowId; }
""",
- ftsAttributes = hashMapOf("tokenizer" to "FtsOptions.TOKENIZER_PORTER")
+ ftsAttributes = hashMapOf("tokenizer" to "FtsOptions.TOKENIZER_PORTER")
) { entity, _ ->
assertThat(entity.ftsOptions.tokenizer, `is`(FtsOptions.TOKENIZER_PORTER))
}.compilesWithoutError()
@@ -224,7 +252,8 @@
@Test
fun customTokenizer() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
private int rowId;
@@ -239,32 +268,36 @@
@Test
fun badExternalContentEntity_notAnEntity() {
- val contentSrc = JavaFileObjects.forSourceString("foo.bar.Content",
- """
+ val contentSrc = JavaFileObjects.forSourceString(
+ "foo.bar.Content",
+ """
package foo.bar;
import androidx.room.*;
public class Content {
String text;
}
- """)
- singleEntity("""
+ """
+ )
+ singleEntity(
+ """
@PrimaryKey
public int rowid;
public String text;
public String extraData;
""",
- ftsAttributes = hashMapOf("contentEntity" to "Content.class"),
- jfos = listOf(contentSrc)
+ ftsAttributes = hashMapOf("contentEntity" to "Content.class"),
+ jfos = listOf(contentSrc)
) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.externalContentNotAnEntity("foo.bar.Content"))
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.externalContentNotAnEntity("foo.bar.Content"))
}
@Test
fun badExternalContentEntity_missingFields() {
- val contentSrc = JavaFileObjects.forSourceString("foo.bar.Content",
- """
+ val contentSrc = JavaFileObjects.forSourceString(
+ "foo.bar.Content",
+ """
package foo.bar;
import androidx.room.*;
@@ -274,88 +307,99 @@
int id;
String text;
}
- """)
- singleEntity("""
+ """
+ )
+ singleEntity(
+ """
@PrimaryKey
public int rowid;
public String text;
public String extraData;
""",
- ftsAttributes = hashMapOf("contentEntity" to "Content.class"),
- jfos = listOf(contentSrc)
+ ftsAttributes = hashMapOf("contentEntity" to "Content.class"),
+ jfos = listOf(contentSrc)
) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.missingFtsContentField("foo.bar.MyEntity",
- "extraData", "foo.bar.Content"))
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors.missingFtsContentField(
+ "foo.bar.MyEntity",
+ "extraData", "foo.bar.Content"
+ )
+ )
}
@Test
fun missingLanguageIdField() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
public int rowId;
public String body;
""",
- ftsAttributes = hashMapOf("languageId" to "\"lid\"")
+ ftsAttributes = hashMapOf("languageId" to "\"lid\"")
) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.missingLanguageIdField("lid"))
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.missingLanguageIdField("lid"))
}
@Test
fun badLanguageIdAffinity() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
public int rowId;
public String body;
public String lid;
""",
- ftsAttributes = hashMapOf("languageId" to "\"lid\"")
+ ftsAttributes = hashMapOf("languageId" to "\"lid\"")
) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_LANGUAGE_ID_AFFINITY)
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_LANGUAGE_ID_AFFINITY)
}
@Test
fun missingNotIndexedField() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
public int rowId;
""",
- ftsAttributes = hashMapOf("notIndexed" to "{\"body\"}")
+ ftsAttributes = hashMapOf("notIndexed" to "{\"body\"}")
) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.missingNotIndexedField(listOf("body")))
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.missingNotIndexedField(listOf("body")))
}
@Test
fun badPrefixValue_zero() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
public int rowId;
public String body;
""",
- ftsAttributes = hashMapOf("prefix" to "{0,2}")
+ ftsAttributes = hashMapOf("prefix" to "{0,2}")
) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PREFIX_SIZES)
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PREFIX_SIZES)
}
@Test
fun badPrefixValue_negative() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
@ColumnInfo(name = "rowid")
public int rowId;
public String body;
""",
- ftsAttributes = hashMapOf("prefix" to "{-2,2}")
+ ftsAttributes = hashMapOf("prefix" to "{-2,2}")
) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PREFIX_SIZES)
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.INVALID_FTS_ENTITY_PREFIX_SIZES)
}
}
\ No newline at end of file
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt
index 011428c..14e28c6 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt
@@ -65,33 +65,38 @@
@Test
fun readNoParams() {
singleInsertMethod(
- """
+ """
@Insert
abstract public void foo();
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("foo"))
assertThat(insertion.parameters.size, `is`(0))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
assertThat(insertion.entities.size, `is`(0))
}.failsToCompile().withErrorContaining(
- ProcessorErrors.INSERTION_DOES_NOT_HAVE_ANY_PARAMETERS_TO_INSERT)
+ ProcessorErrors.INSERTION_DOES_NOT_HAVE_ANY_PARAMETERS_TO_INSERT
+ )
}
@Test
fun insertSingle() {
singleInsertMethod(
- """
+ """
@Insert
abstract public long foo(User user);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("foo"))
assertThat(insertion.parameters.size, `is`(1))
val param = insertion.parameters.first()
assertThat(param.type.typeName, `is`(USER_TYPE_NAME))
assertThat(param.pojoType?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.entities["user"]?.isPartialEntity, `is`(false))
- assertThat(insertion.entities["user"]?.pojo?.typeName,
- `is`(ClassName.get("foo.bar", "User") as TypeName))
+ assertThat(
+ insertion.entities["user"]?.pojo?.typeName,
+ `is`(ClassName.get("foo.bar", "User") as TypeName)
+ )
assertThat(insertion.returnType.typeName, `is`(TypeName.LONG))
}.compilesWithoutError()
}
@@ -99,25 +104,27 @@
@Test
fun insertNotAnEntity() {
singleInsertMethod(
- """
+ """
@Insert
abstract public void foo(NotAnEntity notValid);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("foo"))
assertThat(insertion.parameters.size, `is`(1))
assertThat(insertion.entities.size, `is`(0))
}.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER
+ ProcessorErrors.CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER
)
}
@Test
fun insertTwo() {
singleInsertMethod(
- """
+ """
@Insert
abstract public void foo(User u1, User u2);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("foo"))
assertThat(insertion.parameters.size, `is`(2))
@@ -136,40 +143,55 @@
@Test
fun insertList() {
singleInsertMethod(
- """
+ """
@Insert
abstract public List<Long> insertUsers(List<User> users);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("insertUsers"))
assertThat(insertion.parameters.size, `is`(1))
val param = insertion.parameters.first()
- assertThat(param.type.typeName, `is`(
+ assertThat(
+ param.type.typeName,
+ `is`(
ParameterizedTypeName.get(
- ClassName.get("java.util", "List"),
- USER_TYPE_NAME) as TypeName))
+ ClassName.get("java.util", "List"),
+ USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
assertThat(param.pojoType?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
- assertThat(insertion.returnType.typeName, `is`(
+ assertThat(
+ insertion.returnType.typeName,
+ `is`(
ParameterizedTypeName.get(
- ClassName.get("java.util", "List"),
- ClassName.get("java.lang", "Long")) as TypeName
- ))
+ ClassName.get("java.util", "List"),
+ ClassName.get("java.lang", "Long")
+ ) as TypeName
+ )
+ )
}.compilesWithoutError()
}
@Test
fun insertArray() {
singleInsertMethod(
- """
+ """
@Insert
abstract public void insertUsers(User[] users);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("insertUsers"))
assertThat(insertion.parameters.size, `is`(1))
val param = insertion.parameters.first()
- assertThat(param.type.typeName, `is`(
- ArrayTypeName.of(COMMON.USER_TYPE_NAME) as TypeName))
+ assertThat(
+ param.type.typeName,
+ `is`(
+ ArrayTypeName.of(COMMON.USER_TYPE_NAME) as TypeName
+ )
+ )
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
@@ -179,17 +201,23 @@
@Test
fun insertSet() {
singleInsertMethod(
- """
+ """
@Insert
abstract public void insertUsers(Set<User> users);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("insertUsers"))
assertThat(insertion.parameters.size, `is`(1))
val param = insertion.parameters.first()
- assertThat(param.type.typeName, `is`(
+ assertThat(
+ param.type.typeName,
+ `is`(
ParameterizedTypeName.get(
- ClassName.get("java.util", "Set"),
- COMMON.USER_TYPE_NAME) as TypeName))
+ ClassName.get("java.util", "Set"),
+ COMMON.USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
@@ -199,17 +227,23 @@
@Test
fun insertQueue() {
singleInsertMethod(
- """
+ """
@Insert
abstract public void insertUsers(Queue<User> users);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("insertUsers"))
assertThat(insertion.parameters.size, `is`(1))
val param = insertion.parameters.first()
- assertThat(param.type.typeName, `is`(
+ assertThat(
+ param.type.typeName,
+ `is`(
ParameterizedTypeName.get(
- ClassName.get("java.util", "Queue"),
- USER_TYPE_NAME) as TypeName))
+ ClassName.get("java.util", "Queue"),
+ USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
@@ -218,17 +252,24 @@
@Test
fun insertIterable() {
- singleInsertMethod("""
+ singleInsertMethod(
+ """
@Insert
abstract public void insert(Iterable<User> users);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("insert"))
assertThat(insertion.parameters.size, `is`(1))
val param = insertion.parameters.first()
- assertThat(param.type.typeName, `is`(
+ assertThat(
+ param.type.typeName,
+ `is`(
ParameterizedTypeName.get(
- ClassName.get("java.lang", "Iterable"),
- USER_TYPE_NAME) as TypeName))
+ ClassName.get("java.lang", "Iterable"),
+ USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
@@ -237,17 +278,25 @@
@Test
fun insertCustomCollection() {
- singleInsertMethod("""
+ singleInsertMethod(
+ """
static class MyList<Irrelevant, Item> extends ArrayList<Item> {}
@Insert
abstract public void insert(MyList<String, User> users);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("insert"))
assertThat(insertion.parameters.size, `is`(1))
val param = insertion.parameters.first()
- assertThat(param.type.typeName, `is`(ParameterizedTypeName.get(
- ClassName.get("foo.bar", "MyClass.MyList"),
- CommonTypeNames.STRING, USER_TYPE_NAME) as TypeName))
+ assertThat(
+ param.type.typeName,
+ `is`(
+ ParameterizedTypeName.get(
+ ClassName.get("foo.bar", "MyClass.MyList"),
+ CommonTypeNames.STRING, USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
@@ -257,15 +306,20 @@
@Test
fun insertDifferentTypes() {
singleInsertMethod(
- """
+ """
@Insert
abstract public void foo(User u1, Book b1);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.parameters.size, `is`(2))
- assertThat(insertion.parameters[0].type.typeName.toString(),
- `is`("foo.bar.User"))
- assertThat(insertion.parameters[1].type.typeName.toString(),
- `is`("foo.bar.Book"))
+ assertThat(
+ insertion.parameters[0].type.typeName.toString(),
+ `is`("foo.bar.User")
+ )
+ assertThat(
+ insertion.parameters[1].type.typeName.toString(),
+ `is`("foo.bar.Book")
+ )
assertThat(insertion.parameters.map { it.name }, `is`(listOf("u1", "b1")))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
assertThat(insertion.entities.size, `is`(2))
@@ -277,10 +331,11 @@
@Test
fun onConflict_Default() {
singleInsertMethod(
- """
+ """
@Insert
abstract public void foo(User user);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.onConflict, `is`(OnConflictStrategy.ABORT))
}.compilesWithoutError()
}
@@ -288,27 +343,29 @@
@Test
fun onConflict_Invalid() {
singleInsertMethod(
- """
+ """
@Insert(onConflict = -1)
abstract public void foo(User user);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_ON_CONFLICT_VALUE)
}
@Test
fun onConflict_EachValue() {
listOf(
- Pair("REPLACE", 1),
- Pair("ROLLBACK", 2),
- Pair("ABORT", 3),
- Pair("FAIL", 4),
- Pair("IGNORE", 5)
+ Pair("REPLACE", 1),
+ Pair("ROLLBACK", 2),
+ Pair("ABORT", 3),
+ Pair("FAIL", 4),
+ Pair("IGNORE", 5)
).forEach { pair ->
singleInsertMethod(
- """
+ """
@Insert(onConflict=OnConflictStrategy.${pair.first})
abstract public void foo(User user);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.onConflict, `is`(pair.second))
}.compilesWithoutError()
}
@@ -317,126 +374,156 @@
@Test
fun invalidReturnType() {
listOf(
- "int",
- "${RxJava2TypeNames.SINGLE}<Int>",
- "${RxJava2TypeNames.MAYBE}<Int>",
- "${RxJava2TypeNames.SINGLE}<String>",
- "${RxJava2TypeNames.MAYBE}<String>",
- "${RxJava2TypeNames.SINGLE}<User>",
- "${RxJava2TypeNames.MAYBE}<User>"
+ "int",
+ "${RxJava2TypeNames.SINGLE}<Int>",
+ "${RxJava2TypeNames.MAYBE}<Int>",
+ "${RxJava2TypeNames.SINGLE}<String>",
+ "${RxJava2TypeNames.MAYBE}<String>",
+ "${RxJava2TypeNames.SINGLE}<User>",
+ "${RxJava2TypeNames.MAYBE}<User>"
).forEach { type ->
singleInsertMethod(
- """
+ """
@Insert
abstract public $type foo(User user);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.methodBinder.adapter, `is`(nullValue()))
}.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER)
+ ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
+ )
}
}
@Test
fun mismatchedReturnType() {
listOf(
- "long[]",
- "Long[]",
- "List<Long>",
- "${RxJava2TypeNames.SINGLE}<List<Long>>",
- "${RxJava2TypeNames.MAYBE}<List<Long>>"
+ "long[]",
+ "Long[]",
+ "List<Long>",
+ "${RxJava2TypeNames.SINGLE}<List<Long>>",
+ "${RxJava2TypeNames.MAYBE}<List<Long>>"
).forEach { type ->
singleInsertMethod(
- """
+ """
@Insert
abstract public $type foo(User user);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.methodBinder.adapter, `is`(nullValue()))
}.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER)
+ ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
+ )
}
}
@Test
fun mismatchedReturnType2() {
listOf(
- "long",
- "Long",
- "${RxJava2TypeNames.SINGLE}<Long>",
- "${RxJava2TypeNames.MAYBE}<Long>"
+ "long",
+ "Long",
+ "${RxJava2TypeNames.SINGLE}<Long>",
+ "${RxJava2TypeNames.MAYBE}<Long>"
).forEach { type ->
singleInsertMethod(
- """
+ """
@Insert
abstract public $type foo(User... user);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.methodBinder.adapter, `is`(nullValue()))
}.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER)
+ ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
+ )
}
}
@Test
fun mismatchedReturnType3() {
listOf(
- "long",
- "Long",
- "${RxJava2TypeNames.SINGLE}<Long>",
- "${RxJava2TypeNames.MAYBE}<Long>"
+ "long",
+ "Long",
+ "${RxJava2TypeNames.SINGLE}<Long>",
+ "${RxJava2TypeNames.MAYBE}<Long>"
).forEach { type ->
singleInsertMethod(
- """
+ """
@Insert
abstract public $type foo(User user1, User user2);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.methodBinder.adapter, `is`(nullValue()))
}.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER)
+ ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
+ )
}
}
@Test
fun validReturnTypes() {
listOf(
- Pair("void", InsertMethodAdapter.InsertionType.INSERT_VOID),
- Pair("long", InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID),
- Pair("long[]", InsertMethodAdapter.InsertionType.INSERT_ID_ARRAY),
- Pair("Long[]", InsertMethodAdapter.InsertionType.INSERT_ID_ARRAY_BOX),
- Pair("List<Long>", InsertMethodAdapter.InsertionType.INSERT_ID_LIST),
- Pair(RxJava2TypeNames.COMPLETABLE,
- InsertMethodAdapter.InsertionType.INSERT_VOID_OBJECT),
- Pair("${RxJava2TypeNames.SINGLE}<Long>",
- InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID),
- Pair("${RxJava2TypeNames.SINGLE}<List<Long>>",
- InsertMethodAdapter.InsertionType.INSERT_ID_LIST),
- Pair("${RxJava2TypeNames.MAYBE}<Long>",
- InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID),
- Pair("${RxJava2TypeNames.MAYBE}<List<Long>>",
- InsertMethodAdapter.InsertionType.INSERT_ID_LIST),
- Pair(RxJava3TypeNames.COMPLETABLE,
- InsertMethodAdapter.InsertionType.INSERT_VOID_OBJECT),
- Pair("${RxJava3TypeNames.SINGLE}<Long>",
- InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID),
- Pair("${RxJava3TypeNames.SINGLE}<List<Long>>",
- InsertMethodAdapter.InsertionType.INSERT_ID_LIST),
- Pair("${RxJava3TypeNames.MAYBE}<Long>",
- InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID),
- Pair("${RxJava3TypeNames.MAYBE}<List<Long>>",
- InsertMethodAdapter.InsertionType.INSERT_ID_LIST)
+ Pair("void", InsertMethodAdapter.InsertionType.INSERT_VOID),
+ Pair("long", InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID),
+ Pair("long[]", InsertMethodAdapter.InsertionType.INSERT_ID_ARRAY),
+ Pair("Long[]", InsertMethodAdapter.InsertionType.INSERT_ID_ARRAY_BOX),
+ Pair("List<Long>", InsertMethodAdapter.InsertionType.INSERT_ID_LIST),
+ Pair(
+ RxJava2TypeNames.COMPLETABLE,
+ InsertMethodAdapter.InsertionType.INSERT_VOID_OBJECT
+ ),
+ Pair(
+ "${RxJava2TypeNames.SINGLE}<Long>",
+ InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID
+ ),
+ Pair(
+ "${RxJava2TypeNames.SINGLE}<List<Long>>",
+ InsertMethodAdapter.InsertionType.INSERT_ID_LIST
+ ),
+ Pair(
+ "${RxJava2TypeNames.MAYBE}<Long>",
+ InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID
+ ),
+ Pair(
+ "${RxJava2TypeNames.MAYBE}<List<Long>>",
+ InsertMethodAdapter.InsertionType.INSERT_ID_LIST
+ ),
+ Pair(
+ RxJava3TypeNames.COMPLETABLE,
+ InsertMethodAdapter.InsertionType.INSERT_VOID_OBJECT
+ ),
+ Pair(
+ "${RxJava3TypeNames.SINGLE}<Long>",
+ InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID
+ ),
+ Pair(
+ "${RxJava3TypeNames.SINGLE}<List<Long>>",
+ InsertMethodAdapter.InsertionType.INSERT_ID_LIST
+ ),
+ Pair(
+ "${RxJava3TypeNames.MAYBE}<Long>",
+ InsertMethodAdapter.InsertionType.INSERT_SINGLE_ID
+ ),
+ Pair(
+ "${RxJava3TypeNames.MAYBE}<List<Long>>",
+ InsertMethodAdapter.InsertionType.INSERT_ID_LIST
+ )
).forEach { pair ->
val dots = if (pair.second in setOf(
- InsertMethodAdapter.InsertionType.INSERT_ID_LIST,
- InsertMethodAdapter.InsertionType.INSERT_ID_ARRAY,
- InsertMethodAdapter.InsertionType.INSERT_ID_ARRAY_BOX
- )) {
+ InsertMethodAdapter.InsertionType.INSERT_ID_LIST,
+ InsertMethodAdapter.InsertionType.INSERT_ID_ARRAY,
+ InsertMethodAdapter.InsertionType.INSERT_ID_ARRAY_BOX
+ )
+ ) {
"..."
} else {
""
}
singleInsertMethod(
- """
+ """
@Insert
abstract public ${pair.first} foo(User$dots user);
- """) { insertion, _ ->
+ """
+ ) { insertion, _ ->
assertThat(insertion.methodBinder.adapter, `is`(notNullValue()))
}.compilesWithoutError()
}
@@ -460,7 +547,8 @@
@Insert(entity = User.class)
abstract public long foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo)) { insertion, _ ->
+ additionalJFOs = listOf(usernameJfo)
+ ) { insertion, _ ->
assertThat(insertion.name, `is`("foo"))
assertThat(insertion.parameters.size, `is`(1))
val param = insertion.parameters.first()
@@ -479,7 +567,8 @@
"""
@Insert(entity = User.class)
abstract public long foo(User user);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.compilesWithoutError()
}
@@ -501,7 +590,8 @@
@Insert(entity = User.class)
abstract public void foo(Username usernameA, Username usernameB);
""",
- additionalJFOs = listOf(usernameJfo)) { _, _ ->
+ additionalJFOs = listOf(usernameJfo)
+ ) { _, _ ->
}.compilesWithoutError()
}
@@ -521,11 +611,13 @@
@Insert(entity = User.class)
abstract public void foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo)) { _, _ ->
+ additionalJFOs = listOf(usernameJfo)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
ProcessorErrors.missingRequiredColumnsInPartialEntity(
partialEntityName = USERNAME_TYPE_NAME.toString(),
- missingColumnNames = listOf("ageColumn"))
+ missingColumnNames = listOf("ageColumn")
+ )
)
}
@@ -558,7 +650,8 @@
@Insert(entity = Pet.class)
abstract public long foo(PetName petName);
""",
- additionalJFOs = listOf(petNameJfo, petJfo)) { _, _ ->
+ additionalJFOs = listOf(petNameJfo, petJfo)
+ ) { _, _ ->
}.compilesWithoutError()
}
@@ -589,11 +682,13 @@
@Insert(entity = Pet.class)
abstract public long foo(PetName petName);
""",
- additionalJFOs = listOf(petNameJfo, petJfo)) { _, _ ->
+ additionalJFOs = listOf(petNameJfo, petJfo)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
ProcessorErrors.missingPrimaryKeysInPartialEntityForInsert(
partialEntityName = "foo.bar.PetName",
- primaryKeyNames = listOf("petId"))
+ primaryKeyNames = listOf("petId")
+ )
)
}
@@ -624,7 +719,8 @@
@Insert(entity = Pet.class)
abstract public long foo(PetName petName);
""",
- additionalJFOs = listOf(petNameJfo, petJfo)) { _, _ ->
+ additionalJFOs = listOf(petNameJfo, petJfo)
+ ) { _, _ ->
}.compilesWithoutError()
}
@@ -645,9 +741,11 @@
@Insert(entity = User.class)
abstract public long foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo)) { _, _ ->
+ additionalJFOs = listOf(usernameJfo)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.cannotFindAsEntityField("foo.bar.User"))
+ ProcessorErrors.cannotFindAsEntityField("foo.bar.User")
+ )
}
@Test
@@ -670,7 +768,8 @@
@Insert(entity = User.class)
abstract public long foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo)) { _, _ ->
+ additionalJFOs = listOf(usernameJfo)
+ ) { _, _ ->
}.compilesWithoutError()
}
@@ -703,7 +802,8 @@
@Insert(entity = User.class)
abstract public long foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo, fullnameJfo)) { _, _ ->
+ additionalJFOs = listOf(usernameJfo, fullnameJfo)
+ ) { _, _ ->
}.compilesWithoutError()
}
@@ -736,7 +836,8 @@
@Insert(entity = User.class)
abstract public long foo(UserPets userPets);
""",
- additionalJFOs = listOf(userPetsJfo, petJfo)) { _, _ ->
+ additionalJFOs = listOf(userPetsJfo, petJfo)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_RELATION_IN_PARTIAL_ENTITY)
}
@@ -746,32 +847,41 @@
handler: (InsertionMethod, TestInvocation) -> Unit
): CompileTester {
return assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(listOf(JavaFileObjects.forSourceString("foo.bar.MyClass",
- DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX),
- COMMON.USER, COMMON.BOOK, COMMON.NOT_AN_ENTITY, COMMON.RX2_COMPLETABLE,
- COMMON.RX2_MAYBE, COMMON.RX2_SINGLE, COMMON.RX3_COMPLETABLE,
- COMMON.RX3_MAYBE, COMMON.RX3_SINGLE) + additionalJFOs
- )
- .processedWith(TestProcessor.builder()
- .forAnnotations(Insert::class, Dao::class)
- .nextRunHandler { invocation ->
- val (owner, methods) = invocation.roundEnv
- .getElementsAnnotatedWith(Dao::class.java)
- .map {
- Pair(it,
- it.asTypeElement().getAllMethods().filter {
- it.hasAnnotation(Insert::class)
- }
- )
- }.first { it.second.isNotEmpty() }
- val processor = InsertionMethodProcessor(
- baseContext = invocation.context,
- containing = owner.asDeclaredType(),
- executableElement = methods.first())
- val processed = processor.process()
- handler(processed, invocation)
- true
- }
- .build())
+ .that(
+ listOf(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyClass",
+ DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
+ ),
+ COMMON.USER, COMMON.BOOK, COMMON.NOT_AN_ENTITY, COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_MAYBE, COMMON.RX2_SINGLE, COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_MAYBE, COMMON.RX3_SINGLE
+ ) + additionalJFOs
+ )
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(Insert::class, Dao::class)
+ .nextRunHandler { invocation ->
+ val (owner, methods) = invocation.roundEnv
+ .getElementsAnnotatedWith(Dao::class.java)
+ .map {
+ Pair(
+ it,
+ it.asTypeElement().getAllMethods().filter {
+ it.hasAnnotation(Insert::class)
+ }
+ )
+ }.first { it.second.isNotEmpty() }
+ val processor = InsertionMethodProcessor(
+ baseContext = invocation.context,
+ containing = owner.asDeclaredType(),
+ executableElement = methods.first()
+ )
+ val processed = processor.process()
+ handler(processed, invocation)
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTargetMethodTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTargetMethodTest.kt
index c24005c..2ac1802 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTargetMethodTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTargetMethodTest.kt
@@ -66,9 +66,10 @@
}
""".toJFO(MY_POJO.toString())
singleRun(source)
- .failsToCompile()
- .withErrorContaining(
- ProcessorErrors.invalidAnnotationTarget("PrimaryKey", "method"))
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors.invalidAnnotationTarget("PrimaryKey", "method")
+ )
}
@Test
@@ -84,9 +85,10 @@
}
""".toJFO(MY_POJO.toString())
singleRun(source)
- .failsToCompile()
- .withErrorContaining(
- ProcessorErrors.invalidAnnotationTarget("PrimaryKey", "method"))
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors.invalidAnnotationTarget("PrimaryKey", "method")
+ )
}
@Test
@@ -102,15 +104,16 @@
}
""".toJFO(MY_POJO.toString())
singleRun(source)
- .failsToCompile()
- .withErrorContaining(
- ProcessorErrors.invalidAnnotationTarget("PrimaryKey", "method"))
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors.invalidAnnotationTarget("PrimaryKey", "method")
+ )
}
@Test
fun invalidAnnotationInAutoValueMethod() {
singleRun(
- """
+ """
@AutoValue.CopyAnnotations
@PrimaryKey
abstract long getId();
@@ -118,7 +121,7 @@
void someRandomMethod() { }
static MyPojo create(long id) { return new AutoValue_MyPojo(id); }
""",
- """
+ """
@PrimaryKey
private final long id;
AutoValue_MyPojo(long id) { this.id = id; }
@@ -126,7 +129,8 @@
long getId() { return this.id; }
"""
).failsToCompile().withErrorContaining(
- ProcessorErrors.invalidAnnotationTarget("ColumnInfo", "method"))
+ ProcessorErrors.invalidAnnotationTarget("ColumnInfo", "method")
+ )
}
@Test
@@ -144,7 +148,7 @@
}
"""
singleRunFullClass(
- """
+ """
package foo.bar;
import androidx.room.*;
@@ -160,7 +164,7 @@
}
$FOOTER
""",
- """
+ """
$AUTO_VALUE_HEADER
private final long id;
private final String value;
@@ -171,9 +175,10 @@
String getValue() { return this.value; };
$FOOTER
""",
- parent.toJFO("foo.bar.ParentPojo")
+ parent.toJFO("foo.bar.ParentPojo")
).failsToCompile().withErrorContaining(
- ProcessorErrors.invalidAnnotationTarget("ColumnInfo", "method"))
+ ProcessorErrors.invalidAnnotationTarget("ColumnInfo", "method")
+ )
}
@Test
@@ -189,7 +194,7 @@
}
""".toJFO(MY_POJO.toString())
singleRun(source)
- .compilesWithoutError()
+ .compilesWithoutError()
}
@Test
@@ -205,19 +210,19 @@
}
""".toJFO(MY_POJO.toString())
singleRun(source)
- .compilesWithoutError()
+ .compilesWithoutError()
}
@Test
fun validAnnotationInAutoValueAbstractMethod() {
singleRun(
- """
+ """
@AutoValue.CopyAnnotations
@PrimaryKey
abstract long getId();
static MyPojo create(long id) { return new AutoValue_MyPojo(id); }
""",
- """
+ """
@PrimaryKey
private final long id;
AutoValue_MyPojo(long id) { this.id = id; }
@@ -240,7 +245,7 @@
}
"""
singleRunFullClass(
- """
+ """
package foo.bar;
import androidx.room.*;
@@ -256,7 +261,7 @@
}
$FOOTER
""",
- """
+ """
$AUTO_VALUE_HEADER
private final long id;
private final String value;
@@ -267,7 +272,7 @@
String getValue() { return this.value; };
$FOOTER
""",
- parent.toJFO("foo.bar.ParentPojo")
+ parent.toJFO("foo.bar.ParentPojo")
).compilesWithoutError()
}
@@ -284,7 +289,7 @@
}
"""
singleRunFullClass(
- """
+ """
package foo.bar;
import androidx.room.*;
@@ -300,7 +305,7 @@
}
$FOOTER
""",
- """
+ """
$AUTO_VALUE_HEADER
private final long id;
private final String value;
@@ -311,7 +316,7 @@
public String getValue() { return this.value; };
$FOOTER
""",
- parent.toJFO("foo.bar.InterfacePojo")
+ parent.toJFO("foo.bar.InterfacePojo")
).compilesWithoutError()
}
@@ -327,7 +332,7 @@
}
"""
singleRun(
- """
+ """
@AutoValue.CopyAnnotations
@PrimaryKey
abstract long getId();
@@ -338,7 +343,7 @@
return new AutoValue_MyPojo(id, embedded);
}
""",
- """
+ """
@PrimaryKey
private final long id;
@Embedded
@@ -352,7 +357,7 @@
@Embedded
EmbeddedPojo getEmbedded() { return this.embedded; }
""",
- embeddedPojo.toJFO("foo.bar.EmbeddedPojo")
+ embeddedPojo.toJFO("foo.bar.EmbeddedPojo")
).compilesWithoutError()
}
@@ -372,7 +377,7 @@
}
"""
singleRun(
- """
+ """
@AutoValue.CopyAnnotations
@PrimaryKey
abstract long getId();
@@ -383,7 +388,7 @@
return new AutoValue_MyPojo(id, relations);
}
""",
- """
+ """
@PrimaryKey
private final long id;
@Relation(parentColumn = "id", entityColumn = "parentId")
@@ -397,15 +402,17 @@
@Relation(parentColumn = "id", entityColumn = "parentId")
List<RelationPojo> getRelations() { return this.relations; }
""",
- embeddedPojo.toJFO("foo.bar.RelationPojo")
+ embeddedPojo.toJFO("foo.bar.RelationPojo")
).compilesWithoutError()
}
private fun singleRun(vararg jfos: JavaFileObject) = simpleRun(*jfos) { invocation ->
- PojoProcessor.createFor(context = invocation.context,
+ PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ parent = null
+ ).process()
}
private fun singleRun(
@@ -414,17 +421,17 @@
vararg jfos: JavaFileObject
): CompileTester {
return singleRunFullClass(
- pojoCode = """
+ pojoCode = """
$HEADER
$pojoCode
$FOOTER
""",
- autoValuePojoCode = """
+ autoValuePojoCode = """
$AUTO_VALUE_HEADER
$autoValuePojoCode
$FOOTER
""",
- jfos = jfos
+ jfos = jfos
)
}
@@ -437,10 +444,12 @@
val autoValuePojoJFO = autoValuePojoCode.toJFO(AUTOVALUE_MY_POJO.toString())
val all = (jfos.toList() + pojoJFO + autoValuePojoJFO).toTypedArray()
return simpleRun(*all) { invocation ->
- PojoProcessor.createFor(context = invocation.context,
+ PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ parent = null
+ ).process()
}
}
}
\ No newline at end of file
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt
index 245bdee..ce8e194 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/PojoProcessorTest.kt
@@ -84,18 +84,21 @@
}
"""
simpleRun(
- """
+ """
package foo.bar;
import androidx.room.*;
public class ${MY_POJO.simpleName()} extends foo.bar.x.BaseClass {
public String myField;
}
""".toJFO(MY_POJO.toString()),
- parent.toJFO("foo.bar.x.BaseClass")) { invocation ->
- val pojo = PojoProcessor.createFor(context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(MY_POJO),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ parent.toJFO("foo.bar.x.BaseClass")
+ ) { invocation ->
+ val pojo = PojoProcessor.createFor(
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(MY_POJO),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
+ ).process()
assertThat(pojo.fields.find { it.name == "myField" }, notNullValue())
assertThat(pojo.fields.find { it.name == "baseField" }, notNullValue())
}.compilesWithoutError()
@@ -103,10 +106,12 @@
@Test
fun transient_ignore() {
- singleRun("""
+ singleRun(
+ """
transient int foo;
int bar;
- """) { pojo ->
+ """
+ ) { pojo ->
assertThat(pojo.fields.size, `is`(1))
assertThat(pojo.fields[0].name, `is`("bar"))
}.compilesWithoutError()
@@ -114,32 +119,37 @@
@Test
fun transient_withColumnInfo() {
- singleRun("""
+ singleRun(
+ """
@ColumnInfo
transient int foo;
int bar;
- """) { pojo ->
+ """
+ ) { pojo ->
assertThat(pojo.fields.map { it.name }.toSet(), `is`(setOf("bar", "foo")))
}.compilesWithoutError()
}
@Test
fun transient_embedded() {
- singleRun("""
+ singleRun(
+ """
@Embedded
transient Foo foo;
int bar;
static class Foo {
int x;
}
- """) { pojo ->
+ """
+ ) { pojo ->
assertThat(pojo.fields.map { it.name }.toSet(), `is`(setOf("x", "bar")))
}.compilesWithoutError()
}
@Test
fun transient_insideEmbedded() {
- singleRun("""
+ singleRun(
+ """
@Embedded
Foo foo;
int bar;
@@ -147,7 +157,8 @@
transient int x;
int y;
}
- """) { pojo ->
+ """
+ ) { pojo ->
assertThat(pojo.fields.map { it.name }.toSet(), `is`(setOf("bar", "y")))
}.compilesWithoutError()
}
@@ -155,11 +166,12 @@
@Test
fun transient_relation() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid")
public transient List<User> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { pojo ->
assertThat(pojo.relations.size, `is`(1))
assertThat(pojo.relations.first().entityField.name, `is`("uid"))
@@ -170,7 +182,7 @@
@Test
fun embedded() {
singleRun(
- """
+ """
int id;
@Embedded
Point myPoint;
@@ -189,15 +201,17 @@
val parent = pojo.fields[2].parent!!
assertThat(parent.prefix, `is`(""))
assertThat(parent.field.name, `is`("myPoint"))
- assertThat(parent.pojo.typeName,
- `is`(ClassName.get("foo.bar.MyPojo", "Point") as TypeName))
+ assertThat(
+ parent.pojo.typeName,
+ `is`(ClassName.get("foo.bar.MyPojo", "Point") as TypeName)
+ )
}.compilesWithoutError()
}
@Test
fun embeddedWithPrefix() {
singleRun(
- """
+ """
int id;
@Embedded(prefix = "foo")
Point myPoint;
@@ -221,7 +235,7 @@
@Test
fun nestedEmbedded() {
singleRun(
- """
+ """
int id;
@Embedded(prefix = "foo")
Point myPoint;
@@ -241,8 +255,12 @@
"""
) { pojo ->
assertThat(pojo.fields.size, `is`(5))
- assertThat(pojo.fields.map { it.columnName }, `is`(
- listOf("id", "foox", "fooy2", "foobarlat", "foobarlng")))
+ assertThat(
+ pojo.fields.map { it.columnName },
+ `is`(
+ listOf("id", "foox", "fooy2", "foobarlat", "foobarlng")
+ )
+ )
}.compilesWithoutError()
}
@@ -273,34 +291,40 @@
point, base
) { pojo, _ ->
assertThat(pojo.fields.size, `is`(3))
- assertThat(pojo.fields.map { it.columnName }.toSet(), `is`(
- setOf("x", "y", "normalField")))
+ assertThat(
+ pojo.fields.map { it.columnName }.toSet(),
+ `is`(
+ setOf("x", "y", "normalField")
+ )
+ )
val pointField = pojo.embeddedFields.first { it.field.name == "genericField" }
- assertThat(pointField.pojo.typeName,
- `is`(ClassName.get("foo.bar", "Point") as TypeName))
+ assertThat(
+ pointField.pojo.typeName,
+ `is`(ClassName.get("foo.bar", "Point") as TypeName)
+ )
}.compilesWithoutError()
}
@Test
fun duplicateColumnNames() {
singleRun(
- """
+ """
int id;
@ColumnInfo(name = "id")
int another;
"""
) { _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.pojoDuplicateFieldNames("id", listOf("id", "another"))
+ ProcessorErrors.pojoDuplicateFieldNames("id", listOf("id", "another"))
).and().withErrorContaining(
- POJO_FIELD_HAS_DUPLICATE_COLUMN_NAME
+ POJO_FIELD_HAS_DUPLICATE_COLUMN_NAME
).and().withErrorCount(3)
}
@Test
fun duplicateColumnNamesFromEmbedded() {
singleRun(
- """
+ """
int id;
@Embedded
Foo foo;
@@ -311,16 +335,16 @@
"""
) { _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.pojoDuplicateFieldNames("id", listOf("id", "foo > x"))
+ ProcessorErrors.pojoDuplicateFieldNames("id", listOf("id", "foo > x"))
).and().withErrorContaining(
- POJO_FIELD_HAS_DUPLICATE_COLUMN_NAME
+ POJO_FIELD_HAS_DUPLICATE_COLUMN_NAME
).and().withErrorCount(3)
}
@Test
fun dropSubPrimaryKeyNoWarningForPojo() {
singleRun(
- """
+ """
@PrimaryKey
int id;
@Embedded
@@ -338,11 +362,12 @@
@Test
fun relation_view() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid")
public List<UserSummary> user;
- """, COMMON.USER_SUMMARY
+ """,
+ COMMON.USER_SUMMARY
) { _ ->
}.compilesWithoutError()
}
@@ -350,11 +375,12 @@
@Test
fun relation_notCollection() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid")
public User user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { _ ->
}.compilesWithoutError()
}
@@ -362,25 +388,28 @@
@Test
fun relation_columnInfo() {
singleRun(
- """
+ """
int id;
@ColumnInfo
@Relation(parentColumn = "id", entityColumn = "uid")
public List<User> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_USE_MORE_THAN_ONE_POJO_FIELD_ANNOTATION)
+ ProcessorErrors.CANNOT_USE_MORE_THAN_ONE_POJO_FIELD_ANNOTATION
+ )
}
@Test
fun relation_notEntity() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid")
public List<NotAnEntity> user;
- """, COMMON.NOT_AN_ENTITY
+ """,
+ COMMON.NOT_AN_ENTITY
) { _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.NOT_ENTITY_OR_VIEW)
}
@@ -388,36 +417,40 @@
@Test
fun relation_missingParent() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "idk", entityColumn = "uid")
public List<User> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { _ ->
}.failsToCompile().withErrorContaining(
- relationCannotFindParentEntityField("foo.bar.MyPojo", "idk", listOf("id"))
+ relationCannotFindParentEntityField("foo.bar.MyPojo", "idk", listOf("id"))
)
}
@Test
fun relation_missingEntityField() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "idk")
public List<User> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { _ ->
}.failsToCompile().withErrorContaining(
- relationCannotFindEntityField("foo.bar.User", "idk",
- listOf("uid", "name", "lastName", "age"))
+ relationCannotFindEntityField(
+ "foo.bar.User", "idk",
+ listOf("uid", "name", "lastName", "age")
+ )
)
}
@Test
fun relation_missingType() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid")
public List<User> user;
@@ -429,7 +462,7 @@
@Test
fun relation_nestedField() {
singleRun(
- """
+ """
static class Nested {
@ColumnInfo(name = "foo")
public int id;
@@ -438,7 +471,8 @@
Nested nested;
@Relation(parentColumn = "foo", entityColumn = "uid")
public List<User> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { pojo ->
assertThat(pojo.relations.first().parentField.columnName, `is`("foo"))
}.compilesWithoutError()
@@ -447,7 +481,7 @@
@Test
fun relation_nestedRelation() {
singleRun(
- """
+ """
static class UserWithNested {
@Embedded
public User user;
@@ -457,7 +491,8 @@
int id;
@Relation(parentColumn = "id", entityColumn = "uid", entity = User.class)
public List<UserWithNested> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { pojo, _ ->
assertThat(pojo.relations.first().parentField.name, `is`("id"))
}.compilesWithoutError().withWarningCount(0)
@@ -466,11 +501,12 @@
@Test
fun relation_affinityMismatch() {
singleRun(
- """
+ """
String id;
@Relation(parentColumn = "id", entityColumn = "uid")
public List<User> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { pojo, invocation ->
// trigger assignment evaluation
RelationCollector.createCollectors(invocation.context, pojo.relations)
@@ -478,22 +514,24 @@
assertThat(pojo.relations.first().entityField.name, `is`("uid"))
assertThat(pojo.relations.first().parentField.name, `is`("id"))
}.compilesWithoutError().withWarningContaining(
- ProcessorErrors.relationAffinityMismatch(
- parentAffinity = SQLTypeAffinity.TEXT,
- childAffinity = SQLTypeAffinity.INTEGER,
- parentColumn = "id",
- childColumn = "uid")
+ ProcessorErrors.relationAffinityMismatch(
+ parentAffinity = SQLTypeAffinity.TEXT,
+ childAffinity = SQLTypeAffinity.INTEGER,
+ parentColumn = "id",
+ childColumn = "uid"
+ )
)
}
@Test
fun relation_simple() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid")
public List<User> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { pojo ->
assertThat(pojo.relations.size, `is`(1))
assertThat(pojo.relations.first().entityField.name, `is`("uid"))
@@ -504,28 +542,32 @@
@Test
fun relation_badProjection() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid", projection={"i_dont_exist"})
public List<User> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.relationBadProject("foo.bar.User", listOf("i_dont_exist"),
- listOf("uid", "name", "lastName", "ageColumn"))
+ ProcessorErrors.relationBadProject(
+ "foo.bar.User", listOf("i_dont_exist"),
+ listOf("uid", "name", "lastName", "ageColumn")
+ )
)
}
@Test
fun relation_badReturnTypeInGetter() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid")
private List<User> user;
public void setUser(List<User> user){ this.user = user;}
public User getUser(){return null;}
- """, COMMON.USER
+ """,
+ COMMON.USER
) { _ ->
}.failsToCompile().withErrorContaining(CANNOT_FIND_GETTER_FOR_FIELD)
}
@@ -533,12 +575,13 @@
@Test
fun relation_primitiveList() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid", projection={"uid"},
entity = User.class)
public List<Integer> userIds;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { pojo ->
assertThat(pojo.relations.size, `is`(1))
val rel = pojo.relations.first()
@@ -550,12 +593,13 @@
@Test
fun relation_stringList() {
singleRun(
- """
+ """
int id;
@Relation(parentColumn = "id", entityColumn = "uid", projection={"name"},
entity = User.class)
public List<String> userNames;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { pojo ->
assertThat(pojo.relations.size, `is`(1))
val rel = pojo.relations.first()
@@ -571,7 +615,8 @@
int id;
@Relation(parentColumn = "id", entityColumn = "uid")
public List<? extends User> user;
- """, COMMON.USER
+ """,
+ COMMON.USER
) { pojo ->
assertThat(pojo.relations.size, `is`(1))
assertThat(pojo.relations.first().entityField.name, `is`("uid"))
@@ -617,14 +662,19 @@
parentColumn = "uid", entityColumn = "friendId")
)
public List<User> user;
- """, COMMON.USER, junctionEntity
+ """,
+ COMMON.USER, junctionEntity
) { pojo ->
assertThat(pojo.relations.size, `is`(1))
assertThat(pojo.relations.first().junction, notNullValue())
- assertThat(pojo.relations.first().junction!!.parentField.columnName,
- `is`("uid"))
- assertThat(pojo.relations.first().junction!!.entityField.columnName,
- `is`("friendId"))
+ assertThat(
+ pojo.relations.first().junction!!.parentField.columnName,
+ `is`("uid")
+ )
+ assertThat(
+ pojo.relations.first().junction!!.entityField.columnName,
+ `is`("friendId")
+ )
}.compilesWithoutError().withWarningCount(0)
}
@@ -651,7 +701,8 @@
parentColumn = "uid", entityColumn = "friendId")
)
public List<User> user;
- """, COMMON.USER, junctionEntity
+ """,
+ COMMON.USER, junctionEntity
) { _ ->
}.compilesWithoutError().withWarningCount(0)
}
@@ -691,7 +742,8 @@
parentColumn = "friendId", entityColumn = "uid",
associateBy = @Junction(UserFriendsXRef.class))
public List<User> user;
- """, COMMON.USER, junctionEntity
+ """,
+ COMMON.USER, junctionEntity
) { _ ->
}.compilesWithoutError().withWarningCount(0)
}
@@ -717,10 +769,14 @@
associateBy = @Junction(UserFriendsXRef.class)
)
public List<User> user;
- """, COMMON.USER, junctionEntity
+ """,
+ COMMON.USER, junctionEntity
) { _ ->
- }.failsToCompile().withErrorContaining(relationCannotFindJunctionParentField(
- "foo.bar.UserFriendsXRef", "id", listOf("friendFrom", "uid")))
+ }.failsToCompile().withErrorContaining(
+ relationCannotFindJunctionParentField(
+ "foo.bar.UserFriendsXRef", "id", listOf("friendFrom", "uid")
+ )
+ )
}
@Test
@@ -744,10 +800,13 @@
associateBy = @Junction(UserFriendsXRef.class)
)
public List<User> user;
- """, COMMON.USER, junctionEntity
+ """,
+ COMMON.USER, junctionEntity
) { _ ->
- }.failsToCompile().withErrorContaining(relationCannotFindJunctionEntityField(
- "foo.bar.UserFriendsXRef", "uid", listOf("friendA", "friendB"))
+ }.failsToCompile().withErrorContaining(
+ relationCannotFindJunctionEntityField(
+ "foo.bar.UserFriendsXRef", "uid", listOf("friendA", "friendB")
+ )
)
}
@@ -774,10 +833,13 @@
parentColumn = "bad_col")
)
public List<User> user;
- """, COMMON.USER, junctionEntity
+ """,
+ COMMON.USER, junctionEntity
) { _ ->
- }.failsToCompile().withErrorContaining(relationCannotFindJunctionParentField(
- "foo.bar.UserFriendsXRef", "bad_col", listOf("friendA", "friendB"))
+ }.failsToCompile().withErrorContaining(
+ relationCannotFindJunctionParentField(
+ "foo.bar.UserFriendsXRef", "bad_col", listOf("friendA", "friendB")
+ )
)
}
@@ -804,10 +866,13 @@
entityColumn = "bad_col")
)
public List<User> user;
- """, COMMON.USER, junctionEntity
+ """,
+ COMMON.USER, junctionEntity
) { _ ->
- }.failsToCompile().withErrorContaining(relationCannotFindJunctionEntityField(
- "foo.bar.UserFriendsXRef", "bad_col", listOf("friendA", "friendB"))
+ }.failsToCompile().withErrorContaining(
+ relationCannotFindJunctionEntityField(
+ "foo.bar.UserFriendsXRef", "bad_col", listOf("friendA", "friendB")
+ )
)
}
@@ -833,10 +898,12 @@
parentColumn = "friendId", entityColumn = "uid",
associateBy = @Junction(UserFriendsXRef.class))
public List<User> user;
- """, COMMON.USER, junctionEntity
+ """,
+ COMMON.USER, junctionEntity
) { _ ->
}.compilesWithoutError().withWarningCount(2).withWarningContaining(
- junctionColumnWithoutIndex("foo.bar.UserFriendsXRef", "uid"))
+ junctionColumnWithoutIndex("foo.bar.UserFriendsXRef", "uid")
+ )
}
@Test
@@ -848,51 +915,65 @@
""".toJFO(MY_POJO.toString())
simpleRun(pojo) { invocation ->
val element = invocation.processingEnv.requireTypeElement(MY_POJO)
- val pojo1 = PojoProcessor.createFor(invocation.context, element,
- FieldProcessor.BindingScope.BIND_TO_STMT, null).process()
+ val pojo1 = PojoProcessor.createFor(
+ invocation.context, element,
+ FieldProcessor.BindingScope.BIND_TO_STMT, null
+ ).process()
assertThat(pojo1, notNullValue())
- val pojo2 = PojoProcessor.createFor(invocation.context, element,
- FieldProcessor.BindingScope.BIND_TO_STMT, null).process()
+ val pojo2 = PojoProcessor.createFor(
+ invocation.context, element,
+ FieldProcessor.BindingScope.BIND_TO_STMT, null
+ ).process()
assertThat(pojo2, sameInstance(pojo1))
- val pojo3 = PojoProcessor.createFor(invocation.context, element,
- FieldProcessor.BindingScope.READ_FROM_CURSOR, null).process()
+ val pojo3 = PojoProcessor.createFor(
+ invocation.context, element,
+ FieldProcessor.BindingScope.READ_FROM_CURSOR, null
+ ).process()
assertThat(pojo3, notNullValue())
assertThat(pojo3, not(sameInstance(pojo1)))
- val pojo4 = PojoProcessor.createFor(invocation.context, element,
- FieldProcessor.BindingScope.TWO_WAY, null).process()
+ val pojo4 = PojoProcessor.createFor(
+ invocation.context, element,
+ FieldProcessor.BindingScope.TWO_WAY, null
+ ).process()
assertThat(pojo4, notNullValue())
assertThat(pojo4, not(sameInstance(pojo1)))
assertThat(pojo4, not(sameInstance(pojo3)))
- val pojo5 = PojoProcessor.createFor(invocation.context, element,
- FieldProcessor.BindingScope.TWO_WAY, null).process()
+ val pojo5 = PojoProcessor.createFor(
+ invocation.context, element,
+ FieldProcessor.BindingScope.TWO_WAY, null
+ ).process()
assertThat(pojo5, sameInstance(pojo4))
val type = invocation.context.COMMON_TYPES.STRING
val mockElement = mock(XFieldElement::class.java)
doReturn(type).`when`(mockElement).type
val fakeField = Field(
- element = mockElement,
- name = "foo",
- type = type,
- affinity = SQLTypeAffinity.TEXT,
- columnName = "foo",
- parent = null,
- indexed = false
+ element = mockElement,
+ name = "foo",
+ type = type,
+ affinity = SQLTypeAffinity.TEXT,
+ columnName = "foo",
+ parent = null,
+ indexed = false
)
val fakeEmbedded = EmbeddedField(fakeField, "", null)
- val pojo6 = PojoProcessor.createFor(invocation.context, element,
- FieldProcessor.BindingScope.TWO_WAY, fakeEmbedded).process()
+ val pojo6 = PojoProcessor.createFor(
+ invocation.context, element,
+ FieldProcessor.BindingScope.TWO_WAY, fakeEmbedded
+ ).process()
assertThat(pojo6, notNullValue())
assertThat(pojo6, not(sameInstance(pojo1)))
assertThat(pojo6, not(sameInstance(pojo3)))
assertThat(pojo6, not(sameInstance(pojo4)))
- val pojo7 = PojoProcessor.createFor(invocation.context, element,
- FieldProcessor.BindingScope.TWO_WAY, fakeEmbedded).process()
+ val pojo7 = PojoProcessor.createFor(
+ invocation.context, element,
+ FieldProcessor.BindingScope.TWO_WAY, fakeEmbedded
+ ).process()
assertThat(pojo7, sameInstance(pojo6))
}.compilesWithoutError()
}
@@ -920,8 +1001,10 @@
val param = pojo.constructor?.params?.first()
assertThat(param, instanceOf(Constructor.Param.FieldParam::class.java))
assertThat((param as Constructor.Param.FieldParam).field.name, `is`("mName"))
- assertThat(pojo.fields.find { it.name == "mName" }?.setter?.callType,
- `is`(CallType.CONSTRUCTOR))
+ assertThat(
+ pojo.fields.find { it.name == "mName" }?.setter?.callType,
+ `is`(CallType.CONSTRUCTOR)
+ )
}.compilesWithoutError()
}
@@ -937,8 +1020,10 @@
val param = pojo.constructor?.params?.first()
assertThat(param, instanceOf(Constructor.Param.FieldParam::class.java))
assertThat((param as Constructor.Param.FieldParam).field.name, `is`("mName"))
- assertThat(pojo.fields.find { it.name == "mName" }?.setter?.callType,
- `is`(CallType.CONSTRUCTOR))
+ assertThat(
+ pojo.fields.find { it.name == "mName" }?.setter?.callType,
+ `is`(CallType.CONSTRUCTOR)
+ )
}.compilesWithoutError()
}
@@ -952,59 +1037,70 @@
"""
singleRun(pojo) { _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.ambigiousConstructor(MY_POJO.toString(),
- "name", listOf("mName", "_name"))
+ ProcessorErrors.ambigiousConstructor(
+ MY_POJO.toString(),
+ "name", listOf("mName", "_name")
+ )
)
}
@Test
fun constructor_noMatchBadType() {
- singleRun("""
+ singleRun(
+ """
int foo;
public MyPojo(String foo) {
}
- """) { _ ->
+ """
+ ) { _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.MISSING_POJO_CONSTRUCTOR)
}
@Test
fun constructor_noMatch() {
- singleRun("""
+ singleRun(
+ """
String mName;
String _name;
public MyPojo(String foo) {
}
- """) { _ ->
+ """
+ ) { _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.MISSING_POJO_CONSTRUCTOR)
}
@Test
fun constructor_noMatchMultiArg() {
- singleRun("""
+ singleRun(
+ """
String mName;
int bar;
public MyPojo(String foo, String name) {
}
- """) { _ ->
+ """
+ ) { _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.MISSING_POJO_CONSTRUCTOR)
}
@Test
fun constructor_multipleMatching() {
- singleRun("""
+ singleRun(
+ """
String mName;
String mLastName;
public MyPojo(String name) {
}
public MyPojo(String name, String lastName) {
}
- """) { _ ->
+ """
+ ) { _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.TOO_MANY_POJO_CONSTRUCTORS)
}
@Test
fun constructor_multipleMatchingWithIgnored() {
- singleRun("""
+ singleRun(
+ """
String mName;
String mLastName;
@Ignore
@@ -1012,65 +1108,83 @@
}
public MyPojo(String name, String lastName) {
}
- """) { pojo ->
+ """
+ ) { pojo ->
assertThat(pojo.constructor, notNullValue())
assertThat(pojo.constructor?.params?.size, `is`(2))
- assertThat(pojo.fields.find { it.name == "mName" }?.setter?.callType,
- `is`(CallType.CONSTRUCTOR))
- assertThat(pojo.fields.find { it.name == "mLastName" }?.setter?.callType,
- `is`(CallType.CONSTRUCTOR))
+ assertThat(
+ pojo.fields.find { it.name == "mName" }?.setter?.callType,
+ `is`(CallType.CONSTRUCTOR)
+ )
+ assertThat(
+ pojo.fields.find { it.name == "mLastName" }?.setter?.callType,
+ `is`(CallType.CONSTRUCTOR)
+ )
}.compilesWithoutError()
}
@Test
fun constructor_dontTryForBindToScope() {
- singleRun("""
+ singleRun(
+ """
String mName;
String mLastName;
- """) { _, invocation ->
- val process2 = PojoProcessor.createFor(context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(MY_POJO),
- bindingScope = FieldProcessor.BindingScope.BIND_TO_STMT,
- parent = null).process()
+ """
+ ) { _, invocation ->
+ val process2 = PojoProcessor.createFor(
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(MY_POJO),
+ bindingScope = FieldProcessor.BindingScope.BIND_TO_STMT,
+ parent = null
+ ).process()
assertThat(process2.constructor, nullValue())
}.compilesWithoutError()
}
@Test
fun constructor_bindForTwoWay() {
- singleRun("""
+ singleRun(
+ """
String mName;
String mLastName;
- """) { _, invocation ->
- val process2 = PojoProcessor.createFor(context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(MY_POJO),
- bindingScope = FieldProcessor.BindingScope.TWO_WAY,
- parent = null).process()
+ """
+ ) { _, invocation ->
+ val process2 = PojoProcessor.createFor(
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(MY_POJO),
+ bindingScope = FieldProcessor.BindingScope.TWO_WAY,
+ parent = null
+ ).process()
assertThat(process2.constructor, notNullValue())
}.compilesWithoutError()
}
@Test
fun constructor_multipleMatching_withNoArg() {
- singleRun("""
+ singleRun(
+ """
String mName;
String mLastName;
public MyPojo() {
}
public MyPojo(String name, String lastName) {
}
- """) { pojo ->
+ """
+ ) { pojo ->
assertThat(pojo.constructor?.params?.size ?: -1, `is`(0))
}.compilesWithoutError().withWarningContaining(
- ProcessorErrors.TOO_MANY_POJO_CONSTRUCTORS_CHOOSING_NO_ARG)
+ ProcessorErrors.TOO_MANY_POJO_CONSTRUCTORS_CHOOSING_NO_ARG
+ )
}
@Test // added for b/69562125
fun constructor_withNullabilityAnnotation() {
- singleRun("""
+ singleRun(
+ """
String mName;
public MyPojo(@androidx.annotation.NonNull String name) {}
- """) { pojo ->
+ """
+ ) { pojo ->
val constructor = pojo.constructor
assertThat(constructor, notNullValue())
assertThat(constructor!!.params.size, `is`(1))
@@ -1079,47 +1193,56 @@
@Test
fun constructor_relationParameter() {
- singleRun("""
+ singleRun(
+ """
@Relation(entity = foo.bar.User.class, parentColumn = "uid", entityColumn="uid",
projection = "name")
public List<String> items;
public String uid;
public MyPojo(String uid, List<String> items) {
}
- """, COMMON.USER) { _ ->
+ """,
+ COMMON.USER
+ ) { _ ->
}.compilesWithoutError()
}
@Test
fun recursion_1Level_embedded() {
singleRun(
- """
+ """
@Embedded
MyPojo myPojo;
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo -> foo.bar.MyPojo"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo -> foo.bar.MyPojo"
+ )
+ )
}
@Test
fun recursion_1Level_relation() {
singleRun(
- """
+ """
long id;
long parentId;
@Relation(parentColumn = "id", entityColumn = "parentId")
Set<MyPojo> children;
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo -> foo.bar.MyPojo"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo -> foo.bar.MyPojo"
+ )
+ )
}
@Test
fun recursion_1Level_relation_specifyEntity() {
singleRun(
- """
+ """
@Embedded
A a;
@@ -1140,16 +1263,19 @@
@Embedded
B b;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo.A -> foo.bar.MyPojo.A"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo.A -> foo.bar.MyPojo.A"
+ )
+ )
}
@Test
fun recursion_2Levels_relationToEmbed() {
singleRun(
- """
+ """
int pojoId;
@Relation(parentColumn = "pojoId", entityColumn = "entityId")
@@ -1162,16 +1288,19 @@
@Embedded
MyPojo myPojo;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo -> foo.bar.MyPojo.MyEntity -> foo.bar.MyPojo"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo -> foo.bar.MyPojo.MyEntity -> foo.bar.MyPojo"
+ )
+ )
}
@Test
fun recursion_2Levels_onlyEmbeds_pojoToEntity() {
singleRun(
- """
+ """
@Embedded
A a;
@@ -1180,32 +1309,38 @@
@Embedded
MyPojo myPojo;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo"
+ )
+ )
}
@Test
fun recursion_2Levels_onlyEmbeds_onlyPojos() {
singleRun(
- """
+ """
@Embedded
A a;
static class A {
@Embedded
MyPojo myPojo;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo"
+ )
+ )
}
@Test
fun recursion_2Level_relationToEmbed() {
singleRun(
- """
+ """
@Embedded
A a;
@@ -1226,16 +1361,19 @@
@Embedded
B b;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo.A -> foo.bar.MyPojo.AWithB -> foo.bar.MyPojo.A"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo.A -> foo.bar.MyPojo.AWithB -> foo.bar.MyPojo.A"
+ )
+ )
}
@Test
fun recursion_3Levels() {
singleRun(
- """
+ """
@Embedded
A a;
public static class A {
@@ -1246,16 +1384,19 @@
@Embedded
MyPojo myPojo;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo.B -> foo.bar.MyPojo"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo.B -> foo.bar.MyPojo"
+ )
+ )
}
@Test
fun recursion_1Level_1LevelDown() {
singleRun(
- """
+ """
@Embedded
A a;
static class A {
@@ -1266,16 +1407,19 @@
@Embedded
A a;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo.A -> foo.bar.MyPojo.B -> foo.bar.MyPojo.A"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo.A -> foo.bar.MyPojo.B -> foo.bar.MyPojo.A"
+ )
+ )
}
@Test
fun recursion_branchAtLevel0_afterBackTrack() {
singleRun(
- """
+ """
@PrimaryKey
int id;
@Embedded
@@ -1292,16 +1436,19 @@
@Embedded
MyPojo myPojo;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo -> foo.bar.MyPojo.C -> foo.bar.MyPojo"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo -> foo.bar.MyPojo.C -> foo.bar.MyPojo"
+ )
+ )
}
@Test
fun recursion_branchAtLevel1_afterBackTrack() {
singleRun(
- """
+ """
@PrimaryKey
int id;
@Embedded
@@ -1318,27 +1465,30 @@
}
static class C {
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyPojo -> foo.bar.MyPojo.A -> foo.bar.MyPojo"
+ )
+ )
}
@Test
fun dataClass_primaryConstructor() {
listOf(
- TestData.AllDefaultVals::class.java.canonicalName!!,
- TestData.AllDefaultVars::class.java.canonicalName!!,
- TestData.SomeDefaultVals::class.java.canonicalName!!,
- TestData.SomeDefaultVars::class.java.canonicalName!!,
- TestData.WithJvmOverloads::class.java.canonicalName!!
+ TestData.AllDefaultVals::class.java.canonicalName!!,
+ TestData.AllDefaultVars::class.java.canonicalName!!,
+ TestData.SomeDefaultVals::class.java.canonicalName!!,
+ TestData.SomeDefaultVars::class.java.canonicalName!!,
+ TestData.WithJvmOverloads::class.java.canonicalName!!
).forEach {
simpleRun { invocation ->
PojoProcessor.createFor(
- context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(it),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(it),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
).process()
}.compilesWithoutError().withWarningCount(0)
}
@@ -1348,12 +1498,12 @@
fun dataClass_withJvmOverloads_primaryConstructor() {
simpleRun { invocation ->
PojoProcessor.createFor(
- context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(
- TestData.WithJvmOverloads::class
- ),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(
+ TestData.WithJvmOverloads::class
+ ),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
).process()
}.compilesWithoutError().withWarningCount(0)
}
@@ -1361,7 +1511,7 @@
@Test
fun ignoredColumns() {
simpleRun(
- """
+ """
package foo.bar;
import androidx.room.*;
@@ -1370,11 +1520,14 @@
public String foo;
public String bar;
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- val pojo = PojoProcessor.createFor(context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(MY_POJO),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ val pojo = PojoProcessor.createFor(
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(MY_POJO),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
+ ).process()
assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
assertThat(pojo.fields.find { it.name == "bar" }, nullValue())
}.compilesWithoutError()
@@ -1401,11 +1554,14 @@
return this.foo;
}
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- val pojo = PojoProcessor.createFor(context = invocation.context,
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ val pojo = PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ parent = null
+ ).process()
assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
assertThat(pojo.fields.find { it.name == "bar" }, nullValue())
}.compilesWithoutError()
@@ -1431,11 +1587,14 @@
this.foo = foo;
}
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- val pojo = PojoProcessor.createFor(context = invocation.context,
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ val pojo = PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ parent = null
+ ).process()
assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
assertThat(pojo.fields.find { it.name == "bar" }, nullValue())
}.compilesWithoutError()
@@ -1444,7 +1603,7 @@
@Test
fun ignoredColumns_columnInfo() {
simpleRun(
- """
+ """
package foo.bar;
import androidx.room.*;
@@ -1454,11 +1613,14 @@
@ColumnInfo(name = "my_bar")
public String bar;
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- val pojo = PojoProcessor.createFor(context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(MY_POJO),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ val pojo = PojoProcessor.createFor(
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(MY_POJO),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
+ ).process()
assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
assertThat(pojo.fields.find { it.name == "bar" }, nullValue())
}.compilesWithoutError()
@@ -1467,7 +1629,7 @@
@Test
fun ignoredColumns_missing() {
simpleRun(
- """
+ """
package foo.bar;
import androidx.room.*;
@@ -1476,15 +1638,19 @@
public String foo;
public String bar;
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- val pojo = PojoProcessor.createFor(context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(MY_POJO),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ val pojo = PojoProcessor.createFor(
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(MY_POJO),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
+ ).process()
assertThat(pojo.fields.find { it.name == "foo" }, notNullValue())
assertThat(pojo.fields.find { it.name == "bar" }, notNullValue())
}.failsToCompile().withErrorContaining(
- ProcessorErrors.missingIgnoredColumns(listOf("no_such_column")))
+ ProcessorErrors.missingIgnoredColumns(listOf("no_such_column"))
+ )
}
@Test
@@ -1500,11 +1666,14 @@
public String getFoo() { return foo; }
public String getBar() { return bar; }
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- PojoProcessor.createFor(context = invocation.context,
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.BIND_TO_STMT,
- parent = null).process()
+ parent = null
+ ).process()
}.compilesWithoutError()
}
@@ -1521,11 +1690,14 @@
public String getFoo() { return foo; }
public String getBar() { return bar; }
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- PojoProcessor.createFor(context = invocation.context,
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.TWO_WAY,
- parent = null).process()
+ parent = null
+ ).process()
}.failsToCompile().withErrorContaining("Cannot find setter for field.")
}
@@ -1542,11 +1714,14 @@
public String getFoo() { return foo; }
public String getBar() { return bar; }
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- PojoProcessor.createFor(context = invocation.context,
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ parent = null
+ ).process()
}.failsToCompile().withErrorContaining("Cannot find setter for field.")
}
@@ -1563,11 +1738,14 @@
public void setFoo(String foo) { this.foo = foo; }
public void setBar(String bar) { this.bar = bar; }
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- PojoProcessor.createFor(context = invocation.context,
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.BIND_TO_STMT,
- parent = null).process()
+ parent = null
+ ).process()
}.failsToCompile().withErrorContaining("Cannot find getter for field.")
}
@@ -1584,11 +1762,14 @@
public void setFoo(String foo) { this.foo = foo; }
public void setBar(String bar) { this.bar = bar; }
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- PojoProcessor.createFor(context = invocation.context,
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.TWO_WAY,
- parent = null).process()
+ parent = null
+ ).process()
}.failsToCompile().withErrorContaining("Cannot find getter for field.")
}
@@ -1605,11 +1786,14 @@
public void setFoo(String foo) { this.foo = foo; }
public void setBar(String bar) { this.bar = bar; }
}
- """.toJFO(MY_POJO.toString())) { invocation ->
- PojoProcessor.createFor(context = invocation.context,
+ """.toJFO(MY_POJO.toString())
+ ) { invocation ->
+ PojoProcessor.createFor(
+ context = invocation.context,
element = invocation.processingEnv.requireTypeElement(MY_POJO),
bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ parent = null
+ ).process()
}.compilesWithoutError()
}
@@ -1652,10 +1836,12 @@
val all = (jfos.toList() + pojoJFO).toTypedArray()
return simpleRun(*all, classpathFiles = classpathFiles) { invocation ->
handler.invoke(
- PojoProcessor.createFor(context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(MY_POJO),
- bindingScope = FieldProcessor.BindingScope.TWO_WAY,
- parent = null).process(),
+ PojoProcessor.createFor(
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(MY_POJO),
+ bindingScope = FieldProcessor.BindingScope.TWO_WAY,
+ parent = null
+ ).process(),
invocation
)
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/ProjectionExpanderTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/ProjectionExpanderTest.kt
index a402052..08d461b 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/ProjectionExpanderTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/ProjectionExpanderTest.kt
@@ -43,7 +43,8 @@
val ENTITIES = arrayOf(
JavaFileObjects.forSourceString(
- "foo.bar.User", DATABASE_PREFIX + """
+ "foo.bar.User",
+ DATABASE_PREFIX + """
@Entity
public class User {
@PrimaryKey
@@ -55,7 +56,8 @@
"""
),
JavaFileObjects.forSourceString(
- "foo.bar.Pet", DATABASE_PREFIX + """
+ "foo.bar.Pet",
+ DATABASE_PREFIX + """
@Entity
public class Pet {
@PrimaryKey
@@ -65,7 +67,8 @@
"""
),
JavaFileObjects.forSourceString(
- "foo.bar.Team", DATABASE_PREFIX + """
+ "foo.bar.Team",
+ DATABASE_PREFIX + """
@Entity
public class Team {
@PrimaryKey
@@ -75,7 +78,8 @@
"""
),
JavaFileObjects.forSourceString(
- "foo.bar.Employee", DATABASE_PREFIX + """
+ "foo.bar.Employee",
+ DATABASE_PREFIX + """
@Entity
public class Employee {
@PrimaryKey
@@ -86,7 +90,8 @@
"""
),
JavaFileObjects.forSourceString(
- "foo.bar.EmployeeSummary", DATABASE_PREFIX + """
+ "foo.bar.EmployeeSummary",
+ DATABASE_PREFIX + """
public class EmployeeSummary {
public int id;
public String name;
@@ -238,7 +243,7 @@
}
""",
"SELECT *, (SELECT COUNT(*) FROM User AS u WHERE u.firstName = User.firstName) = 1 " +
- "AS hasUniqueFirstName FROM User",
+ "AS hasUniqueFirstName FROM User",
"""
SELECT `id`, `firstName`, (SELECT COUNT(*) FROM User AS u
WHERE u.firstName = User.firstName) = 1 AS hasUniqueFirstName FROM User
@@ -266,7 +271,8 @@
@Test
fun extraColumn() {
testInterpret(
- "foo.bar.UserVariant", """
+ "foo.bar.UserVariant",
+ """
public class UserVariant {
public int id;
public String firstName;
@@ -313,7 +319,7 @@
}
""",
"SELECT * FROM Employee LEFT OUTER JOIN Employee AS manager_ " +
- "ON User.managerId = manager_.id",
+ "ON User.managerId = manager_.id",
"""
SELECT `Employee`.`id` AS `id`, `Employee`.`name` AS `name`,
`Employee`.`managerId` AS `managerId`, `manager_`.`id` AS `manager_id`,
@@ -327,7 +333,8 @@
@Test
fun joinWithoutPrefix() {
testInterpret(
- "foo.bar.UserAndPet", """
+ "foo.bar.UserAndPet",
+ """
public class UserAndPet {
@Embedded
public User user;
@@ -348,7 +355,8 @@
@Test
fun embedPojo() {
testInterpret(
- "foo.bar.TeamMember", """
+ "foo.bar.TeamMember",
+ """
public class TeamMember {
@Embedded
Team team;
@@ -357,7 +365,7 @@
}
""",
"SELECT * FROM Team LEFT OUTER JOIN Employee AS employee_" +
- " ON Team.id = employee_.teamId",
+ " ON Team.id = employee_.teamId",
"""
SELECT `Team`.`id` AS `id`, `Team`.`name` AS `name`,
`employee_`.`id` AS `employee_id`, `employee_`.`name` AS `employee_name`
@@ -392,7 +400,8 @@
@Test
fun specifyAlias() {
testInterpret(
- "foo.bar.UserPair", """
+ "foo.bar.UserPair",
+ """
public class UserPair {
@Embedded(prefix = "a_")
public User a;
@@ -413,7 +422,8 @@
@Test
fun parameter() {
testInterpret(
- "foo.bar.UserSummary", """
+ "foo.bar.UserSummary",
+ """
public class UserSummary {
public int id;
public String firstName;
@@ -427,7 +437,8 @@
@Test
fun noNeedToExpand() {
testInterpret(
- "foo.bar.UserSummary", """
+ "foo.bar.UserSummary",
+ """
public class UserSummary {
public int id;
public String firstName;
@@ -475,8 +486,8 @@
input = null,
original = "SELECT * FROM user as u INNER JOIN Employee AS e ON(u.id = e.id)",
expected = "SELECT `u`.`id` AS `id`, `u`.`firstName` AS `firstName`, `u`" +
- ".`lastName` AS `lastName`, `u`.`teamId` AS `teamId` FROM user as u INNER " +
- "JOIN Employee AS e ON(u.id = e.id)"
+ ".`lastName` AS `lastName`, `u`.`teamId` AS `teamId` FROM user as u INNER " +
+ "JOIN Employee AS e ON(u.id = e.id)"
)
}
@@ -542,12 +553,14 @@
@Test
fun newlineInProjection() {
queryWithPojo(
- "foo.bar.UserSummary", """
+ "foo.bar.UserSummary",
+ """
public class UserSummary {
public int id;
public String name;
}
- """, """
+ """,
+ """
SELECT User
.
*,
@@ -561,7 +574,8 @@
"""
) { expanded, _ ->
assertThat(
- expanded, `is`(
+ expanded,
+ `is`(
equalTo(
"""
SELECT `User`.`id`,
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
index 6c2ca06..1f1e14e 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
@@ -88,11 +88,11 @@
fun createField(name: String, columnName: String? = null): Field {
val (element, type) = mockElementAndType()
return Field(
- element = element,
- name = name,
- type = type,
- columnName = columnName ?: name,
- affinity = null
+ element = element,
+ name = name,
+ type = type,
+ columnName = columnName ?: name,
+ affinity = null
)
}
}
@@ -100,42 +100,49 @@
@Test
fun testReadNoParams() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT * from User")
abstract public int[] foo();
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
assertThat(parsedQuery.name, `is`("foo"))
assertThat(parsedQuery.parameters.size, `is`(0))
- assertThat(parsedQuery.returnType.typeName,
- `is`(ArrayTypeName.of(TypeName.INT) as TypeName))
+ assertThat(
+ parsedQuery.returnType.typeName,
+ `is`(ArrayTypeName.of(TypeName.INT) as TypeName)
+ )
}.compilesWithoutError()
}
@Test
fun testSingleParam() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT * from User where uid = :x")
abstract public long foo(int x);
- """) { parsedQuery, invocation ->
+ """
+ ) { parsedQuery, invocation ->
assertThat(parsedQuery.name, `is`("foo"))
assertThat(parsedQuery.returnType.typeName, `is`(TypeName.LONG))
assertThat(parsedQuery.parameters.size, `is`(1))
val param = parsedQuery.parameters.first()
assertThat(param.name, `is`("x"))
assertThat(param.sqlName, `is`("x"))
- assertThat(param.type,
- `is`(invocation.processingEnv.requireType(TypeName.INT)))
+ assertThat(
+ param.type,
+ `is`(invocation.processingEnv.requireType(TypeName.INT))
+ )
}.compilesWithoutError()
}
@Test
fun testVarArgs() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT * from User where uid in (:ids)")
abstract public long foo(int... ids);
- """) { parsedQuery, invocation ->
+ """
+ ) { parsedQuery, invocation ->
assertThat(parsedQuery.name, `is`("foo"))
assertThat(parsedQuery.returnType.typeName, `is`(TypeName.LONG))
assertThat(parsedQuery.parameters.size, `is`(1))
@@ -143,18 +150,21 @@
assertThat(param.name, `is`("ids"))
assertThat(param.sqlName, `is`("ids"))
val env = invocation.processingEnv
- assertThat(param.type,
- `is`(env.getArrayType(TypeName.INT) as XType))
+ assertThat(
+ param.type,
+ `is`(env.getArrayType(TypeName.INT) as XType)
+ )
}.compilesWithoutError()
}
@Test
fun testParamBindingMatchingNoName() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT uid from User where uid = :id")
abstract public long getIdById(int id);
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
val section = parsedQuery.query.bindSections.first()
val param = parsedQuery.parameters.firstOrNull()
assertThat(section, notNullValue())
@@ -166,65 +176,76 @@
@Test
fun testParamBindingMatchingSimpleBind() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT uid from User where uid = :id")
abstract public long getIdById(int id);
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
val section = parsedQuery.query.bindSections.first()
val param = parsedQuery.parameters.firstOrNull()
assertThat(section, notNullValue())
assertThat(param, notNullValue())
- assertThat(parsedQuery.sectionToParamMapping,
- `is`(listOf(Pair(section, param))))
+ assertThat(
+ parsedQuery.sectionToParamMapping,
+ `is`(listOf(Pair(section, param)))
+ )
}.compilesWithoutError()
}
@Test
fun testParamBindingTwoBindVarsIntoTheSameParameter() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT uid from User where uid = :id OR uid = :id")
abstract public long getIdById(int id);
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
val section = parsedQuery.query.bindSections[0]
val section2 = parsedQuery.query.bindSections[1]
val param = parsedQuery.parameters.firstOrNull()
assertThat(section, notNullValue())
assertThat(section2, notNullValue())
assertThat(param, notNullValue())
- assertThat(parsedQuery.sectionToParamMapping,
- `is`(listOf(Pair(section, param), Pair(section2, param))))
+ assertThat(
+ parsedQuery.sectionToParamMapping,
+ `is`(listOf(Pair(section, param), Pair(section2, param)))
+ )
}.compilesWithoutError()
}
@Test
fun testMissingParameterForBinding() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT uid from User where uid = :id OR uid = :uid")
abstract public long getIdById(int id);
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
val section = parsedQuery.query.bindSections[0]
val section2 = parsedQuery.query.bindSections[1]
val param = parsedQuery.parameters.firstOrNull()
assertThat(section, notNullValue())
assertThat(section2, notNullValue())
assertThat(param, notNullValue())
- assertThat(parsedQuery.sectionToParamMapping,
- `is`(listOf(Pair(section, param), Pair(section2, null))))
+ assertThat(
+ parsedQuery.sectionToParamMapping,
+ `is`(listOf(Pair(section, param), Pair(section2, null)))
+ )
}
- .failsToCompile()
- .withErrorContaining(
- ProcessorErrors.missingParameterForBindVariable(listOf(":uid")))
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors.missingParameterForBindVariable(listOf(":uid"))
+ )
}
@Test
fun test2MissingParameterForBinding() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT uid from User where name = :bar AND uid = :id OR uid = :uid")
abstract public long getIdById(int id);
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
val bar = parsedQuery.query.bindSections[0]
val id = parsedQuery.query.bindSections[1]
val uid = parsedQuery.query.bindSections[2]
@@ -233,81 +254,95 @@
assertThat(id, notNullValue())
assertThat(uid, notNullValue())
assertThat(param, notNullValue())
- assertThat(parsedQuery.sectionToParamMapping,
- `is`(listOf(Pair(bar, null), Pair(id, param), Pair(uid, null))))
+ assertThat(
+ parsedQuery.sectionToParamMapping,
+ `is`(listOf(Pair(bar, null), Pair(id, param), Pair(uid, null)))
+ )
}
- .failsToCompile()
- .withErrorContaining(
- ProcessorErrors.missingParameterForBindVariable(listOf(":bar", ":uid")))
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors.missingParameterForBindVariable(listOf(":bar", ":uid"))
+ )
}
@Test
fun testUnusedParameters() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT uid from User where name = :bar")
abstract public long getIdById(int bar, int whyNotUseMe);
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
val bar = parsedQuery.query.bindSections[0]
val barParam = parsedQuery.parameters.firstOrNull()
assertThat(bar, notNullValue())
assertThat(barParam, notNullValue())
- assertThat(parsedQuery.sectionToParamMapping,
- `is`(listOf(Pair(bar, barParam))))
+ assertThat(
+ parsedQuery.sectionToParamMapping,
+ `is`(listOf(Pair(bar, barParam)))
+ )
}.failsToCompile().withErrorContaining(
- ProcessorErrors.unusedQueryMethodParameter(listOf("whyNotUseMe")))
+ ProcessorErrors.unusedQueryMethodParameter(listOf("whyNotUseMe"))
+ )
}
@Test
fun testNameWithUnderscore() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("select * from User where uid = :_blah")
abstract public long getSth(int _blah);
"""
) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.QUERY_PARAMETERS_CANNOT_START_WITH_UNDERSCORE)
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.QUERY_PARAMETERS_CANNOT_START_WITH_UNDERSCORE)
}
@Test
fun testGenericReturnType() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("select * from User")
abstract public <T> ${CommonTypeNames.LIST}<T> foo(int x);
- """) { parsedQuery, _ ->
- val expected: TypeName = ParameterizedTypeName.get(ClassName.get(List::class.java),
- TypeVariableName.get("T"))
+ """
+ ) { parsedQuery, _ ->
+ val expected: TypeName = ParameterizedTypeName.get(
+ ClassName.get(List::class.java),
+ TypeVariableName.get("T")
+ )
assertThat(parsedQuery.returnType.typeName, `is`(expected))
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_QUERY_METHODS)
+ .withErrorContaining(ProcessorErrors.CANNOT_USE_UNBOUND_GENERICS_IN_QUERY_METHODS)
}
@Test
fun testBadQuery() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("select * from :1 :2")
abstract public long foo(int x);
- """) { _, _ ->
+ """
+ ) { _, _ ->
// do nothing
}.failsToCompile()
- .withErrorContaining("UNEXPECTED_CHAR=:")
+ .withErrorContaining("UNEXPECTED_CHAR=:")
}
@Test
fun testLiveDataWithWithClause() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("WITH RECURSIVE tempTable(n, fact) AS (SELECT 0, 1 UNION ALL SELECT n+1,"
+ " (n+1)*fact FROM tempTable WHERE n < 9) SELECT fact FROM tempTable, User")
abstract public ${LifecyclesTypeNames.LIVE_DATA}<${CommonTypeNames.LIST}<Integer>>
getFactorialLiveData();
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
assertThat(parsedQuery.query.tables, hasItem(Table("User", "User")))
- assertThat(parsedQuery.query.tables,
- not(hasItem(Table("tempTable", "tempTable"))))
+ assertThat(
+ parsedQuery.query.tables,
+ not(hasItem(Table("tempTable", "tempTable")))
+ )
assertThat(parsedQuery.query.tables.size, `is`(1))
}.compilesWithoutError()
}
@@ -315,33 +350,35 @@
@Test
fun testLiveDataWithNothingToObserve() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("SELECT 1")
abstract public ${LifecyclesTypeNames.LIVE_DATA}<Integer> getOne();
- """) { _, _ ->
+ """
+ ) { _, _ ->
// do nothing
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
+ .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
}
@Test
fun testLiveDataWithWithClauseAndNothingToObserve() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("WITH RECURSIVE tempTable(n, fact) AS (SELECT 0, 1 UNION ALL SELECT n+1,"
+ " (n+1)*fact FROM tempTable WHERE n < 9) SELECT fact FROM tempTable")
abstract public ${LifecyclesTypeNames.LIVE_DATA}<${CommonTypeNames.LIST}<Integer>>
getFactorialLiveData();
- """) { _, _ ->
+ """
+ ) { _, _ ->
// do nothing
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
+ .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
}
@Test
fun testBoundGeneric() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
static abstract class BaseModel<T> {
@Query("select COUNT(*) from User")
abstract public T getT();
@@ -349,16 +386,19 @@
@Dao
static abstract class ExtendingModel extends BaseModel<Integer> {
}
- """) { parsedQuery, _ ->
- assertThat(parsedQuery.returnType.typeName,
- `is`(ClassName.get(Integer::class.java) as TypeName))
+ """
+ ) { parsedQuery, _ ->
+ assertThat(
+ parsedQuery.returnType.typeName,
+ `is`(ClassName.get(Integer::class.java) as TypeName)
+ )
}.compilesWithoutError()
}
@Test
fun testBoundGenericParameter() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
static abstract class BaseModel<T> {
@Query("select COUNT(*) from User where :t")
abstract public int getT(T t);
@@ -366,20 +406,26 @@
@Dao
static abstract class ExtendingModel extends BaseModel<Integer> {
}
- """) { parsedQuery, invocation ->
- assertThat(parsedQuery.parameters.first().type,
- `is`(invocation.processingEnv
- .requireType("java.lang.Integer")))
+ """
+ ) { parsedQuery, invocation ->
+ assertThat(
+ parsedQuery.parameters.first().type,
+ `is`(
+ invocation.processingEnv
+ .requireType("java.lang.Integer")
+ )
+ )
}.compilesWithoutError()
}
@Test
fun testReadDeleteWithBadReturnType() {
singleQueryMethod<WriteQueryMethod>(
- """
+ """
@Query("DELETE from User where uid = :id")
abstract public float foo(int id);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
ProcessorErrors.cannotFindPreparedQueryResultAdapter("float", QueryType.DELETE)
)
@@ -388,10 +434,11 @@
@Test
fun testSimpleDelete() {
singleQueryMethod<WriteQueryMethod>(
- """
+ """
@Query("DELETE from User where uid = :id")
abstract public int foo(int id);
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
assertThat(parsedQuery.name, `is`("foo"))
assertThat(parsedQuery.parameters.size, `is`(1))
assertThat(parsedQuery.returnType.typeName, `is`(TypeName.INT))
@@ -401,10 +448,11 @@
@Test
fun testVoidDeleteQuery() {
singleQueryMethod<WriteQueryMethod>(
- """
+ """
@Query("DELETE from User where uid = :id")
abstract public void foo(int id);
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
assertThat(parsedQuery.name, `is`("foo"))
assertThat(parsedQuery.parameters.size, `is`(1))
assertThat(parsedQuery.returnType.typeName, `is`(TypeName.VOID))
@@ -414,55 +462,65 @@
@Test
fun testVoidUpdateQuery() {
singleQueryMethod<WriteQueryMethod>(
- """
+ """
@Query("update user set name = :name")
abstract public void updateAllNames(String name);
- """) { parsedQuery, invocation ->
+ """
+ ) { parsedQuery, invocation ->
assertThat(parsedQuery.name, `is`("updateAllNames"))
assertThat(parsedQuery.parameters.size, `is`(1))
assertThat(parsedQuery.returnType.typeName, `is`(TypeName.VOID))
- assertThat(parsedQuery.parameters.first().type.typeName,
- `is`(invocation.context.COMMON_TYPES.STRING.typeName))
+ assertThat(
+ parsedQuery.parameters.first().type.typeName,
+ `is`(invocation.context.COMMON_TYPES.STRING.typeName)
+ )
}.compilesWithoutError()
}
@Test
fun testVoidInsertQuery() {
singleQueryMethod<WriteQueryMethod>(
- """
+ """
@Query("insert into user (name) values (:name)")
abstract public void insertUsername(String name);
- """) { parsedQuery, invocation ->
+ """
+ ) { parsedQuery, invocation ->
assertThat(parsedQuery.name, `is`("insertUsername"))
assertThat(parsedQuery.parameters.size, `is`(1))
assertThat(parsedQuery.returnType.typeName, `is`(TypeName.VOID))
- assertThat(parsedQuery.parameters.first().type.typeName,
- `is`(invocation.context.COMMON_TYPES.STRING.typeName))
+ assertThat(
+ parsedQuery.parameters.first().type.typeName,
+ `is`(invocation.context.COMMON_TYPES.STRING.typeName)
+ )
}.compilesWithoutError()
}
@Test
fun testLongInsertQuery() {
singleQueryMethod<WriteQueryMethod>(
- """
+ """
@Query("insert into user (name) values (:name)")
abstract public long insertUsername(String name);
- """) { parsedQuery, invocation ->
+ """
+ ) { parsedQuery, invocation ->
assertThat(parsedQuery.name, `is`("insertUsername"))
assertThat(parsedQuery.parameters.size, `is`(1))
assertThat(parsedQuery.returnType.typeName, `is`(TypeName.LONG))
- assertThat(parsedQuery.parameters.first().type.typeName,
- `is`(invocation.context.COMMON_TYPES.STRING.typeName))
+ assertThat(
+ parsedQuery.parameters.first().type.typeName,
+ `is`(invocation.context.COMMON_TYPES.STRING.typeName)
+ )
}.compilesWithoutError()
}
@Test
fun testInsertQueryWithBadReturnType() {
singleQueryMethod<WriteQueryMethod>(
- """
+ """
@Query("insert into user (name) values (:name)")
abstract public int insert(String name);
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
assertThat(parsedQuery.returnType.typeName, `is`(TypeName.INT))
}.failsToCompile().withErrorContaining(
ProcessorErrors.cannotFindPreparedQueryResultAdapter("int", QueryType.INSERT)
@@ -472,30 +530,41 @@
@Test
fun testLiveDataQuery() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("select name from user where uid = :id")
abstract ${LifecyclesTypeNames.LIVE_DATA}<String> nameLiveData(String id);
"""
) { parsedQuery, _ ->
- assertThat(parsedQuery.returnType.typeName,
- `is`(ParameterizedTypeName.get(LifecyclesTypeNames.LIVE_DATA,
- String::class.typeName) as TypeName))
- assertThat(parsedQuery.queryResultBinder,
- instanceOf(LiveDataQueryResultBinder::class.java))
+ assertThat(
+ parsedQuery.returnType.typeName,
+ `is`(
+ ParameterizedTypeName.get(
+ LifecyclesTypeNames.LIVE_DATA,
+ String::class.typeName
+ ) as TypeName
+ )
+ )
+ assertThat(
+ parsedQuery.queryResultBinder,
+ instanceOf(LiveDataQueryResultBinder::class.java)
+ )
}.compilesWithoutError()
}
@Test
fun testBadReturnForDeleteQuery() {
singleQueryMethod<WriteQueryMethod>(
- """
+ """
@Query("delete from user where uid = :id")
abstract ${LifecyclesTypeNames.LIVE_DATA}<Integer> deleteLiveData(String id);
"""
) { _, _ ->
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.cannotFindPreparedQueryResultAdapter(
- "androidx.lifecycle.LiveData<java.lang.Integer>", QueryType.DELETE))
+ .withErrorContaining(
+ ProcessorErrors.cannotFindPreparedQueryResultAdapter(
+ "androidx.lifecycle.LiveData<java.lang.Integer>", QueryType.DELETE
+ )
+ )
}
@Test
@@ -507,27 +576,38 @@
"""
) { _, _ ->
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.cannotFindPreparedQueryResultAdapter(
- "androidx.lifecycle.LiveData<java.lang.Integer>", QueryType.UPDATE))
+ .withErrorContaining(
+ ProcessorErrors.cannotFindPreparedQueryResultAdapter(
+ "androidx.lifecycle.LiveData<java.lang.Integer>", QueryType.UPDATE
+ )
+ )
}
@Test
fun testDataSourceFactoryQuery() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("select name from user")
abstract ${PagingTypeNames.DATA_SOURCE_FACTORY}<Integer, String>
nameDataSourceFactory();
"""
) { parsedQuery, _ ->
- assertThat(parsedQuery.returnType.typeName,
- `is`(ParameterizedTypeName.get(PagingTypeNames.DATA_SOURCE_FACTORY,
- Integer::class.typeName, String::class.typeName) as TypeName))
- assertThat(parsedQuery.queryResultBinder,
- instanceOf(DataSourceFactoryQueryResultBinder::class.java))
+ assertThat(
+ parsedQuery.returnType.typeName,
+ `is`(
+ ParameterizedTypeName.get(
+ PagingTypeNames.DATA_SOURCE_FACTORY,
+ Integer::class.typeName, String::class.typeName
+ ) as TypeName
+ )
+ )
+ assertThat(
+ parsedQuery.queryResultBinder,
+ instanceOf(DataSourceFactoryQueryResultBinder::class.java)
+ )
val tableNames =
- (parsedQuery.queryResultBinder as DataSourceFactoryQueryResultBinder)
- .positionalDataSourceQueryResultBinder.tableNames
+ (parsedQuery.queryResultBinder as DataSourceFactoryQueryResultBinder)
+ .positionalDataSourceQueryResultBinder.tableNames
assertEquals(setOf("user"), tableNames)
}.compilesWithoutError()
}
@@ -535,20 +615,28 @@
@Test
fun testMultiTableDataSourceFactoryQuery() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("select name from User u LEFT OUTER JOIN Book b ON u.uid == b.uid")
abstract ${PagingTypeNames.DATA_SOURCE_FACTORY}<Integer, String>
nameDataSourceFactory();
"""
) { parsedQuery, _ ->
- assertThat(parsedQuery.returnType.typeName,
- `is`(ParameterizedTypeName.get(PagingTypeNames.DATA_SOURCE_FACTORY,
- Integer::class.typeName, String::class.typeName) as TypeName))
- assertThat(parsedQuery.queryResultBinder,
- instanceOf(DataSourceFactoryQueryResultBinder::class.java))
+ assertThat(
+ parsedQuery.returnType.typeName,
+ `is`(
+ ParameterizedTypeName.get(
+ PagingTypeNames.DATA_SOURCE_FACTORY,
+ Integer::class.typeName, String::class.typeName
+ ) as TypeName
+ )
+ )
+ assertThat(
+ parsedQuery.queryResultBinder,
+ instanceOf(DataSourceFactoryQueryResultBinder::class.java)
+ )
val tableNames =
- (parsedQuery.queryResultBinder as DataSourceFactoryQueryResultBinder)
- .positionalDataSourceQueryResultBinder.tableNames
+ (parsedQuery.queryResultBinder as DataSourceFactoryQueryResultBinder)
+ .positionalDataSourceQueryResultBinder.tableNames
assertEquals(setOf("User", "Book"), tableNames)
}.compilesWithoutError()
}
@@ -563,8 +651,11 @@
jfos = listOf(COMMON.CHANNEL)
) { _, _ ->
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.invalidChannelType(
- KotlinTypeNames.CHANNEL.toString()))
+ .withErrorContaining(
+ ProcessorErrors.invalidChannelType(
+ KotlinTypeNames.CHANNEL.toString()
+ )
+ )
}
@Test
@@ -577,8 +668,11 @@
jfos = listOf(COMMON.SEND_CHANNEL)
) { _, _ ->
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.invalidChannelType(
- KotlinTypeNames.SEND_CHANNEL.toString()))
+ .withErrorContaining(
+ ProcessorErrors.invalidChannelType(
+ KotlinTypeNames.SEND_CHANNEL.toString()
+ )
+ )
}
@Test
@@ -591,14 +685,17 @@
jfos = listOf(COMMON.RECEIVE_CHANNEL)
) { _, _ ->
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.invalidChannelType(
- KotlinTypeNames.RECEIVE_CHANNEL.toString()))
+ .withErrorContaining(
+ ProcessorErrors.invalidChannelType(
+ KotlinTypeNames.RECEIVE_CHANNEL.toString()
+ )
+ )
}
@Test
fun query_detectTransaction_select() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Query("select * from user")
abstract int loadUsers();
"""
@@ -610,7 +707,7 @@
@Test
fun query_detectTransaction_selectInTransaction() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@Transaction
@Query("select * from user")
abstract int loadUsers();
@@ -623,25 +720,30 @@
@Test
fun skipVerification() {
singleQueryMethod<ReadQueryMethod>(
- """
+ """
@SkipQueryVerification
@Query("SELECT foo from User")
abstract public int[] foo();
- """) { parsedQuery, _ ->
+ """
+ ) { parsedQuery, _ ->
assertThat(parsedQuery.name, `is`("foo"))
assertThat(parsedQuery.parameters.size, `is`(0))
- assertThat(parsedQuery.returnType.typeName,
- `is`(ArrayTypeName.of(TypeName.INT) as TypeName))
+ assertThat(
+ parsedQuery.returnType.typeName,
+ `is`(ArrayTypeName.of(TypeName.INT) as TypeName)
+ )
}.compilesWithoutError()
}
@Test
fun suppressWarnings() {
- singleQueryMethod<ReadQueryMethod>("""
+ singleQueryMethod<ReadQueryMethod>(
+ """
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
@Query("SELECT uid from User")
abstract public int[] foo();
- """) { method, invocation ->
+ """
+ ) { method, invocation ->
assertThat(
QueryMethodProcessor(
baseContext = invocation.context,
@@ -669,27 +771,38 @@
@Transaction
@Query("select * from user")
abstract java.util.List<Merged> loadUsers();
- """) { method, _ ->
- assertThat(method.queryResultBinder.adapter,
- instanceOf(ListQueryResultAdapter::class.java))
+ """
+ ) { method, _ ->
+ assertThat(
+ method.queryResultBinder.adapter,
+ instanceOf(ListQueryResultAdapter::class.java)
+ )
val listAdapter = method.queryResultBinder.adapter as ListQueryResultAdapter
assertThat(listAdapter.rowAdapter, instanceOf(PojoRowAdapter::class.java))
val pojoRowAdapter = listAdapter.rowAdapter as PojoRowAdapter
assertThat(pojoRowAdapter.relationCollectors.size, `is`(1))
- assertThat(pojoRowAdapter.relationCollectors[0].relationTypeName, `is`(
- ParameterizedTypeName.get(ClassName.get(ArrayList::class.java),
- COMMON.USER_TYPE_NAME) as TypeName
- ))
+ assertThat(
+ pojoRowAdapter.relationCollectors[0].relationTypeName,
+ `is`(
+ ParameterizedTypeName.get(
+ ClassName.get(ArrayList::class.java),
+ COMMON.USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
}.compilesWithoutError()
.withWarningCount(0)
}
@Test
fun pojo_renamedColumn() {
- pojoTest("""
+ pojoTest(
+ """
String name;
String lName;
- """, listOf("name", "lastName as lName")) { adapter, _, _ ->
+ """,
+ listOf("name", "lastName as lName")
+ ) { adapter, _, _ ->
assertThat(adapter?.mapping?.unusedColumns, `is`(emptyList()))
assertThat(adapter?.mapping?.unusedFields, `is`(emptyList()))
}?.compilesWithoutError()?.withWarningCount(0)
@@ -697,10 +810,13 @@
@Test
fun pojo_exactMatch() {
- pojoTest("""
+ pojoTest(
+ """
String name;
String lastName;
- """, listOf("name", "lastName")) { adapter, _, _ ->
+ """,
+ listOf("name", "lastName")
+ ) { adapter, _, _ ->
assertThat(adapter?.mapping?.unusedColumns, `is`(emptyList()))
assertThat(adapter?.mapping?.unusedFields, `is`(emptyList()))
}?.compilesWithoutError()?.withWarningCount(0)
@@ -708,13 +824,16 @@
@Test
fun pojo_exactMatchWithStar() {
- pojoTest("""
+ pojoTest(
+ """
String name;
String lastName;
int uid;
@ColumnInfo(name = "ageColumn")
int age;
- """, listOf("*")) { adapter, _, _ ->
+ """,
+ listOf("*")
+ ) { adapter, _, _ ->
assertThat(adapter?.mapping?.unusedColumns, `is`(emptyList()))
assertThat(adapter?.mapping?.unusedFields, `is`(emptyList()))
}?.compilesWithoutError()?.withWarningCount(0)
@@ -767,11 +886,14 @@
@Test
fun pojo_nonJavaName() {
- pojoTest("""
+ pojoTest(
+ """
@ColumnInfo(name = "MAX(ageColumn)")
int maxAge;
String name;
- """, listOf("MAX(ageColumn)", "name")) { adapter, _, _ ->
+ """,
+ listOf("MAX(ageColumn)", "name")
+ ) { adapter, _, _ ->
assertThat(adapter?.mapping?.unusedColumns, `is`(emptyList()))
assertThat(adapter?.mapping?.unusedFields, `is`(emptyList()))
}?.compilesWithoutError()?.withWarningCount(0)
@@ -779,131 +901,168 @@
@Test
fun pojo_noMatchingFields() {
- pojoTest("""
+ pojoTest(
+ """
String nameX;
String lastNameX;
- """, listOf("name", "lastName")) { adapter, _, _ ->
+ """,
+ listOf("name", "lastName")
+ ) { adapter, _, _ ->
assertThat(adapter?.mapping?.unusedColumns, `is`(listOf("name", "lastName")))
assertThat(adapter?.mapping?.unusedFields, `is`(adapter?.pojo?.fields as List<Field>))
}?.failsToCompile()
- ?.withErrorContaining(cannotFindQueryResultAdapter("foo.bar.MyClass.Pojo"))
- ?.and()
- ?.withWarningContaining(
- ProcessorErrors.cursorPojoMismatch(
- pojoTypeName = POJO,
- unusedColumns = listOf("name", "lastName"),
- unusedFields = listOf(createField("nameX"),
- createField("lastNameX")),
- allColumns = listOf("name", "lastName"),
- allFields = listOf(
- createField("nameX"),
- createField("lastNameX")
- )
- )
+ ?.withErrorContaining(cannotFindQueryResultAdapter("foo.bar.MyClass.Pojo"))
+ ?.and()
+ ?.withWarningContaining(
+ ProcessorErrors.cursorPojoMismatch(
+ pojoTypeName = POJO,
+ unusedColumns = listOf("name", "lastName"),
+ unusedFields = listOf(
+ createField("nameX"),
+ createField("lastNameX")
+ ),
+ allColumns = listOf("name", "lastName"),
+ allFields = listOf(
+ createField("nameX"),
+ createField("lastNameX")
+ )
)
+ )
}
@Test
fun pojo_badQuery() {
// do not report mismatch if query is broken
- pojoTest("""
+ pojoTest(
+ """
@ColumnInfo(name = "MAX(ageColumn)")
int maxAge;
String name;
- """, listOf("MAX(age)", "name")) { _, _, _ ->
+ """,
+ listOf("MAX(age)", "name")
+ ) { _, _, _ ->
}?.failsToCompile()
- ?.withErrorContaining("no such column: age")
- ?.and()?.withErrorContaining(cannotFindQueryResultAdapter("foo.bar.MyClass.Pojo"))
- ?.and()?.withErrorCount(2)
- ?.withWarningCount(0)
+ ?.withErrorContaining("no such column: age")
+ ?.and()?.withErrorContaining(cannotFindQueryResultAdapter("foo.bar.MyClass.Pojo"))
+ ?.and()?.withErrorCount(2)
+ ?.withWarningCount(0)
}
@Test
fun pojo_tooManyColumns() {
- pojoTest("""
+ pojoTest(
+ """
String name;
String lastName;
- """, listOf("uid", "name", "lastName")) { adapter, _, _ ->
+ """,
+ listOf("uid", "name", "lastName")
+ ) { adapter, _, _ ->
assertThat(adapter?.mapping?.unusedColumns, `is`(listOf("uid")))
assertThat(adapter?.mapping?.unusedFields, `is`(emptyList()))
}?.compilesWithoutError()?.withWarningContaining(
- ProcessorErrors.cursorPojoMismatch(
- pojoTypeName = POJO,
- unusedColumns = listOf("uid"),
- unusedFields = emptyList(),
- allColumns = listOf("uid", "name", "lastName"),
- allFields = listOf(createField("name"), createField("lastName"))
- ))
+ ProcessorErrors.cursorPojoMismatch(
+ pojoTypeName = POJO,
+ unusedColumns = listOf("uid"),
+ unusedFields = emptyList(),
+ allColumns = listOf("uid", "name", "lastName"),
+ allFields = listOf(createField("name"), createField("lastName"))
+ )
+ )
}
@Test
fun pojo_tooManyFields() {
- pojoTest("""
+ pojoTest(
+ """
String name;
String lastName;
- """, listOf("lastName")) { adapter, _, _ ->
+ """,
+ listOf("lastName")
+ ) { adapter, _, _ ->
assertThat(adapter?.mapping?.unusedColumns, `is`(emptyList()))
- assertThat(adapter?.mapping?.unusedFields, `is`(
+ assertThat(
+ adapter?.mapping?.unusedFields,
+ `is`(
adapter?.pojo?.fields?.filter { it.name == "name" }
- ))
+ )
+ )
}?.compilesWithoutError()?.withWarningContaining(
- ProcessorErrors.cursorPojoMismatch(
- pojoTypeName = POJO,
- unusedColumns = emptyList(),
- unusedFields = listOf(createField("name")),
- allColumns = listOf("lastName"),
- allFields = listOf(createField("name"), createField("lastName"))
- ))
+ ProcessorErrors.cursorPojoMismatch(
+ pojoTypeName = POJO,
+ unusedColumns = emptyList(),
+ unusedFields = listOf(createField("name")),
+ allColumns = listOf("lastName"),
+ allFields = listOf(createField("name"), createField("lastName"))
+ )
+ )
}
@Test
fun pojo_missingNonNull() {
- pojoTest("""
+ pojoTest(
+ """
@NonNull
String name;
String lastName;
- """, listOf("lastName")) { adapter, _, _ ->
+ """,
+ listOf("lastName")
+ ) { adapter, _, _ ->
assertThat(adapter?.mapping?.unusedColumns, `is`(emptyList()))
- assertThat(adapter?.mapping?.unusedFields, `is`(
+ assertThat(
+ adapter?.mapping?.unusedFields,
+ `is`(
adapter?.pojo?.fields?.filter { it.name == "name" }
- ))
+ )
+ )
}?.failsToCompile()?.withWarningContaining(
- ProcessorErrors.cursorPojoMismatch(
- pojoTypeName = POJO,
- unusedColumns = emptyList(),
- unusedFields = listOf(createField("name")),
- allColumns = listOf("lastName"),
- allFields = listOf(createField("name"), createField("lastName"))
- ))?.and()?.withErrorContaining(
- ProcessorErrors.pojoMissingNonNull(pojoTypeName = POJO,
- missingPojoFields = listOf("name"),
- allQueryColumns = listOf("lastName")))
+ ProcessorErrors.cursorPojoMismatch(
+ pojoTypeName = POJO,
+ unusedColumns = emptyList(),
+ unusedFields = listOf(createField("name")),
+ allColumns = listOf("lastName"),
+ allFields = listOf(createField("name"), createField("lastName"))
+ )
+ )?.and()?.withErrorContaining(
+ ProcessorErrors.pojoMissingNonNull(
+ pojoTypeName = POJO,
+ missingPojoFields = listOf("name"),
+ allQueryColumns = listOf("lastName")
+ )
+ )
}
@Test
fun pojo_tooManyFieldsAndColumns() {
- pojoTest("""
+ pojoTest(
+ """
String name;
String lastName;
- """, listOf("uid", "name")) { adapter, _, _ ->
+ """,
+ listOf("uid", "name")
+ ) { adapter, _, _ ->
assertThat(adapter?.mapping?.unusedColumns, `is`(listOf("uid")))
- assertThat(adapter?.mapping?.unusedFields, `is`(
+ assertThat(
+ adapter?.mapping?.unusedFields,
+ `is`(
adapter?.pojo?.fields?.filter { it.name == "lastName" }
- ))
+ )
+ )
}?.compilesWithoutError()?.withWarningContaining(
- ProcessorErrors.cursorPojoMismatch(
- pojoTypeName = POJO,
- unusedColumns = listOf("uid"),
- unusedFields = listOf(createField("lastName")),
- allColumns = listOf("uid", "name"),
- allFields = listOf(createField("name"), createField("lastName"))
- ))
+ ProcessorErrors.cursorPojoMismatch(
+ pojoTypeName = POJO,
+ unusedColumns = listOf("uid"),
+ unusedFields = listOf(createField("lastName")),
+ allColumns = listOf("uid", "name"),
+ allFields = listOf(createField("name"), createField("lastName"))
+ )
+ )
}
@Test
fun pojo_expandProjection() {
if (!enableVerification) return
- pojoTest("""
+ pojoTest(
+ """
String uid;
String name;
""",
@@ -964,43 +1123,47 @@
JavaFileObjects.forSourceString(
"foo.bar.MyClass",
DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
- ), COMMON.LIVE_DATA, COMMON.COMPUTABLE_LIVE_DATA, COMMON.USER, COMMON.BOOK
+ ),
+ COMMON.LIVE_DATA, COMMON.COMPUTABLE_LIVE_DATA, COMMON.USER, COMMON.BOOK
) + jfos
)
.withCompilerOptions(options)
.withCompilerOptions("-Xlint:-processing") // remove unclaimed annotation warnings
- .processedWith(TestProcessor.builder()
- .forAnnotations(
- Query::class
- )
- .nextRunHandler { invocation ->
- val (owner, methods) = invocation.roundEnv
- .getElementsAnnotatedWith(Dao::class.java)
- .map {
- Pair(it,
- it.asTypeElement().getAllMethods().filter {
- it.hasAnnotation(Query::class)
- }
- )
- }.first { it.second.isNotEmpty() }
- val verifier = if (enableVerification) {
- createVerifierFromEntitiesAndViews(invocation).also(
- invocation.context::attachDatabaseVerifier
- )
- } else {
- null
- }
- val parser = QueryMethodProcessor(
- baseContext = invocation.context,
- containing = owner.asDeclaredType(),
- executableElement = methods.first(),
- dbVerifier = verifier
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(
+ Query::class
)
- val parsedQuery = parser.process()
- @Suppress("UNCHECKED_CAST")
- handler(parsedQuery as T, invocation)
- true
- }
- .build())
+ .nextRunHandler { invocation ->
+ val (owner, methods) = invocation.roundEnv
+ .getElementsAnnotatedWith(Dao::class.java)
+ .map {
+ Pair(
+ it,
+ it.asTypeElement().getAllMethods().filter {
+ it.hasAnnotation(Query::class)
+ }
+ )
+ }.first { it.second.isNotEmpty() }
+ val verifier = if (enableVerification) {
+ createVerifierFromEntitiesAndViews(invocation).also(
+ invocation.context::attachDatabaseVerifier
+ )
+ } else {
+ null
+ }
+ val parser = QueryMethodProcessor(
+ baseContext = invocation.context,
+ containing = owner.asDeclaredType(),
+ executableElement = methods.first(),
+ dbVerifier = verifier
+ )
+ val parsedQuery = parser.process()
+ @Suppress("UNCHECKED_CAST")
+ handler(parsedQuery as T, invocation)
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt
index 1f247e9..f992e09 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/RawQueryMethodProcessorTest.kt
@@ -46,46 +46,57 @@
@Test
fun supportRawQuery() {
singleQueryMethod(
- """
+ """
@RawQuery
abstract public int[] foo(SupportSQLiteQuery query);
- """) { query, _ ->
+ """
+ ) { query, _ ->
assertThat(query.name, `is`("foo"))
- assertThat(query.runtimeQueryParam, `is`(
+ assertThat(
+ query.runtimeQueryParam,
+ `is`(
RawQueryMethod.RuntimeQueryParameter(
- paramName = "query",
- type = SupportDbTypeNames.QUERY
+ paramName = "query",
+ type = SupportDbTypeNames.QUERY
)
- ))
- assertThat(query.returnType.typeName,
- `is`(ArrayTypeName.of(TypeName.INT) as TypeName))
+ )
+ )
+ assertThat(
+ query.returnType.typeName,
+ `is`(ArrayTypeName.of(TypeName.INT) as TypeName)
+ )
}.compilesWithoutError()
}
@Test
fun stringRawQuery() {
singleQueryMethod(
- """
+ """
@RawQuery
abstract public int[] foo(String query);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(RAW_QUERY_STRING_PARAMETER_REMOVED)
}
@Test
fun withObservedEntities() {
singleQueryMethod(
- """
+ """
@RawQuery(observedEntities = User.class)
abstract public LiveData<User> foo(SupportSQLiteQuery query);
- """) { query, _ ->
+ """
+ ) { query, _ ->
assertThat(query.name, `is`("foo"))
- assertThat(query.runtimeQueryParam, `is`(
+ assertThat(
+ query.runtimeQueryParam,
+ `is`(
RawQueryMethod.RuntimeQueryParameter(
- paramName = "query",
- type = SupportDbTypeNames.QUERY
+ paramName = "query",
+ type = SupportDbTypeNames.QUERY
)
- ))
+ )
+ )
assertThat(query.observedTableNames.size, `is`(1))
assertThat(query.observedTableNames, `is`(setOf("User")))
}.compilesWithoutError()
@@ -94,54 +105,61 @@
@Test
fun observableWithoutEntities() {
singleQueryMethod(
- """
+ """
@RawQuery(observedEntities = {})
abstract public LiveData<User> foo(SupportSQLiteQuery query);
- """) { query, _ ->
+ """
+ ) { query, _ ->
assertThat(query.name, `is`("foo"))
- assertThat(query.runtimeQueryParam, `is`(
+ assertThat(
+ query.runtimeQueryParam,
+ `is`(
RawQueryMethod.RuntimeQueryParameter(
- paramName = "query",
- type = SupportDbTypeNames.QUERY
+ paramName = "query",
+ type = SupportDbTypeNames.QUERY
)
- ))
+ )
+ )
assertThat(query.observedTableNames, `is`(emptySet()))
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
+ .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
}
@Test
fun observableWithoutEntities_dataSourceFactory() {
singleQueryMethod(
- """
+ """
@RawQuery
abstract public ${PagingTypeNames.DATA_SOURCE_FACTORY}<Integer, User> getOne();
- """) { _, _ ->
+ """
+ ) { _, _ ->
// do nothing
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
+ .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
}
@Test
fun observableWithoutEntities_positionalDataSource() {
singleQueryMethod(
- """
+ """
@RawQuery
abstract public ${PagingTypeNames.POSITIONAL_DATA_SOURCE}<User> getOne();
- """) { _, _ ->
+ """
+ ) { _, _ ->
// do nothing
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
+ .withErrorContaining(ProcessorErrors.OBSERVABLE_QUERY_NOTHING_TO_OBSERVE)
}
@Test
fun positionalDataSource() {
singleQueryMethod(
- """
+ """
@RawQuery(observedEntities = {User.class})
abstract public ${PagingTypeNames.POSITIONAL_DATA_SOURCE}<User> getOne(
SupportSQLiteQuery query);
- """) { _, _ ->
+ """
+ ) { _, _ ->
// do nothing
}.compilesWithoutError()
}
@@ -150,7 +168,7 @@
fun pojo() {
val pojo: TypeName = ClassName.get("foo.bar.MyClass", "MyPojo")
singleQueryMethod(
- """
+ """
public class MyPojo {
public String foo;
public String bar;
@@ -158,14 +176,18 @@
@RawQuery
abstract public MyPojo foo(SupportSQLiteQuery query);
- """) { query, _ ->
+ """
+ ) { query, _ ->
assertThat(query.name, `is`("foo"))
- assertThat(query.runtimeQueryParam, `is`(
+ assertThat(
+ query.runtimeQueryParam,
+ `is`(
RawQueryMethod.RuntimeQueryParameter(
- paramName = "query",
- type = SupportDbTypeNames.QUERY
+ paramName = "query",
+ type = SupportDbTypeNames.QUERY
)
- ))
+ )
+ )
assertThat(query.returnType.typeName, `is`(pojo))
assertThat(query.observedTableNames, `is`(emptySet()))
}.compilesWithoutError()
@@ -174,12 +196,13 @@
@Test
fun void() {
singleQueryMethod(
- """
+ """
@RawQuery
abstract public void foo(SupportSQLiteQuery query);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RAW_QUERY_BAD_RETURN_TYPE
+ ProcessorErrors.RAW_QUERY_BAD_RETURN_TYPE
)
}
@@ -207,56 +230,60 @@
@Test
fun noArgs() {
singleQueryMethod(
- """
+ """
@RawQuery
abstract public int[] foo();
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RAW_QUERY_BAD_PARAMS
+ ProcessorErrors.RAW_QUERY_BAD_PARAMS
)
}
@Test
fun tooManyArgs() {
singleQueryMethod(
- """
+ """
@RawQuery
abstract public int[] foo(SupportSQLiteQuery query,
SupportSQLiteQuery query2);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RAW_QUERY_BAD_PARAMS
+ ProcessorErrors.RAW_QUERY_BAD_PARAMS
)
}
@Test
fun varargs() {
singleQueryMethod(
- """
+ """
@RawQuery
abstract public int[] foo(SupportSQLiteQuery... query);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RAW_QUERY_BAD_PARAMS
+ ProcessorErrors.RAW_QUERY_BAD_PARAMS
)
}
@Test
fun observed_notAnEntity() {
singleQueryMethod(
- """
+ """
@RawQuery(observedEntities = {${COMMON.NOT_AN_ENTITY_TYPE_NAME}.class})
abstract public int[] foo(SupportSQLiteQuery query);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.rawQueryBadEntity(COMMON.NOT_AN_ENTITY_TYPE_NAME)
+ ProcessorErrors.rawQueryBadEntity(COMMON.NOT_AN_ENTITY_TYPE_NAME)
)
}
@Test
fun observed_relationPojo() {
singleQueryMethod(
- """
+ """
public static class MyPojo {
public String foo;
@Relation(
@@ -267,7 +294,8 @@
}
@RawQuery(observedEntities = MyPojo.class)
abstract public int[] foo(SupportSQLiteQuery query);
- """) { method, _ ->
+ """
+ ) { method, _ ->
assertThat(method.observedTableNames, `is`(setOf("User")))
}.compilesWithoutError()
}
@@ -275,7 +303,7 @@
@Test
fun observed_embedded() {
singleQueryMethod(
- """
+ """
public static class MyPojo {
public String foo;
@Embedded
@@ -283,7 +311,8 @@
}
@RawQuery(observedEntities = MyPojo.class)
abstract public int[] foo(SupportSQLiteQuery query);
- """) { method, _ ->
+ """
+ ) { method, _ ->
assertThat(method.observedTableNames, `is`(setOf("User")))
}.compilesWithoutError()
}
@@ -293,35 +322,47 @@
handler: (RawQueryMethod, TestInvocation) -> Unit
): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(listOf(JavaFileObjects.forSourceString("foo.bar.MyClass",
+ .that(
+ listOf(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyClass",
DAO_PREFIX +
- input.joinToString("\n") +
- DAO_SUFFIX
- ), COMMON.LIVE_DATA, COMMON.COMPUTABLE_LIVE_DATA, COMMON.USER,
- COMMON.DATA_SOURCE_FACTORY, COMMON.POSITIONAL_DATA_SOURCE,
- COMMON.NOT_AN_ENTITY))
- .processedWith(TestProcessor.builder()
- .forAnnotations(Query::class, Dao::class, ColumnInfo::class,
- Entity::class, PrimaryKey::class, RawQuery::class)
- .nextRunHandler { invocation ->
- val (owner, methods) = invocation.roundEnv
- .getElementsAnnotatedWith(Dao::class.java)
- .map {
- Pair(it,
- it.asTypeElement().getAllMethods().filter {
- it.hasAnnotation(RawQuery::class)
- }
- )
- }.first { it.second.isNotEmpty() }
- val parser = RawQueryMethodProcessor(
- baseContext = invocation.context,
- containing = owner.asDeclaredType(),
- executableElement = methods.first())
- val parsedQuery = parser.process()
- handler(parsedQuery, invocation)
- true
- }
- .build())
+ input.joinToString("\n") +
+ DAO_SUFFIX
+ ),
+ COMMON.LIVE_DATA, COMMON.COMPUTABLE_LIVE_DATA, COMMON.USER,
+ COMMON.DATA_SOURCE_FACTORY, COMMON.POSITIONAL_DATA_SOURCE,
+ COMMON.NOT_AN_ENTITY
+ )
+ )
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(
+ Query::class, Dao::class, ColumnInfo::class,
+ Entity::class, PrimaryKey::class, RawQuery::class
+ )
+ .nextRunHandler { invocation ->
+ val (owner, methods) = invocation.roundEnv
+ .getElementsAnnotatedWith(Dao::class.java)
+ .map {
+ Pair(
+ it,
+ it.asTypeElement().getAllMethods().filter {
+ it.hasAnnotation(RawQuery::class)
+ }
+ )
+ }.first { it.second.isNotEmpty() }
+ val parser = RawQueryMethodProcessor(
+ baseContext = invocation.context,
+ containing = owner.asDeclaredType(),
+ executableElement = methods.first()
+ )
+ val parsedQuery = parser.process()
+ handler(parsedQuery, invocation)
+ true
+ }
+ .build()
+ )
}
companion object {
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/ShortcutMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/ShortcutMethodProcessorTest.kt
index a4321c3..7555ec17 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/ShortcutMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/ShortcutMethodProcessorTest.kt
@@ -65,10 +65,11 @@
@Test
fun noParams() {
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public void foo();
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("foo"))
assertThat(shortcut.parameters.size, `is`(0))
}.failsToCompile().withErrorContaining(noParamsError())
@@ -79,10 +80,11 @@
@Test
fun single() {
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public int foo(User user);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("foo"))
assertThat(shortcut.parameters.size, `is`(1))
val param = shortcut.parameters.first()
@@ -97,25 +99,27 @@
@Test
fun notAnEntity() {
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public void foo(NotAnEntity notValid);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("foo"))
assertThat(shortcut.parameters.size, `is`(1))
assertThat(shortcut.entities.size, `is`(0))
}.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER
+ ProcessorErrors.CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER
)
}
@Test
fun two() {
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public void foo(User u1, User u2);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("foo"))
assertThat(shortcut.parameters.size, `is`(2))
@@ -126,35 +130,43 @@
assertThat(shortcut.entities.size, `is`(2))
assertThat(shortcut.entities["u1"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(shortcut.entities["u1"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
- assertThat(shortcut.parameters.map { it.name },
- `is`(listOf("u1", "u2")))
+ assertThat(
+ shortcut.parameters.map { it.name },
+ `is`(listOf("u1", "u2"))
+ )
}.compilesWithoutError()
}
@Test
fun list() {
listOf(
- "int",
- "Integer",
- "${RxJava2TypeNames.SINGLE}<Integer>",
- "${RxJava2TypeNames.MAYBE}<Integer>",
- RxJava2TypeNames.COMPLETABLE,
- "${RxJava3TypeNames.SINGLE}<Integer>",
- "${RxJava3TypeNames.MAYBE}<Integer>",
- RxJava3TypeNames.COMPLETABLE,
- "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<Integer>"
+ "int",
+ "Integer",
+ "${RxJava2TypeNames.SINGLE}<Integer>",
+ "${RxJava2TypeNames.MAYBE}<Integer>",
+ RxJava2TypeNames.COMPLETABLE,
+ "${RxJava3TypeNames.SINGLE}<Integer>",
+ "${RxJava3TypeNames.MAYBE}<Integer>",
+ RxJava3TypeNames.COMPLETABLE,
+ "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<Integer>"
).forEach { type ->
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public $type users(List<User> users);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("users"))
assertThat(shortcut.parameters.size, `is`(1))
val param = shortcut.parameters.first()
- assertThat(param.type.typeName, `is`(
+ assertThat(
+ param.type.typeName,
+ `is`(
ParameterizedTypeName.get(
- ClassName.get("java.util", "List"), USER_TYPE_NAME) as TypeName))
+ ClassName.get("java.util", "List"), USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
assertThat(param.pojoType?.typeName, `is`(USER_TYPE_NAME))
assertThat(shortcut.entities.size, `is`(1))
assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
@@ -165,15 +177,20 @@
@Test
fun array() {
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public void users(User[] users);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("users"))
assertThat(shortcut.parameters.size, `is`(1))
val param = shortcut.parameters.first()
- assertThat(param.type.typeName, `is`(
- ArrayTypeName.of(COMMON.USER_TYPE_NAME) as TypeName))
+ assertThat(
+ param.type.typeName,
+ `is`(
+ ArrayTypeName.of(COMMON.USER_TYPE_NAME) as TypeName
+ )
+ )
assertThat(shortcut.entities.size, `is`(1))
assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
}.compilesWithoutError()
@@ -182,18 +199,23 @@
@Test
fun set() {
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public void modifyUsers(Set<User> users);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("modifyUsers"))
assertThat(shortcut.parameters.size, `is`(1))
val param = shortcut.parameters.first()
- assertThat(param.type.typeName, `is`(
+ assertThat(
+ param.type.typeName,
+ `is`(
ParameterizedTypeName.get(
- ClassName.get("java.util", "Set"),
- COMMON.USER_TYPE_NAME
- ) as TypeName))
+ ClassName.get("java.util", "Set"),
+ COMMON.USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
assertThat(shortcut.entities.size, `is`(1))
assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
}.compilesWithoutError()
@@ -202,16 +224,23 @@
@Test
fun iterable() {
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public void modifyUsers(Iterable<User> users);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("modifyUsers"))
assertThat(shortcut.parameters.size, `is`(1))
val param = shortcut.parameters.first()
- assertThat(param.type.typeName, `is`(
- ParameterizedTypeName.get(ClassName.get("java.lang", "Iterable"),
- COMMON.USER_TYPE_NAME) as TypeName))
+ assertThat(
+ param.type.typeName,
+ `is`(
+ ParameterizedTypeName.get(
+ ClassName.get("java.lang", "Iterable"),
+ COMMON.USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
assertThat(shortcut.entities.size, `is`(1))
assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
}.compilesWithoutError()
@@ -220,17 +249,24 @@
@Test
fun customCollection() {
singleShortcutMethod(
- """
+ """
static class MyList<Irrelevant, Item> extends ArrayList<Item> {}
@${annotation.java.canonicalName}
abstract public void modifyUsers(MyList<String, User> users);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("modifyUsers"))
assertThat(shortcut.parameters.size, `is`(1))
val param = shortcut.parameters.first()
- assertThat(param.type.typeName, `is`(
- ParameterizedTypeName.get(ClassName.get("foo.bar", "MyClass.MyList"),
- CommonTypeNames.STRING, COMMON.USER_TYPE_NAME) as TypeName))
+ assertThat(
+ param.type.typeName,
+ `is`(
+ ParameterizedTypeName.get(
+ ClassName.get("foo.bar", "MyClass.MyList"),
+ CommonTypeNames.STRING, COMMON.USER_TYPE_NAME
+ ) as TypeName
+ )
+ )
assertThat(shortcut.entities.size, `is`(1))
assertThat(shortcut.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
}.compilesWithoutError()
@@ -239,27 +275,32 @@
@Test
fun differentTypes() {
listOf(
- "void",
- "int",
- "Integer",
- "${RxJava2TypeNames.SINGLE}<Integer>",
- "${RxJava2TypeNames.MAYBE}<Integer>",
- RxJava2TypeNames.COMPLETABLE,
- "${RxJava3TypeNames.SINGLE}<Integer>",
- "${RxJava3TypeNames.MAYBE}<Integer>",
- RxJava3TypeNames.COMPLETABLE,
- "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<Integer>"
+ "void",
+ "int",
+ "Integer",
+ "${RxJava2TypeNames.SINGLE}<Integer>",
+ "${RxJava2TypeNames.MAYBE}<Integer>",
+ RxJava2TypeNames.COMPLETABLE,
+ "${RxJava3TypeNames.SINGLE}<Integer>",
+ "${RxJava3TypeNames.MAYBE}<Integer>",
+ RxJava3TypeNames.COMPLETABLE,
+ "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<Integer>"
).forEach { type ->
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public $type foo(User u1, Book b1);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.parameters.size, `is`(2))
- assertThat(shortcut.parameters[0].type.typeName.toString(),
- `is`("foo.bar.User"))
- assertThat(shortcut.parameters[1].type.typeName.toString(),
- `is`("foo.bar.Book"))
+ assertThat(
+ shortcut.parameters[0].type.typeName.toString(),
+ `is`("foo.bar.User")
+ )
+ assertThat(
+ shortcut.parameters[1].type.typeName.toString(),
+ `is`("foo.bar.Book")
+ )
assertThat(shortcut.parameters.map { it.name }, `is`(listOf("u1", "b1")))
assertThat(shortcut.entities.size, `is`(2))
assertThat(shortcut.entities["u1"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
@@ -271,24 +312,25 @@
@Test
fun invalidReturnType() {
listOf(
- "long",
- "String",
- "User",
- "${RxJava2TypeNames.SINGLE}<Int>",
- "${RxJava2TypeNames.MAYBE}<Int>",
- "${RxJava2TypeNames.SINGLE}<String>",
- "${RxJava2TypeNames.MAYBE}<String>",
- "${RxJava2TypeNames.SINGLE}<User>",
- "${RxJava2TypeNames.MAYBE}<User>",
- "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<Int>",
- "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<String>",
- "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<User>"
+ "long",
+ "String",
+ "User",
+ "${RxJava2TypeNames.SINGLE}<Int>",
+ "${RxJava2TypeNames.MAYBE}<Int>",
+ "${RxJava2TypeNames.SINGLE}<String>",
+ "${RxJava2TypeNames.MAYBE}<String>",
+ "${RxJava2TypeNames.SINGLE}<User>",
+ "${RxJava2TypeNames.MAYBE}<User>",
+ "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<Int>",
+ "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<String>",
+ "${GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE}<User>"
).forEach { type ->
singleShortcutMethod(
- """
+ """
@${annotation.java.canonicalName}
abstract public $type foo(User user);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(invalidReturnTypeError())
}
}
@@ -309,7 +351,8 @@
@${annotation.java.canonicalName}(entity = User.class)
abstract public int foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo)) { shortcut, _ ->
+ additionalJFOs = listOf(usernameJfo)
+ ) { shortcut, _ ->
assertThat(shortcut.name, `is`("foo"))
assertThat(shortcut.parameters.size, `is`(1))
val param = shortcut.parameters.first()
@@ -328,7 +371,8 @@
"""
@${annotation.java.canonicalName}(entity = User.class)
abstract public int foo(User user);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.compilesWithoutError()
}
@@ -349,9 +393,11 @@
@${annotation.java.canonicalName}(entity = User.class)
abstract public int foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo)) { _, _ ->
+ additionalJFOs = listOf(usernameJfo)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.cannotFindAsEntityField("foo.bar.User"))
+ ProcessorErrors.cannotFindAsEntityField("foo.bar.User")
+ )
}
@Test
@@ -372,7 +418,8 @@
@${annotation.java.canonicalName}(entity = User.class)
abstract public int foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo)) { _, _ ->
+ additionalJFOs = listOf(usernameJfo)
+ ) { _, _ ->
}.compilesWithoutError()
}
@@ -403,7 +450,8 @@
@${annotation.java.canonicalName}(entity = User.class)
abstract public int foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo, fullnameJfo)) { _, _ ->
+ additionalJFOs = listOf(usernameJfo, fullnameJfo)
+ ) { _, _ ->
}.compilesWithoutError()
}
@@ -436,7 +484,8 @@
@${annotation.java.canonicalName}(entity = User.class)
abstract public int foo(UserPets userPets);
""",
- additionalJFOs = listOf(userPetsJfo, petJfo)) { _, _ ->
+ additionalJFOs = listOf(userPetsJfo, petJfo)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_RELATION_IN_PARTIAL_ENTITY)
}
@@ -453,33 +502,43 @@
additionalJFOs: List<JavaFileObject> = emptyList(),
handler: (T, TestInvocation) -> Unit
):
- CompileTester {
- return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(listOf(JavaFileObjects.forSourceString("foo.bar.MyClass",
- DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
- ), COMMON.USER, COMMON.BOOK, COMMON.NOT_AN_ENTITY, COMMON.RX2_COMPLETABLE,
- COMMON.RX2_MAYBE, COMMON.RX2_SINGLE, COMMON.RX3_COMPLETABLE,
- COMMON.RX3_MAYBE, COMMON.RX3_SINGLE, COMMON.LISTENABLE_FUTURE,
- COMMON.GUAVA_ROOM) + additionalJFOs)
- .processedWith(TestProcessor.builder()
+ CompileTester {
+ return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
+ .that(
+ listOf(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyClass",
+ DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
+ ),
+ COMMON.USER, COMMON.BOOK, COMMON.NOT_AN_ENTITY, COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_MAYBE, COMMON.RX2_SINGLE, COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_MAYBE, COMMON.RX3_SINGLE, COMMON.LISTENABLE_FUTURE,
+ COMMON.GUAVA_ROOM
+ ) + additionalJFOs
+ )
+ .processedWith(
+ TestProcessor.builder()
.forAnnotations(annotation, Dao::class)
.nextRunHandler { invocation ->
val (owner, methods) = invocation.roundEnv
- .getElementsAnnotatedWith(Dao::class.java)
- .map {
- Pair(it,
- it.asTypeElement().getAllMethods().filter {
- it.hasAnnotation(annotation)
- }
- )
- }.first { it.second.isNotEmpty() }
+ .getElementsAnnotatedWith(Dao::class.java)
+ .map {
+ Pair(
+ it,
+ it.asTypeElement().getAllMethods().filter {
+ it.hasAnnotation(annotation)
+ }
+ )
+ }.first { it.second.isNotEmpty() }
val processed = process(
- baseContext = invocation.context,
- containing = owner.asDeclaredType(),
- executableElement = methods.first())
+ baseContext = invocation.context,
+ containing = owner.asDeclaredType(),
+ executableElement = methods.first()
+ )
handler(processed, invocation)
true
}
- .build())
- }
+ .build()
+ )
+ }
}
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 62a30e5..bc6a765 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt
@@ -42,22 +42,30 @@
class TableEntityProcessorTest : BaseEntityParserTest() {
@Test
fun simple() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
- """) { entity, invocation ->
+ """
+ ) { entity, invocation ->
assertThat(entity.type.toString(), `is`("foo.bar.MyEntity"))
assertThat(entity.fields.size, `is`(1))
val field = entity.fields.first()
val intType = invocation.processingEnv.requireType(TypeName.INT)
- assertThat(field, `is`(Field(
- element = field.element,
- name = "id",
- type = intType,
- columnName = "id",
- affinity = SQLTypeAffinity.INTEGER)))
+ assertThat(
+ field,
+ `is`(
+ Field(
+ element = field.element,
+ name = "id",
+ type = intType,
+ columnName = "id",
+ affinity = SQLTypeAffinity.INTEGER
+ )
+ )
+ )
assertThat(field.setter, `is`(FieldSetter("setId", intType, CallType.METHOD)))
assertThat(field.getter, `is`(FieldGetter("getId", intType, CallType.METHOD)))
assertThat(entity.primaryKey.fields, `is`(Fields(field)))
@@ -66,94 +74,113 @@
@Test
fun noGetter() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public void setId(int id) {this.id = id;}
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD)
}
@Test
fun noGetterInLibraryClass() {
val libraryClasspath = compileLibrarySource(
- "test.library.MissingGetterEntity",
- """
+ "test.library.MissingGetterEntity",
+ """
@Entity
public class MissingGetterEntity {
@PrimaryKey
private long id;
public void setId(int id) {this.id = id;}
}
- """)
- singleEntity("",
- baseClass = "test.library.MissingGetterEntity",
- classpathFiles = libraryClasspath) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD +
- " - id in test.library.MissingGetterEntity")
+ """
+ )
+ singleEntity(
+ "",
+ baseClass = "test.library.MissingGetterEntity",
+ classpathFiles = libraryClasspath
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(
+ ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD +
+ " - id in test.library.MissingGetterEntity"
+ )
}
@Test
fun getterWithBadType() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public float getId() {return 0f;}
public void setId(int id) {this.id = id;}
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD)
}
@Test
fun setterWithBadType() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public int getId() {return id;}
public void setId(float id) {}
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.CANNOT_FIND_SETTER_FOR_FIELD)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.CANNOT_FIND_SETTER_FOR_FIELD)
}
@Test
fun setterWithAssignableType() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public int getId() {return id;}
public void setId(Integer id) {}
- """) { _, _ -> }
- .compilesWithoutError()
+ """
+ ) { _, _ -> }
+ .compilesWithoutError()
}
@Test
fun getterWithAssignableType() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public Integer getId() {return id;}
public void setId(int id) {}
- """) { _, _ -> }
- .compilesWithoutError()
+ """
+ ) { _, _ -> }
+ .compilesWithoutError()
}
@Test
fun setterWithAssignableType_2() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private Integer id;
public Integer getId() {return id;}
public void setId(int id) {}
- """) { entity, invocation ->
+ """
+ ) { 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.processingEnv.requireType(TypeName.INT).typeName))
+ assertThat(
+ cursorValueReader.typeMirror().typeName,
+ `is`(invocation.processingEnv.requireType(TypeName.INT).typeName)
+ )
}.compilesWithoutError()
.withWarningContaining(
ProcessorErrors.mismatchedSetter(
@@ -167,78 +194,92 @@
@Test
fun getterWithAssignableType_2() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private Integer id;
public int getId() {return id == null ? 0 : id;}
public void setId(Integer id) {}
- """) { entity, invocation ->
+ """
+ ) { entity, invocation ->
val idField = entity.fields.first()
val statementBinder = idField.statementBinder
?: throw AssertionError("must have a statement binder")
- assertThat(statementBinder.typeMirror().typeName,
- `is`(invocation.processingEnv.requireType(TypeName.INT).typeName))
+ assertThat(
+ statementBinder.typeMirror().typeName,
+ `is`(invocation.processingEnv.requireType(TypeName.INT).typeName)
+ )
}.compilesWithoutError()
}
@Test
fun noSetter() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public int getId(){ return id; }
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining(ProcessorErrors.CANNOT_FIND_SETTER_FOR_FIELD)
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining(ProcessorErrors.CANNOT_FIND_SETTER_FOR_FIELD)
}
@Test
fun tooManyGetters() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public void setId(int id) {}
public int getId(){ return id; }
public int id(){ return id; }
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining("getId, id")
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining("getId, id")
}
@Test
fun tooManyGettersWithIgnore() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public void setId(int id) {}
public int getId(){ return id; }
@Ignore public int id(){ return id; }
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.fields.first().getter.name, `is`("getId"))
}.compilesWithoutError()
}
@Test
fun tooManyGettersWithDifferentVisibility() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public void setId(int id) {}
public int getId(){ return id; }
protected int id(){ return id; }
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.fields.first().getter.name, `is`("getId"))
}.compilesWithoutError()
}
@Test
fun tooManyGettersWithDifferentTypes() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
public int id;
public void setId(int id) {}
public int getId(){ return id; }
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.fields.first().getter.name, `is`("id"))
assertThat(entity.fields.first().getter.callType, `is`(CallType.FIELD))
}.compilesWithoutError()
@@ -246,51 +287,59 @@
@Test
fun tooManySetters() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public void setId(int id) {}
public void id(int id) {}
public int getId(){ return id; }
- """) { _, _ -> }
- .failsToCompile()
- .withErrorContaining("setId, id")
+ """
+ ) { _, _ -> }
+ .failsToCompile()
+ .withErrorContaining("setId, id")
}
@Test
fun tooManySettersWithIgnore() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public void setId(int id) {}
@Ignore public void id(int id) {}
public int getId(){ return id; }
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.fields.first().setter.name, `is`("setId"))
}.compilesWithoutError()
}
@Test
fun tooManySettersWithDifferentVisibility() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
private int id;
public void setId(int id) {}
protected void id(int id) {}
public int getId(){ return id; }
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.fields.first().setter.name, `is`("setId"))
}.compilesWithoutError()
}
@Test
fun tooManySettersWithDifferentTypes() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
public int id;
public void setId(int id) {}
public int getId(){ return id; }
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.fields.first().setter.name, `is`("id"))
assertThat(entity.fields.first().setter.callType, `is`(CallType.FIELD))
}.compilesWithoutError()
@@ -298,12 +347,14 @@
@Test
fun preferPublicOverProtected() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
int id;
public void setId(int id) {}
public int getId(){ return id; }
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.fields.first().setter.name, `is`("setId"))
assertThat(entity.fields.first().getter.name, `is`("getId"))
}.compilesWithoutError()
@@ -311,44 +362,54 @@
@Test
fun customName() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
int x;
- """, hashMapOf(Pair("tableName", "\"foo_table\""))) { entity, _ ->
+ """,
+ hashMapOf(Pair("tableName", "\"foo_table\""))
+ ) { entity, _ ->
assertThat(entity.tableName, `is`("foo_table"))
}.compilesWithoutError()
}
@Test
fun emptyCustomName() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
int x;
- """, hashMapOf(Pair("tableName", "\" \""))) { _, _ ->
+ """,
+ hashMapOf(Pair("tableName", "\" \""))
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.ENTITY_TABLE_NAME_CANNOT_BE_EMPTY)
}
@Test
fun missingPrimaryKey() {
- singleEntity("""
- """) { _, _ ->
+ singleEntity(
+ """
+ """
+ ) { _, _ ->
}.failsToCompile()
- .withErrorContaining(ProcessorErrors.MISSING_PRIMARY_KEY)
+ .withErrorContaining(ProcessorErrors.MISSING_PRIMARY_KEY)
}
@Test
fun missingColumnAdapter() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
public java.util.Date myDate;
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.CANNOT_FIND_COLUMN_TYPE_ADAPTER)
}
@Test
fun dropSubPrimaryKey() {
singleEntity(
- """
+ """
@PrimaryKey
int id;
@Embedded
@@ -362,15 +423,18 @@
) { entity, _ ->
assertThat(entity.primaryKey.fields.map { it.name }, `is`(listOf("id")))
}.compilesWithoutError()
- .withWarningCount(1)
- .withWarningContaining(ProcessorErrors.embeddedPrimaryKeyIsDropped(
- "foo.bar.MyEntity", "x"))
+ .withWarningCount(1)
+ .withWarningContaining(
+ ProcessorErrors.embeddedPrimaryKeyIsDropped(
+ "foo.bar.MyEntity", "x"
+ )
+ )
}
@Test
fun ignoreDropSubPrimaryKey() {
singleEntity(
- """
+ """
@PrimaryKey
int id;
@Embedded
@@ -390,7 +454,7 @@
@Test
fun notNull() {
singleEntity(
- """
+ """
@PrimaryKey int id;
@NonNull public String name;
"""
@@ -409,193 +473,264 @@
@Test
fun index_simple() {
val annotation = mapOf(
- "indices" to """@Index("foo")"""
+ "indices" to """@Index("foo")"""
)
singleEntity(
- """
+ """
@PrimaryKey
public int id;
public String foo;
- """, annotation) { entity, _ ->
- assertThat(entity.indices, `is`(
- listOf(Index(name = "index_MyEntity_foo",
+ """,
+ annotation
+ ) { entity, _ ->
+ assertThat(
+ entity.indices,
+ `is`(
+ listOf(
+ Index(
+ name = "index_MyEntity_foo",
unique = false,
- fields = fieldsByName(entity, "foo")))))
+ fields = fieldsByName(entity, "foo")
+ )
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun index_fromField() {
singleEntity(
- """
+ """
@PrimaryKey
public int id;
@ColumnInfo(index = true)
public String foo;
- """) { entity, _ ->
- assertThat(entity.indices, `is`(
- listOf(Index(name = "index_MyEntity_foo",
+ """
+ ) { entity, _ ->
+ assertThat(
+ entity.indices,
+ `is`(
+ listOf(
+ Index(
+ name = "index_MyEntity_foo",
unique = false,
- fields = fieldsByName(entity, "foo")))
- ))
+ fields = fieldsByName(entity, "foo")
+ )
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun index_multiColumn() {
val annotation = mapOf(
- "indices" to """@Index({"foo", "id"})"""
+ "indices" to """@Index({"foo", "id"})"""
)
singleEntity(
- """
+ """
@PrimaryKey
public int id;
public String foo;
- """, annotation) { entity, _ ->
- assertThat(entity.indices, `is`(
- listOf(Index(name = "index_MyEntity_foo_id",
+ """,
+ annotation
+ ) { entity, _ ->
+ assertThat(
+ entity.indices,
+ `is`(
+ listOf(
+ Index(
+ name = "index_MyEntity_foo_id",
unique = false,
- fields = fieldsByName(entity, "foo", "id")))
- ))
+ fields = fieldsByName(entity, "foo", "id")
+ )
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun index_multiple() {
val annotation = mapOf(
- "indices" to """{@Index({"foo", "id"}), @Index({"bar_column", "foo"})}"""
+ "indices" to """{@Index({"foo", "id"}), @Index({"bar_column", "foo"})}"""
)
singleEntity(
- """
+ """
@PrimaryKey
public int id;
public String foo;
@ColumnInfo(name = "bar_column")
public String bar;
- """, annotation) { entity, _ ->
- assertThat(entity.indices, `is`(
- listOf(Index(name = "index_MyEntity_foo_id",
+ """,
+ annotation
+ ) { entity, _ ->
+ assertThat(
+ entity.indices,
+ `is`(
+ listOf(
+ Index(
+ name = "index_MyEntity_foo_id",
unique = false,
- fields = fieldsByName(entity, "foo", "id")),
- Index(name = "index_MyEntity_bar_column_foo",
- unique = false,
- fields = fieldsByName(entity, "bar", "foo")))
- ))
+ fields = fieldsByName(entity, "foo", "id")
+ ),
+ Index(
+ name = "index_MyEntity_bar_column_foo",
+ unique = false,
+ fields = fieldsByName(entity, "bar", "foo")
+ )
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun index_unique() {
val annotation = mapOf(
- "indices" to """@Index(value = {"foo", "id"}, unique = true)"""
+ "indices" to """@Index(value = {"foo", "id"}, unique = true)"""
)
singleEntity(
- """
+ """
@PrimaryKey
public int id;
public String foo;
- """, annotation) { entity, _ ->
- assertThat(entity.indices, `is`(
- listOf(Index(
+ """,
+ annotation
+ ) { entity, _ ->
+ assertThat(
+ entity.indices,
+ `is`(
+ listOf(
+ Index(
name = "index_MyEntity_foo_id",
unique = true,
- fields = fieldsByName(entity, "foo", "id")))
- ))
+ fields = fieldsByName(entity, "foo", "id")
+ )
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun index_customName() {
val annotation = mapOf(
- "indices" to """@Index(value = {"foo"}, name = "myName")"""
+ "indices" to """@Index(value = {"foo"}, name = "myName")"""
)
singleEntity(
- """
+ """
@PrimaryKey
public int id;
public String foo;
- """, annotation) { entity, _ ->
- assertThat(entity.indices, `is`(
- listOf(Index(name = "myName",
+ """,
+ annotation
+ ) { entity, _ ->
+ assertThat(
+ entity.indices,
+ `is`(
+ listOf(
+ Index(
+ name = "myName",
unique = false,
- fields = fieldsByName(entity, "foo")))
- ))
+ fields = fieldsByName(entity, "foo")
+ )
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun index_customTableName() {
val annotation = mapOf(
- "tableName" to "\"MyTable\"",
- "indices" to """@Index(value = {"foo"})"""
+ "tableName" to "\"MyTable\"",
+ "indices" to """@Index(value = {"foo"})"""
)
singleEntity(
- """
+ """
@PrimaryKey
public int id;
public String foo;
- """, annotation) { entity, _ ->
- assertThat(entity.indices, `is`(
- listOf(Index(name = "index_MyTable_foo",
+ """,
+ annotation
+ ) { entity, _ ->
+ assertThat(
+ entity.indices,
+ `is`(
+ listOf(
+ Index(
+ name = "index_MyTable_foo",
unique = false,
- fields = fieldsByName(entity, "foo")))
- ))
+ fields = fieldsByName(entity, "foo")
+ )
+ )
+ )
+ )
}.compilesWithoutError()
}
@Test
fun index_empty() {
val annotation = mapOf(
- "indices" to """@Index({})"""
+ "indices" to """@Index({})"""
)
singleEntity(
- """
+ """
@PrimaryKey
public int id;
public String foo;
- """, annotation) { _, _ ->
+ """,
+ annotation
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.INDEX_COLUMNS_CANNOT_BE_EMPTY
+ ProcessorErrors.INDEX_COLUMNS_CANNOT_BE_EMPTY
)
}
@Test
fun index_missingColumn() {
val annotation = mapOf(
- "indices" to """@Index({"foo", "bar"})"""
+ "indices" to """@Index({"foo", "bar"})"""
)
singleEntity(
- """
+ """
@PrimaryKey
public int id;
public String foo;
- """, annotation) { _, _ ->
+ """,
+ annotation
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.indexColumnDoesNotExist("bar", listOf("id, foo"))
+ ProcessorErrors.indexColumnDoesNotExist("bar", listOf("id, foo"))
)
}
@Test
fun index_nameConflict() {
val annotation = mapOf(
- "indices" to """@Index({"foo"})"""
+ "indices" to """@Index({"foo"})"""
)
singleEntity(
- """
+ """
@PrimaryKey
public int id;
@ColumnInfo(index = true)
public String foo;
- """, annotation) { _, _ ->
+ """,
+ annotation
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.duplicateIndexInEntity("index_MyEntity_foo")
+ ProcessorErrors.duplicateIndexInEntity("index_MyEntity_foo")
)
}
@Test
fun index_droppedParentFieldIndex() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
public class Base {
@@ -605,26 +740,31 @@
String name;
String lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
- """, baseClass = "foo.bar.Base", jfos = listOf(parent)) { entity, _ ->
+ """,
+ baseClass = "foo.bar.Base", jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.indices.isEmpty(), `is`(true))
}.compilesWithoutError()
- .withWarningContaining(
- ProcessorErrors.droppedSuperClassFieldIndex(
- fieldName = "name",
- childEntity = "foo.bar.MyEntity",
- superEntity = "foo.bar.Base")
+ .withWarningContaining(
+ ProcessorErrors.droppedSuperClassFieldIndex(
+ fieldName = "name",
+ childEntity = "foo.bar.MyEntity",
+ superEntity = "foo.bar.Base"
)
+ )
}
@Test
fun index_keptGrandParentEntityIndex() {
- val grandParent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val grandParent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
@Entity(indices = @Index({"name", "lastName"}))
@@ -633,37 +773,48 @@
long baseId;
String name, lastName;
}
- """)
- val parent = JavaFileObjects.forSourceLines("foo.bar.Parent",
"""
+ )
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Parent",
+ """
package foo.bar;
import androidx.room.*;
public class Parent extends Base {
String iHaveAField;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
""",
- baseClass = "foo.bar.Parent",
- attributes = hashMapOf("inheritSuperIndices" to "true"),
- jfos = listOf(parent, grandParent)) {
+ baseClass = "foo.bar.Parent",
+ attributes = hashMapOf("inheritSuperIndices" to "true"),
+ jfos = listOf(parent, grandParent)
+ ) {
entity, _ ->
assertThat(entity.indices.size, `is`(1))
- assertThat(entity.indices.first(),
- `is`(Index(name = "index_MyEntity_name_lastName",
- unique = false,
- fields = fieldsByName(entity, "name", "lastName"))))
+ assertThat(
+ entity.indices.first(),
+ `is`(
+ Index(
+ name = "index_MyEntity_name_lastName",
+ unique = false,
+ fields = fieldsByName(entity, "name", "lastName")
+ )
+ )
+ )
}.compilesWithoutError().withWarningCount(0)
}
@Test
fun index_keptParentEntityIndex() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
@Entity(indices = @Index({"name", "lastName"}))
@@ -672,43 +823,54 @@
long baseId;
String name, lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
""",
- baseClass = "foo.bar.Base",
- attributes = hashMapOf("inheritSuperIndices" to "true"),
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ attributes = hashMapOf("inheritSuperIndices" to "true"),
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.indices.size, `is`(1))
- assertThat(entity.indices.first(),
- `is`(Index(name = "index_MyEntity_name_lastName",
- unique = false,
- fields = fieldsByName(entity, "name", "lastName"))))
+ assertThat(
+ entity.indices.first(),
+ `is`(
+ Index(
+ name = "index_MyEntity_name_lastName",
+ unique = false,
+ fields = fieldsByName(entity, "name", "lastName")
+ )
+ )
+ )
}.compilesWithoutError().withWarningCount(0)
}
@Test
fun ignoredFields() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
public class Base {
String name;
String tmp1;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
public String tmp2;
""",
- baseClass = "foo.bar.Base",
- attributes = hashMapOf("ignoredColumns" to "{\"tmp1\", \"tmp2\"}"),
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ attributes = hashMapOf("ignoredColumns" to "{\"tmp1\", \"tmp2\"}"),
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.fields.size, `is`(2))
assertThat(entity.fields.map(Field::name), hasItems("name", "id"))
}.compilesWithoutError().withWarningCount(0)
@@ -716,8 +878,9 @@
@Test
fun index_keptParentFieldIndex() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
public class Base {
@@ -727,27 +890,36 @@
String name;
String lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
""",
- baseClass = "foo.bar.Base",
- attributes = hashMapOf("inheritSuperIndices" to "true"),
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ attributes = hashMapOf("inheritSuperIndices" to "true"),
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.indices.size, `is`(1))
- assertThat(entity.indices.first(),
- `is`(Index(name = "index_MyEntity_name",
- unique = false,
- fields = fieldsByName(entity, "name"))))
+ assertThat(
+ entity.indices.first(),
+ `is`(
+ Index(
+ name = "index_MyEntity_name",
+ unique = false,
+ fields = fieldsByName(entity, "name")
+ )
+ )
+ )
}.compilesWithoutError().withWarningCount(0)
}
@Test
fun index_droppedGrandParentEntityIndex() {
- val grandParent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val grandParent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
@Entity(indices = @Index({"name", "lastName"}))
@@ -756,35 +928,42 @@
long baseId;
String name, lastName;
}
- """)
- val parent = JavaFileObjects.forSourceLines("foo.bar.Parent",
"""
+ )
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Parent",
+ """
package foo.bar;
import androidx.room.*;
public class Parent extends Base {
String iHaveAField;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
- """, baseClass = "foo.bar.Parent", jfos = listOf(parent, grandParent)) {
+ """,
+ baseClass = "foo.bar.Parent", jfos = listOf(parent, grandParent)
+ ) {
entity, _ ->
assertThat(entity.indices.isEmpty(), `is`(true))
}.compilesWithoutError()
- .withWarningContaining(
- ProcessorErrors.droppedSuperClassIndex(
- childEntity = "foo.bar.MyEntity",
- superEntity = "foo.bar.Base")
+ .withWarningContaining(
+ ProcessorErrors.droppedSuperClassIndex(
+ childEntity = "foo.bar.MyEntity",
+ superEntity = "foo.bar.Base"
)
+ )
}
@Test
fun index_droppedParentEntityIndex() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
@Entity(indices = @Index({"name", "lastName"}))
@@ -793,25 +972,29 @@
long baseId;
String name, lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
- """, baseClass = "foo.bar.Base", jfos = listOf(parent)) { entity, _ ->
+ """,
+ baseClass = "foo.bar.Base", jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.indices.isEmpty(), `is`(true))
}.compilesWithoutError()
- .withWarningContaining(
- ProcessorErrors.droppedSuperClassIndex(
- childEntity = "foo.bar.MyEntity",
- superEntity = "foo.bar.Base")
+ .withWarningContaining(
+ ProcessorErrors.droppedSuperClassIndex(
+ childEntity = "foo.bar.MyEntity",
+ superEntity = "foo.bar.Base"
)
+ )
}
@Test
fun index_droppedEmbeddedEntityIndex() {
singleEntity(
- """
+ """
@PrimaryKey
public int id;
@Embedded
@@ -824,21 +1007,23 @@
@ColumnInfo(index = true)
public int a;
}
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.indices.isEmpty(), `is`(true))
}.compilesWithoutError()
- .withWarningContaining(
- ProcessorErrors.droppedEmbeddedIndex(
- entityName = "foo.bar.MyEntity.Foo",
- fieldPath = "foo",
- grandParent = "foo.bar.MyEntity")
+ .withWarningContaining(
+ ProcessorErrors.droppedEmbeddedIndex(
+ entityName = "foo.bar.MyEntity.Foo",
+ fieldPath = "foo",
+ grandParent = "foo.bar.MyEntity"
)
+ )
}
@Test
fun index_onEmbeddedField() {
singleEntity(
- """
+ """
@PrimaryKey
public int id;
@Embedded
@@ -848,17 +1033,18 @@
@ColumnInfo(index = true)
public int a;
}
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.indices.isEmpty(), `is`(true))
}.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_USE_MORE_THAN_ONE_POJO_FIELD_ANNOTATION
+ ProcessorErrors.CANNOT_USE_MORE_THAN_ONE_POJO_FIELD_ANNOTATION
)
}
@Test
fun index_droppedEmbeddedFieldIndex() {
singleEntity(
- """
+ """
@PrimaryKey
public int id;
@Embedded
@@ -867,18 +1053,19 @@
@ColumnInfo(index = true)
public int a;
}
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.indices.isEmpty(), `is`(true))
}.compilesWithoutError()
- .withWarningContaining(
- ProcessorErrors.droppedEmbeddedFieldIndex("foo > a", "foo.bar.MyEntity")
- )
+ .withWarningContaining(
+ ProcessorErrors.droppedEmbeddedFieldIndex("foo > a", "foo.bar.MyEntity")
+ )
}
@Test
fun index_referenceEmbeddedField() {
singleEntity(
- """
+ """
@PrimaryKey
public int id;
@Embedded
@@ -886,63 +1073,77 @@
static class Foo {
public int a;
}
- """, attributes = mapOf("indices" to "@Index(\"a\")")) { entity, _ ->
+ """,
+ attributes = mapOf("indices" to "@Index(\"a\")")
+ ) { entity, _ ->
assertThat(entity.indices.size, `is`(1))
- assertThat(entity.indices.first(), `is`(
+ assertThat(
+ entity.indices.first(),
+ `is`(
Index(
- name = "index_MyEntity_a",
- unique = false,
- fields = fieldsByName(entity, "a")
+ name = "index_MyEntity_a",
+ unique = false,
+ fields = fieldsByName(entity, "a")
)
- ))
+ )
+ )
}.compilesWithoutError()
}
@Test
fun primaryKey_definedInBothWays() {
singleEntity(
- """
+ """
public int id;
@PrimaryKey
public String foo;
""",
- attributes = mapOf("primaryKeys" to "\"id\"")) { _, _ ->
+ attributes = mapOf("primaryKeys" to "\"id\"")
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.multiplePrimaryKeyAnnotations(
- listOf("PrimaryKey[id]", "PrimaryKey[foo]")
- ))
+ ProcessorErrors.multiplePrimaryKeyAnnotations(
+ listOf("PrimaryKey[id]", "PrimaryKey[foo]")
+ )
+ )
}
@Test
fun primaryKey_badColumnName() {
singleEntity(
- """
+ """
public int id;
""",
- attributes = mapOf("primaryKeys" to "\"foo\"")) { _, _ ->
+ attributes = mapOf("primaryKeys" to "\"foo\"")
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.primaryKeyColumnDoesNotExist("foo", listOf("id")))
+ ProcessorErrors.primaryKeyColumnDoesNotExist("foo", listOf("id"))
+ )
}
@Test
fun primaryKey_multipleAnnotations() {
- singleEntity("""
+ singleEntity(
+ """
@PrimaryKey
int x;
@PrimaryKey
int y;
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.isEmpty(), `is`(true))
}.failsToCompile()
- .withErrorContaining(
- ProcessorErrors.multiplePrimaryKeyAnnotations(
- listOf("PrimaryKey[x]", "PrimaryKey[y]")))
+ .withErrorContaining(
+ ProcessorErrors.multiplePrimaryKeyAnnotations(
+ listOf("PrimaryKey[x]", "PrimaryKey[y]")
+ )
+ )
}
@Test
fun primaryKey_fromParentField() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
public class Base {
@@ -950,21 +1151,24 @@
long baseId;
String name, lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("baseId"))
}.compilesWithoutError().withWarningCount(0)
}
@Test
fun primaryKey_fromParentEntity() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
@Entity(primaryKeys = "baseId")
@@ -972,21 +1176,24 @@
long baseId;
String name, lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("baseId"))
}.compilesWithoutError().withWarningCount(0)
}
@Test
fun primaryKey_overrideFromParentField() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
public class Base {
@@ -994,26 +1201,29 @@
long baseId;
String name, lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.size, `is`(1))
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("id"))
assertThat(entity.primaryKey.autoGenerateId, `is`(false))
}.compilesWithoutError().withNoteContaining(
- "PrimaryKey[baseId] is overridden by PrimaryKey[id]"
+ "PrimaryKey[baseId] is overridden by PrimaryKey[id]"
)
}
@Test
fun primaryKey_overrideFromParentEntityViaField() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
@Entity(primaryKeys = "baseId")
@@ -1021,25 +1231,28 @@
long baseId;
String name, lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.size, `is`(1))
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("id"))
}.compilesWithoutError().withNoteContaining(
- "PrimaryKey[baseId] is overridden by PrimaryKey[id]"
+ "PrimaryKey[baseId] is overridden by PrimaryKey[id]"
)
}
@Test
fun primaryKey_overrideFromParentEntityViaEntity() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
@Entity(primaryKeys = "baseId")
@@ -1047,19 +1260,21 @@
long baseId;
String name, lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent),
- attributes = mapOf("primaryKeys" to "\"id\"")) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent),
+ attributes = mapOf("primaryKeys" to "\"id\"")
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.size, `is`(1))
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("id"))
assertThat(entity.primaryKey.autoGenerateId, `is`(false))
}.compilesWithoutError().withNoteContaining(
- "PrimaryKey[baseId] is overridden by PrimaryKey[id]"
+ "PrimaryKey[baseId] is overridden by PrimaryKey[id]"
)
}
@@ -1067,10 +1282,11 @@
fun primaryKey_autoGenerate() {
listOf("long", "Long", "Integer", "int").forEach { type ->
singleEntity(
- """
+ """
@PrimaryKey(autoGenerate = true)
public $type id;
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.size, `is`(1))
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("id"))
assertThat(entity.primaryKey.autoGenerateId, `is`(true))
@@ -1082,10 +1298,11 @@
fun primaryKey_nonNull_notNeeded() {
listOf("long", "Long", "Integer", "int").forEach { type ->
singleEntity(
- """
+ """
@PrimaryKey
public $type id;
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.size, `is`(1))
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("id"))
assertThat(entity.primaryKey.autoGenerateId, `is`(false))
@@ -1097,22 +1314,24 @@
fun primaryKey_autoGenerateBadType() {
listOf("String", "float", "Float", "Double", "double").forEach { type ->
singleEntity(
- """
+ """
@PrimaryKey(autoGenerate = true)
public $type id;
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.size, `is`(1))
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("id"))
assertThat(entity.primaryKey.autoGenerateId, `is`(true))
}.failsToCompile().withErrorContaining(
- ProcessorErrors.AUTO_INCREMENTED_PRIMARY_KEY_IS_NOT_INT)
+ ProcessorErrors.AUTO_INCREMENTED_PRIMARY_KEY_IS_NOT_INT
+ )
}
}
@Test
fun primaryKey_embedded() {
singleEntity(
- """
+ """
public int id;
@Embedded(prefix = "bar_")
@@ -1124,15 +1343,17 @@
public int a;
public int b;
}
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.primaryKey.columnNames, `is`(listOf("bar_a", "bar_b")))
}.compilesWithoutError().withWarningCount(0)
}
@Test
fun primaryKey_embeddedInherited() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.annotation.NonNull;
import androidx.room.*;
@@ -1150,21 +1371,24 @@
public int b;
}
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.primaryKey.columnNames, `is`(listOf("bar_a", "bar_b")))
}.compilesWithoutError().withWarningCount(0)
}
@Test
fun primaryKey_overrideViaEmbedded() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
@@ -1173,9 +1397,10 @@
long baseId;
String name, lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
public int id;
@Embedded(prefix = "bar_")
@PrimaryKey
@@ -1187,17 +1412,20 @@
public int b;
}
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.primaryKey.columnNames, `is`(listOf("bar_a", "bar_b")))
}.compilesWithoutError().withNoteContaining(
- "PrimaryKey[baseId] is overridden by PrimaryKey[foo > a, foo > b]")
+ "PrimaryKey[baseId] is overridden by PrimaryKey[foo > a, foo > b]"
+ )
}
@Test
fun primaryKey_overrideEmbedded() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.annotation.NonNull;
import androidx.room.*;
@@ -1215,27 +1443,31 @@
public int b;
}
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { entity, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { entity, _ ->
assertThat(entity.primaryKey.columnNames, `is`(listOf("id")))
}.compilesWithoutError().withNoteContaining(
- "PrimaryKey[foo > a, foo > b] is overridden by PrimaryKey[id]")
+ "PrimaryKey[foo > a, foo > b] is overridden by PrimaryKey[id]"
+ )
}
@Test
fun primaryKey_NonNull() {
singleEntity(
- """
+ """
@PrimaryKey
@NonNull
public String id;
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.size, `is`(1))
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("id"))
}.compilesWithoutError()
@@ -1244,10 +1476,11 @@
@Test
fun primaryKey_Nullable() {
singleEntity(
- """
+ """
@PrimaryKey
public String id;
- """) { entity, _ ->
+ """
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.size, `is`(1))
assertThat(entity.primaryKey.fields.firstOrNull()?.name, `is`("id"))
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("id"))
@@ -1256,49 +1489,53 @@
@Test
fun primaryKey_MultipleNullable() {
singleEntity(
- """
+ """
@PrimaryKey
public String id;
@PrimaryKey
public String anotherId;
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("id"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("anotherId"))
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("anotherId"))
}
@Test
fun primaryKey_MultipleNullableAndNonNullable() {
singleEntity(
- """
+ """
@PrimaryKey
@NonNull
public String id;
@PrimaryKey
public String anotherId;
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("anotherId"))
}
@Test
fun primaryKey_definedAsAttributesNullable() {
singleEntity(
- """
+ """
public int id;
public String foo;
""",
- attributes = mapOf("primaryKeys" to "{\"id\", \"foo\"}")) { _, _ ->
+ attributes = mapOf("primaryKeys" to "{\"id\", \"foo\"}")
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
}
@Test
fun primaryKey_definedAsAttributesNonNull() {
singleEntity(
- """
+ """
public int id;
@NonNull
public String foo;
""",
- attributes = mapOf("primaryKeys" to "{\"id\", \"foo\"}")) { entity, _ ->
+ attributes = mapOf("primaryKeys" to "{\"id\", \"foo\"}")
+ ) { entity, _ ->
assertThat(entity.primaryKey.fields.map { it.name }, `is`(listOf("id", "foo")))
}.compilesWithoutError()
}
@@ -1306,7 +1543,7 @@
@Test
fun primaryKey_nullableEmbedded() {
singleEntity(
- """
+ """
public int id;
@Embedded(prefix = "bar_")
@@ -1317,14 +1554,15 @@
public int a;
public int b;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
}
@Test
fun primaryKey_nullableEmbeddedObject() {
singleEntity(
- """
+ """
public int id;
@Embedded(prefix = "bar_")
@@ -1335,17 +1573,18 @@
public String a;
public String b;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
- .and().withErrorCount(3)
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
+ .and().withErrorCount(3)
}
@Test
fun primaryKey_nullableEmbeddedObject_multipleParents() {
singleEntity(
- """
+ """
public int id;
@Embedded(prefix = "bar_")
@@ -1361,18 +1600,20 @@
public Integer bb;
}
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a > bb"))
- .and().withErrorCount(4)
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a > bb"))
+ .and().withErrorCount(4)
}
@Test
fun primaryKey_nullableEmbeddedInherited() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.annotation.NonNull;
import androidx.room.*;
@@ -1389,23 +1630,26 @@
public int b;
}
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { _, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
- .and().withErrorCount(3)
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+ .and().withErrorCount(3)
}
@Test
fun primaryKey_nullableOverrideViaEmbedded() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.room.*;
@@ -1414,9 +1658,10 @@
long baseId;
String name, lastName;
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
public int id;
@Embedded(prefix = "bar_")
@PrimaryKey
@@ -1427,20 +1672,23 @@
public int b;
}
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { _, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
- .and().withNoteContaining(
- "PrimaryKey[baseId] is overridden by PrimaryKey[foo > a, foo > b]")
- .and().withErrorCount(3)
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+ .and().withNoteContaining(
+ "PrimaryKey[baseId] is overridden by PrimaryKey[foo > a, foo > b]"
+ )
+ .and().withErrorCount(3)
}
@Test
fun primaryKey_nullableOverrideEmbedded() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.annotation.NonNull;
import androidx.room.*;
@@ -1457,26 +1705,30 @@
public int b;
}
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { _, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
- .and().withNoteContaining(
- "PrimaryKey[foo > a, foo > b] is overridden by PrimaryKey[id]")
- .and().withErrorCount(3)
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > b"))
+ .and().withNoteContaining(
+ "PrimaryKey[foo > a, foo > b] is overridden by PrimaryKey[id]"
+ )
+ .and().withErrorCount(3)
}
@Test
fun primaryKey_integerOverrideEmbedded() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.annotation.NonNull;
import androidx.room.*;
@@ -1492,22 +1744,26 @@
public Integer a;
}
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { _, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { _, _ ->
}.compilesWithoutError().withNoteContaining(
- "PrimaryKey[foo > a] is overridden by PrimaryKey[id]")
+ "PrimaryKey[foo > a] is overridden by PrimaryKey[id]"
+ )
}
@Test
fun primaryKey_singleStringPrimaryKeyOverrideEmbedded() {
- val parent = JavaFileObjects.forSourceLines("foo.bar.Base",
- """
+ val parent = JavaFileObjects.forSourceLines(
+ "foo.bar.Base",
+ """
package foo.bar;
import androidx.annotation.NonNull;
import androidx.room.*;
@@ -1523,30 +1779,34 @@
public String a;
}
}
- """)
- singleEntity(
"""
+ )
+ singleEntity(
+ """
@PrimaryKey
public int id;
""",
- baseClass = "foo.bar.Base",
- jfos = listOf(parent)) { _, _ ->
+ baseClass = "foo.bar.Base",
+ jfos = listOf(parent)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.primaryKeyNull("foo"))
- .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
- .and().withNoteContaining(
- "PrimaryKey[foo > a] is overridden by PrimaryKey[id]")
- .and().withErrorCount(2)
+ .and().withErrorContaining(ProcessorErrors.primaryKeyNull("foo > a"))
+ .and().withNoteContaining(
+ "PrimaryKey[foo > a] is overridden by PrimaryKey[id]"
+ )
+ .and().withErrorCount(2)
}
@Test
fun relationInEntity() {
singleEntity(
- """
+ """
@PrimaryKey
int id;
@Relation(parentColumn = "id", entityColumn = "uid")
java.util.List<User> users;
- """, jfos = listOf(COMMON.USER)
+ """,
+ jfos = listOf(COMMON.USER)
) { _, _ ->
}.failsToCompile().withErrorContaining(RELATION_IN_ENTITY)
}
@@ -1554,20 +1814,21 @@
@Test
fun foreignKey_invalidAction() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = "lastName",
childColumns = "name",
onDelete = 101
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_FOREIGN_KEY_ACTION)
}
@@ -1575,19 +1836,20 @@
@Test
fun foreignKey_badEntity() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = dsa.class,
parentColumns = "lastName",
childColumns = "name"
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { _, _ ->
}.failsToCompile().withErrorContaining("cannot find symbol")
}
@@ -1595,82 +1857,95 @@
@Test
fun foreignKey_notAnEntity() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.NOT_AN_ENTITY_TYPE_NAME}.class,
parentColumns = "lastName",
childColumns = "name"
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.NOT_AN_ENTITY)
+ attributes = annotation, jfos = listOf(COMMON.NOT_AN_ENTITY)
) { _, _ ->
- }.failsToCompile().withErrorContaining(ProcessorErrors.foreignKeyNotAnEntity(
- COMMON.NOT_AN_ENTITY_TYPE_NAME.toString()))
+ }.failsToCompile().withErrorContaining(
+ ProcessorErrors.foreignKeyNotAnEntity(
+ COMMON.NOT_AN_ENTITY_TYPE_NAME.toString()
+ )
+ )
}
@Test
fun foreignKey_invalidChildColumn() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = "lastName",
childColumns = "namex"
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { _, _ ->
- }.failsToCompile().withErrorContaining(ProcessorErrors.foreignKeyChildColumnDoesNotExist(
- "namex", listOf("id", "name")))
+ }.failsToCompile().withErrorContaining(
+ ProcessorErrors.foreignKeyChildColumnDoesNotExist(
+ "namex", listOf("id", "name")
+ )
+ )
}
@Test
fun foreignKey_columnCountMismatch() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = "lastName",
childColumns = {"name", "id"}
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { _, _ ->
- }.failsToCompile().withErrorContaining(ProcessorErrors.foreignKeyColumnNumberMismatch(
- listOf("name", "id"), listOf("lastName")))
+ }.failsToCompile().withErrorContaining(
+ ProcessorErrors.foreignKeyColumnNumberMismatch(
+ listOf("name", "id"), listOf("lastName")
+ )
+ )
}
@Test
fun foreignKey_emptyChildColumns() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = "lastName",
childColumns = {}
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.FOREIGN_KEY_EMPTY_CHILD_COLUMN_LIST)
}
@@ -1678,19 +1953,20 @@
@Test
fun foreignKey_emptyParentColumns() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = {},
childColumns = {"name"}
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.FOREIGN_KEY_EMPTY_PARENT_COLUMN_LIST)
}
@@ -1698,22 +1974,23 @@
@Test
fun foreignKey_simple() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = "lastName",
childColumns = "name",
onDelete = ForeignKey.SET_NULL,
onUpdate = ForeignKey.CASCADE,
deferred = true
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { entity, _ ->
assertThat(entity.foreignKeys.size, `is`(1))
val fKey = entity.foreignKeys.first()
@@ -1729,23 +2006,24 @@
@Test
fun foreignKey_dontDuplicationChildIndex_SingleColumn() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = "lastName",
childColumns = "name",
onDelete = ForeignKey.SET_NULL,
onUpdate = ForeignKey.CASCADE,
deferred = true
- )}""".trimIndent(),
- "indices" to """@Index("name")"""
+ )}
+ """.trimIndent(),
+ "indices" to """@Index("name")"""
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { _, _ ->
}.compilesWithoutWarnings()
}
@@ -1753,24 +2031,25 @@
@Test
fun foreignKey_dontDuplicationChildIndex_MultipleColumns() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = {"lastName", "name"},
childColumns = {"lName", "name"},
onDelete = ForeignKey.SET_NULL,
onUpdate = ForeignKey.CASCADE,
deferred = true
- )}""".trimIndent(),
- "indices" to """@Index({"lName", "name"})"""
+ )}
+ """.trimIndent(),
+ "indices" to """@Index({"lName", "name"})"""
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
String lName;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { entity, _ ->
assertThat(entity.indices.size, `is`(1))
}.compilesWithoutWarnings()
@@ -1779,24 +2058,25 @@
@Test
fun foreignKey_dontDuplicationChildIndex_WhenCovered() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = {"lastName"},
childColumns = {"name"},
onDelete = ForeignKey.SET_NULL,
onUpdate = ForeignKey.CASCADE,
deferred = true
- )}""".trimIndent(),
- "indices" to """@Index({"name", "lName"})"""
+ )}
+ """.trimIndent(),
+ "indices" to """@Index({"name", "lName"})"""
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
String lName;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { entity, _ ->
assertThat(entity.indices.size, `is`(1))
}.compilesWithoutWarnings()
@@ -1805,70 +2085,75 @@
@Test
fun foreignKey_warnMissingChildIndex() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = "lastName",
childColumns = "name",
onDelete = ForeignKey.SET_NULL,
onUpdate = ForeignKey.CASCADE,
deferred = true
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { entity, _ ->
assertThat(entity.indices, `is`(emptyList()))
}.compilesWithoutError().withWarningContaining(
- ProcessorErrors.foreignKeyMissingIndexInChildColumn("name"))
+ ProcessorErrors.foreignKeyMissingIndexInChildColumn("name")
+ )
}
@Test
fun foreignKey_warnMissingChildrenIndex() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = {"lastName", "name"},
childColumns = {"lName", "name"}
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
String lName;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { entity, _ ->
assertThat(entity.indices, `is`(emptyList()))
}.compilesWithoutError().withWarningContaining(
- ProcessorErrors.foreignKeyMissingIndexInChildColumns(listOf("lName", "name")))
+ ProcessorErrors.foreignKeyMissingIndexInChildColumns(listOf("lName", "name"))
+ )
}
@Test
fun foreignKey_dontIndexIfAlreadyPrimaryKey() {
val annotation = mapOf(
- "foreignKeys" to """{@ForeignKey(
+ "foreignKeys" to """{@ForeignKey(
entity = ${COMMON.USER_TYPE_NAME}.class,
parentColumns = "lastName",
childColumns = "id",
onDelete = ForeignKey.SET_NULL,
onUpdate = ForeignKey.CASCADE,
deferred = true
- )}""".trimIndent()
+ )}
+ """.trimIndent()
)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { entity, _ ->
assertThat(entity.indices, `is`(emptyList()))
}.compilesWithoutWarnings()
@@ -1877,19 +2162,22 @@
@Test
fun recursion_1Level() {
singleEntity(
- """
+ """
@Embedded
MyEntity myEntity;
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyEntity -> foo.bar.MyEntity"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyEntity -> foo.bar.MyEntity"
+ )
+ )
}
@Test
fun recursion_2Levels_embedToRelation() {
singleEntity(
- """
+ """
int pojoId;
@Embedded
A a;
@@ -1899,16 +2187,19 @@
@Relation(parentColumn = "entityId", entityColumn = "pojoId")
List<MyEntity> myEntity;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"
+ )
+ )
}
@Test
fun recursion_2Levels_onlyEmbeds_entityToPojo() {
singleEntity(
- """
+ """
@Embedded
A a;
@@ -1916,16 +2207,19 @@
@Embedded
MyEntity myEntity;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"
+ )
+ )
}
@Test
fun recursion_2Levels_onlyEmbeds_onlyEntities() {
singleEntity(
- """
+ """
@Embedded
A a;
@@ -1934,22 +2228,25 @@
@Embedded
MyEntity myEntity;
}
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
- ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
- "foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"))
+ ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format(
+ "foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"
+ )
+ )
}
@Test
fun okTableName() {
val annotation = mapOf("tableName" to "\"foo bar\"")
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { _, _ ->
}.compilesWithoutError()
}
@@ -1958,12 +2255,12 @@
fun badTableName() {
val annotation = mapOf("tableName" to """ "foo`bar" """)
singleEntity(
- """
+ """
@PrimaryKey
int id;
String name;
""",
- attributes = annotation, jfos = listOf(COMMON.USER)
+ attributes = annotation, jfos = listOf(COMMON.USER)
) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_TABLE_NAME)
}
@@ -1971,13 +2268,13 @@
@Test
fun badColumnName() {
singleEntity(
- """
+ """
@PrimaryKey
int id;
@ColumnInfo(name = "\"foo bar\"")
String name;
""",
- jfos = listOf(COMMON.USER)
+ jfos = listOf(COMMON.USER)
) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_COLUMN_NAME)
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/TransactionMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/TransactionMethodProcessorTest.kt
index 0b17a05..aebd173 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/TransactionMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/TransactionMethodProcessorTest.kt
@@ -52,10 +52,11 @@
@Test
fun simple() {
singleTransactionMethod(
- """
+ """
@Transaction
public String doInTransaction(int param) { return null; }
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.compilesWithoutError()
}
@@ -63,10 +64,11 @@
@Test
fun modifier_private() {
singleTransactionMethod(
- """
+ """
@Transaction
private String doInTransaction(int param) { return null; }
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile().withErrorContaining(ProcessorErrors.TRANSACTION_METHOD_MODIFIERS)
}
@@ -74,10 +76,11 @@
@Test
fun modifier_final() {
singleTransactionMethod(
- """
+ """
@Transaction
public final String doInTransaction(int param) { return null; }
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile().withErrorContaining(ProcessorErrors.TRANSACTION_METHOD_MODIFIERS)
}
@@ -88,7 +91,8 @@
"""
@Transaction
public LiveData<String> doInTransaction(int param) { return null; }
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile()
.withErrorContaining(
@@ -104,7 +108,8 @@
"""
@Transaction
public io.reactivex.Flowable<String> doInTransaction(int param) { return null; }
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile()
.withErrorContaining(
@@ -122,7 +127,8 @@
public io.reactivex.rxjava3.core.Flowable<String> doInTransaction(int param) {
return null;
}
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile()
.withErrorContaining(
@@ -138,7 +144,8 @@
"""
@Transaction
public io.reactivex.Completable doInTransaction(int param) { return null; }
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile()
.withErrorContaining(
@@ -156,7 +163,8 @@
public io.reactivex.rxjava3.core.Completable doInTransaction(int param) {
return null;
}
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile()
.withErrorContaining(
@@ -172,7 +180,8 @@
"""
@Transaction
public io.reactivex.Single<String> doInTransaction(int param) { return null; }
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile()
.withErrorContaining(
@@ -190,7 +199,8 @@
public io.reactivex.rxjava3.core.Single<String> doInTransaction(int param) {
return null;
}
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile()
.withErrorContaining(
@@ -206,7 +216,8 @@
"""
@Transaction
public ListenableFuture<String> doInTransaction(int param) { return null; }
- """) { transaction, _ ->
+ """
+ ) { transaction, _ ->
assertThat(transaction.name, `is`("doInTransaction"))
}.failsToCompile()
.withErrorContaining(
@@ -224,31 +235,41 @@
handler: (TransactionMethod, TestInvocation) -> Unit
): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(listOf(JavaFileObjects.forSourceString("foo.bar.MyClass",
+ .that(
+ listOf(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyClass",
DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
- ), COMMON.LIVE_DATA, COMMON.RX2_FLOWABLE, COMMON.PUBLISHER, COMMON.RX2_COMPLETABLE,
+ ),
+ COMMON.LIVE_DATA, COMMON.RX2_FLOWABLE, COMMON.PUBLISHER, COMMON.RX2_COMPLETABLE,
COMMON.RX2_SINGLE, COMMON.RX3_FLOWABLE, COMMON.RX3_COMPLETABLE,
- COMMON.RX3_SINGLE, COMMON.LISTENABLE_FUTURE))
- .processedWith(TestProcessor.builder()
- .forAnnotations(Transaction::class, Dao::class)
- .nextRunHandler { invocation ->
- val (owner, methods) = invocation.roundEnv
- .getElementsAnnotatedWith(Dao::class.java)
- .map {
- Pair(it,
- it.asTypeElement().getAllMethods().filter {
- it.hasAnnotation(Transaction::class)
- }
- )
- }.first { it.second.isNotEmpty() }
- val processor = TransactionMethodProcessor(
- baseContext = invocation.context,
- containing = owner.asDeclaredType(),
- executableElement = methods.first())
- val processed = processor.process()
- handler(processed, invocation)
- true
- }
- .build())
+ COMMON.RX3_SINGLE, COMMON.LISTENABLE_FUTURE
+ )
+ )
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(Transaction::class, Dao::class)
+ .nextRunHandler { invocation ->
+ val (owner, methods) = invocation.roundEnv
+ .getElementsAnnotatedWith(Dao::class.java)
+ .map {
+ Pair(
+ it,
+ it.asTypeElement().getAllMethods().filter {
+ it.hasAnnotation(Transaction::class)
+ }
+ )
+ }.first { it.second.isNotEmpty() }
+ val processor = TransactionMethodProcessor(
+ baseContext = invocation.context,
+ containing = owner.asDeclaredType(),
+ executableElement = methods.first()
+ )
+ val processed = processor.process()
+ handler(processed, invocation)
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/UpdateMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/UpdateMethodProcessorTest.kt
index 5402b10..191ec98 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/UpdateMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/UpdateMethodProcessorTest.kt
@@ -47,10 +47,11 @@
@Test
fun goodConflict() {
singleShortcutMethod(
- """
+ """
@Update(onConflict = OnConflictStrategy.REPLACE)
abstract public void foo(User user);
- """) { shortcut, _ ->
+ """
+ ) { shortcut, _ ->
assertThat(shortcut.onConflictStrategy, `is`(OnConflictStrategy.REPLACE))
}.compilesWithoutError()
}
@@ -58,10 +59,11 @@
@Test
fun badConflict() {
singleShortcutMethod(
- """
+ """
@Update(onConflict = -1)
abstract public void foo(User user);
- """) { _, _ ->
+ """
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_ON_CONFLICT_VALUE)
}
@@ -80,10 +82,13 @@
@Update(entity = User.class)
abstract public int foo(Username username);
""",
- additionalJFOs = listOf(usernameJfo)) { _, _ ->
+ additionalJFOs = listOf(usernameJfo)
+ ) { _, _ ->
}.failsToCompile().withErrorContaining(
ProcessorErrors.missingPrimaryKeysInPartialEntityForUpdate(
partialEntityName = "foo.bar.Username",
- primaryKeyNames = listOf("uid")))
+ primaryKeyNames = listOf("uid")
+ )
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegateTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegateTest.kt
index 1a7e3cb..1e194a4 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegateTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/autovalue/AutoValuePojoProcessorDelegateTest.kt
@@ -67,13 +67,13 @@
@Test
fun goodPojo() {
singleRun(
- """
+ """
@AutoValue.CopyAnnotations
@PrimaryKey
abstract long getId();
static MyPojo create(long id) { return new AutoValue_MyPojo(id); }
""",
- """
+ """
@PrimaryKey
private final long id;
AutoValue_MyPojo(long id) { this.id = id; }
@@ -90,7 +90,8 @@
@Test
fun goodLibraryPojo() {
val libraryClasspath = compileLibrarySources(
- JavaFileObjects.forSourceString(MY_POJO.toString(),
+ JavaFileObjects.forSourceString(
+ MY_POJO.toString(),
"""
$HEADER
@AutoValue.CopyAnnotations
@@ -98,33 +99,36 @@
abstract long getArg0();
static MyPojo create(long arg0) { return new AutoValue_MyPojo(arg0); }
$FOOTER
- """)
+ """
+ )
)
simpleRun(classpathFiles = libraryClasspath) { invocation ->
- PojoProcessor.createFor(context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(MY_POJO),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process()
+ PojoProcessor.createFor(
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(MY_POJO),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
+ ).process()
}.compilesWithoutError().withWarningCount(0)
}
@Test
fun missingCopyAnnotationsWarning() {
singleRun(
- """
+ """
@PrimaryKey
abstract long getId();
static MyPojo create(long id) { return new AutoValue_MyPojo(id); }
""",
- """
+ """
private final long id;
AutoValue_MyPojo(long id) { this.id = id; }
long getId() { return this.id; }
"""
) { _ -> }
- .compilesWithoutError()
- .withWarningCount(1)
- .withWarningContaining(ProcessorErrors.MISSING_COPY_ANNOTATIONS)
+ .compilesWithoutError()
+ .withWarningCount(1)
+ .withWarningContaining(ProcessorErrors.MISSING_COPY_ANNOTATIONS)
}
@Test
@@ -140,7 +144,7 @@
}
"""
singleRunFullClass(
- """
+ """
package foo.bar;
import androidx.room.*;
@@ -156,7 +160,7 @@
}
$FOOTER
""",
- """
+ """
$AUTO_VALUE_HEADER
private final long id;
private final String value;
@@ -165,11 +169,11 @@
String getValue() { return this.value; };
$FOOTER
""",
- parent.toJFO("foo.bar.ParentPojo")
+ parent.toJFO("foo.bar.ParentPojo")
) { _, _ -> }
- .compilesWithoutError()
- .withWarningCount(2)
- .withWarningContaining(ProcessorErrors.MISSING_COPY_ANNOTATIONS)
+ .compilesWithoutError()
+ .withWarningCount(2)
+ .withWarningContaining(ProcessorErrors.MISSING_COPY_ANNOTATIONS)
}
@Test
@@ -185,7 +189,7 @@
}
"""
singleRunFullClass(
- """
+ """
package foo.bar;
import androidx.room.*;
@@ -201,7 +205,7 @@
}
$FOOTER
""",
- """
+ """
$AUTO_VALUE_HEADER
private final long id;
private final String value;
@@ -210,11 +214,11 @@
public String getValue() { return this.value; };
$FOOTER
""",
- parent.toJFO("foo.bar.InterfacePojo")
+ parent.toJFO("foo.bar.InterfacePojo")
) { _, _ -> }
- .compilesWithoutError()
- .withWarningCount(2)
- .withWarningContaining(ProcessorErrors.MISSING_COPY_ANNOTATIONS)
+ .compilesWithoutError()
+ .withWarningCount(2)
+ .withWarningContaining(ProcessorErrors.MISSING_COPY_ANNOTATIONS)
}
private fun singleRun(
@@ -236,19 +240,19 @@
handler: (Pojo, TestInvocation) -> Unit
): CompileTester {
return singleRunFullClass(
- pojoCode = """
+ pojoCode = """
$HEADER
$pojoCode
$FOOTER
""",
- autoValuePojoCode = """
+ autoValuePojoCode = """
$AUTO_VALUE_HEADER
$autoValuePojoCode
$FOOTER
""",
- jfos = jfos,
- classpathFiles = classpathFiles,
- handler = handler
+ jfos = jfos,
+ classpathFiles = classpathFiles,
+ handler = handler
)
}
@@ -264,11 +268,13 @@
val all = (jfos.toList() + pojoJFO + autoValuePojoJFO).toTypedArray()
return simpleRun(*all, classpathFiles = classpathFiles) { invocation ->
handler.invoke(
- PojoProcessor.createFor(context = invocation.context,
- element = invocation.processingEnv.requireTypeElement(MY_POJO),
- bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
- parent = null).process(),
- invocation
+ PojoProcessor.createFor(
+ context = invocation.context,
+ element = invocation.processingEnv.requireTypeElement(MY_POJO),
+ bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR,
+ parent = null
+ ).process(),
+ invocation
)
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
index 43f7f21..4096f31 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/BasicColumnTypeAdaptersTest.kt
@@ -18,6 +18,7 @@
import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.writeTo
import androidx.room.processor.Context
import androidx.room.testing.TestInvocation
import com.squareup.javapoet.ClassName
@@ -93,7 +94,7 @@
} else {
st.bindString(6, inp);
}
- """.trimIndent(),
+ """.trimIndent(),
"out = crs.getString(9);"
)
)
@@ -123,7 +124,8 @@
)!!
adapter.bindToStmt("st", "6", "inp", scope)
assertThat(
- scope.generate().toString().trim(), `is`(
+ scope.generate().toString().trim(),
+ `is`(
"""
if (inp == null) {
st.bindNull(6);
@@ -151,7 +153,9 @@
.build()
)
.build()
- JavaFile.builder("foo.bar", spec).build().writeTo(invocation.processingEnv.filer)
+ JavaFile.builder("foo.bar", spec).build().writeTo(
+ invocation.processingEnv.filer
+ )
}
@Test
@@ -177,7 +181,8 @@
)!!
adapter.readFromCursor("out", "crs", "9", scope)
assertThat(
- scope.generate().toString().trim(), `is`(
+ scope.generate().toString().trim(),
+ `is`(
"""
if (crs.isNull(9)) {
out = null;
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/CustomTypeConverterResolutionTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/CustomTypeConverterResolutionTest.kt
index 69fe5b6..13b72c6 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/CustomTypeConverterResolutionTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/CustomTypeConverterResolutionTest.kt
@@ -51,8 +51,10 @@
@RunWith(JUnit4::class)
class CustomTypeConverterResolutionTest {
fun TypeSpec.toJFO(): JavaFileObject {
- return JavaFileObjects.forSourceString("foo.bar.${this.name}",
- "package foo.bar;\n" + toString())
+ return JavaFileObjects.forSourceString(
+ "foo.bar.${this.name}",
+ "package foo.bar;\n" + toString()
+ )
}
companion object {
@@ -61,17 +63,19 @@
val DAO = ClassName.get("foo.bar", "MyDao")
val CUSTOM_TYPE = ClassName.get("foo.bar", "CustomType")
- val CUSTOM_TYPE_JFO = JavaFileObjects.forSourceLines(CUSTOM_TYPE.toString(),
- """
+ val CUSTOM_TYPE_JFO = JavaFileObjects.forSourceLines(
+ CUSTOM_TYPE.toString(),
+ """
package ${CUSTOM_TYPE.packageName()};
public class ${CUSTOM_TYPE.simpleName()} {
public int value;
}
- """)
+ """
+ )
val CUSTOM_TYPE_CONVERTER = ClassName.get("foo.bar", "MyConverter")
val CUSTOM_TYPE_CONVERTER_JFO = JavaFileObjects.forSourceLines(
- CUSTOM_TYPE_CONVERTER.toString(),
- """
+ CUSTOM_TYPE_CONVERTER.toString(),
+ """
package ${CUSTOM_TYPE_CONVERTER.packageName()};
public class ${CUSTOM_TYPE_CONVERTER.simpleName()} {
@${TypeConverter::class.java.canonicalName}
@@ -83,13 +87,15 @@
return 0;
}
}
- """)
+ """
+ )
val CUSTOM_TYPE_SET = ParameterizedTypeName.get(
- ClassName.get(Set::class.java), CUSTOM_TYPE)
+ ClassName.get(Set::class.java), CUSTOM_TYPE
+ )
val CUSTOM_TYPE_SET_CONVERTER = ClassName.get("foo.bar", "MySetConverter")
val CUSTOM_TYPE_SET_CONVERTER_JFO = JavaFileObjects.forSourceLines(
- CUSTOM_TYPE_SET_CONVERTER.toString(),
- """
+ CUSTOM_TYPE_SET_CONVERTER.toString(),
+ """
package ${CUSTOM_TYPE_SET_CONVERTER.packageName()};
import java.util.HashSet;
import java.util.Set;
@@ -103,7 +109,8 @@
return 0;
}
}
- """)
+ """
+ )
}
@Test
@@ -117,30 +124,36 @@
@Test
fun collection_forEntity() {
val entity = createEntity(
- hasCustomField = true,
- useCollection = true)
+ hasCustomField = true,
+ useCollection = true
+ )
val database = createDatabase(
- hasConverters = true,
- hasDao = true,
- useCollection = true)
+ hasConverters = true,
+ hasDao = true,
+ useCollection = true
+ )
val dao = createDao(
- hasQueryWithCustomParam = false,
- useCollection = true)
+ hasQueryWithCustomParam = false,
+ useCollection = true
+ )
run(entity.toJFO(), dao.toJFO(), database.toJFO()).compilesWithoutError()
}
@Test
fun collection_forDao() {
val entity = createEntity(
- hasCustomField = true,
- useCollection = true)
+ hasCustomField = true,
+ useCollection = true
+ )
val database = createDatabase(
- hasConverters = true,
- hasDao = true,
- useCollection = true)
+ hasConverters = true,
+ hasDao = true,
+ useCollection = true
+ )
val dao = createDao(
- hasQueryWithCustomParam = true,
- useCollection = true)
+ hasQueryWithCustomParam = true,
+ useCollection = true
+ )
run(entity.toJFO(), dao.toJFO(), database.toJFO()).compilesWithoutError()
}
@@ -164,8 +177,10 @@
fun useFromDao_forQueryParameter() {
val entity = createEntity()
val database = createDatabase(hasDao = true)
- val dao = createDao(hasConverters = true, hasQueryReturningEntity = true,
- hasQueryWithCustomParam = true)
+ val dao = createDao(
+ hasConverters = true, hasQueryReturningEntity = true,
+ hasQueryWithCustomParam = true
+ )
run(entity.toJFO(), dao.toJFO(), database.toJFO()).compilesWithoutError()
}
@@ -191,7 +206,7 @@
val database = createDatabase(hasDao = true)
val dao = createDao(hasQueryWithCustomParam = true)
run(entity.toJFO(), dao.toJFO(), database.toJFO())
- .failsToCompile().withErrorContaining(CANNOT_BIND_QUERY_PARAMETER_INTO_STMT)
+ .failsToCompile().withErrorContaining(CANNOT_BIND_QUERY_PARAMETER_INTO_STMT)
}
@Test
@@ -200,7 +215,7 @@
val database = createDatabase(hasDao = true)
val dao = createDao(hasQueryWithCustomParam = true)
run(entity.toJFO(), dao.toJFO(), database.toJFO())
- .failsToCompile().withErrorContaining(CANNOT_BIND_QUERY_PARAMETER_INTO_STMT)
+ .failsToCompile().withErrorContaining(CANNOT_BIND_QUERY_PARAMETER_INTO_STMT)
}
@Test
@@ -221,9 +236,11 @@
fun run(vararg jfos: JavaFileObject): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(jfos.toList() + CUSTOM_TYPE_JFO + CUSTOM_TYPE_CONVERTER_JFO +
- CUSTOM_TYPE_SET_CONVERTER_JFO)
- .processedWith(RoomProcessor())
+ .that(
+ jfos.toList() + CUSTOM_TYPE_JFO + CUSTOM_TYPE_CONVERTER_JFO +
+ CUSTOM_TYPE_SET_CONVERTER_JFO
+ )
+ .processedWith(RoomProcessor())
}
private fun createEntity(
@@ -244,18 +261,22 @@
addAnnotation(Entity::class.java)
addModifiers(Modifier.PUBLIC)
if (hasCustomField) {
- addField(FieldSpec.builder(type, "myCustomField", Modifier.PUBLIC).apply {
- if (hasConverterOnField) {
- addAnnotation(createConvertersAnnotation())
- }
- }.build())
+ addField(
+ FieldSpec.builder(type, "myCustomField", Modifier.PUBLIC).apply {
+ if (hasConverterOnField) {
+ addAnnotation(createConvertersAnnotation())
+ }
+ }.build()
+ )
}
if (hasConverters) {
addAnnotation(createConvertersAnnotation())
}
- addField(FieldSpec.builder(TypeName.INT, "id", Modifier.PUBLIC).apply {
- addAnnotation(PrimaryKey::class.java)
- }.build())
+ addField(
+ FieldSpec.builder(TypeName.INT, "id", Modifier.PUBLIC).apply {
+ addAnnotation(PrimaryKey::class.java)
+ }.build()
+ )
}.build()
}
@@ -270,20 +291,24 @@
if (hasConverters) {
addAnnotation(createConvertersAnnotation(useCollection = useCollection))
}
- addField(FieldSpec.builder(TypeName.INT, "id", Modifier.PUBLIC).apply {
- addAnnotation(PrimaryKey::class.java)
- }.build())
+ addField(
+ FieldSpec.builder(TypeName.INT, "id", Modifier.PUBLIC).apply {
+ addAnnotation(PrimaryKey::class.java)
+ }.build()
+ )
if (hasDao) {
- addMethod(MethodSpec.methodBuilder("getDao").apply {
- addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
- returns(DAO)
- }.build())
+ addMethod(
+ MethodSpec.methodBuilder("getDao").apply {
+ addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
+ returns(DAO)
+ }.build()
+ )
}
addAnnotation(
- AnnotationSpec.builder(Database::class.java).apply {
- addMember("entities", "{$T.class}", ENTITY)
- addMember("version", "42")
- }.build()
+ AnnotationSpec.builder(Database::class.java).apply {
+ addMember("entities", "{$T.class}", ENTITY)
+ addMember("version", "42")
+ }.build()
)
}.build()
}
@@ -297,7 +322,7 @@
useCollection: Boolean = false
): TypeSpec {
val annotationCount = listOf(hasMethodConverters, hasConverters, hasParameterConverters)
- .map { if (it) 1 else 0 }.sum()
+ .map { if (it) 1 else 0 }.sum()
if (annotationCount > 1) {
throw IllegalArgumentException("cannot set both of these")
}
@@ -311,13 +336,21 @@
addAnnotation(createConvertersAnnotation(useCollection = useCollection))
}
if (hasQueryReturningEntity) {
- addMethod(MethodSpec.methodBuilder("loadAll").apply {
- addAnnotation(AnnotationSpec.builder(Query::class.java).apply {
- addMember("value", S, "SELECT * FROM ${ENTITY.simpleName()} LIMIT 1")
- }.build())
- addModifiers(Modifier.ABSTRACT)
- returns(ENTITY)
- }.build())
+ addMethod(
+ MethodSpec.methodBuilder("loadAll").apply {
+ addAnnotation(
+ AnnotationSpec.builder(Query::class.java).apply {
+ addMember(
+ "value",
+ S,
+ "SELECT * FROM ${ENTITY.simpleName()} LIMIT 1"
+ )
+ }.build()
+ )
+ addModifiers(Modifier.ABSTRACT)
+ returns(ENTITY)
+ }.build()
+ )
}
val customType = if (useCollection) {
CUSTOM_TYPE_SET
@@ -325,22 +358,33 @@
CUSTOM_TYPE
}
if (hasQueryWithCustomParam) {
- addMethod(MethodSpec.methodBuilder("queryWithCustom").apply {
- addAnnotation(AnnotationSpec.builder(Query::class.java).apply {
- addMember("value", S, "SELECT COUNT(*) FROM ${ENTITY.simpleName()} where" +
- " id = :custom")
- }.build())
- if (hasMethodConverters) {
- addAnnotation(createConvertersAnnotation(useCollection = useCollection))
- }
- addParameter(ParameterSpec.builder(customType, "custom").apply {
- if (hasParameterConverters) {
+ addMethod(
+ MethodSpec.methodBuilder("queryWithCustom").apply {
+ addAnnotation(
+ AnnotationSpec.builder(Query::class.java).apply {
+ addMember(
+ "value", S,
+ "SELECT COUNT(*) FROM ${ENTITY.simpleName()} where" +
+ " id = :custom"
+ )
+ }.build()
+ )
+ if (hasMethodConverters) {
addAnnotation(createConvertersAnnotation(useCollection = useCollection))
}
- }.build())
- addModifiers(Modifier.ABSTRACT)
- returns(TypeName.INT)
- }.build())
+ addParameter(
+ ParameterSpec.builder(customType, "custom").apply {
+ if (hasParameterConverters) {
+ addAnnotation(
+ createConvertersAnnotation(useCollection = useCollection)
+ )
+ }
+ }.build()
+ )
+ addModifiers(Modifier.ABSTRACT)
+ returns(TypeName.INT)
+ }.build()
+ )
}
}.build()
}
@@ -352,6 +396,6 @@
CUSTOM_TYPE_CONVERTER
}
return AnnotationSpec.builder(TypeConverters::class.java)
- .addMember("value", "$T.class", converter).build()
+ .addMember("value", "$T.class", converter).build()
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index 1d8b534..e520c12 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -85,16 +85,20 @@
singleRun { invocation ->
val store = TypeAdapterStore.create(Context(invocation.processingEnv))
val boolean = invocation
- .processingEnv
- .requireType("java.lang.Boolean")
+ .processingEnv
+ .requireType("java.lang.Boolean")
val adapter = store.findColumnTypeAdapter(boolean, null)
assertThat(adapter, notNullValue())
assertThat(adapter, instanceOf(CompositeAdapter::class.java))
val composite = adapter as CompositeAdapter
- assertThat(composite.intoStatementConverter?.from?.typeName,
- `is`(TypeName.BOOLEAN.box()))
- assertThat(composite.columnTypeAdapter.out.typeName,
- `is`(TypeName.INT.box()))
+ assertThat(
+ composite.intoStatementConverter?.from?.typeName,
+ `is`(TypeName.BOOLEAN.box())
+ )
+ assertThat(
+ composite.columnTypeAdapter.out.typeName,
+ `is`(TypeName.INT.box())
+ )
}.compilesWithoutError()
}
@@ -108,27 +112,39 @@
assertThat(adapter, instanceOf(CompositeAdapter::class.java))
val bindScope = testCodeGenScope()
adapter!!.bindToStmt("stmt", "41", "fooVar", bindScope)
- assertThat(bindScope.generate().toString().trim(), `is`("""
+ assertThat(
+ bindScope.generate().toString().trim(),
+ `is`(
+ """
final int ${tmp(0)};
${tmp(0)} = fooVar ? 1 : 0;
stmt.bindLong(41, ${tmp(0)});
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
val cursorScope = testCodeGenScope()
adapter.readFromCursor("res", "curs", "7", cursorScope)
- assertThat(cursorScope.generate().toString().trim(), `is`("""
+ assertThat(
+ cursorScope.generate().toString().trim(),
+ `is`(
+ """
final int ${tmp(0)};
${tmp(0)} = curs.getInt(7);
res = ${tmp(0)} != 0;
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@Test
fun testVia2TypeAdapters() {
singleRun { invocation ->
- val store = TypeAdapterStore.create(Context(invocation.processingEnv),
- pointTypeConverters(invocation.processingEnv))
+ val store = TypeAdapterStore.create(
+ Context(invocation.processingEnv),
+ pointTypeConverters(invocation.processingEnv)
+ )
val pointType = invocation.processingEnv.requireType("foo.bar.Point")
val adapter = store.findColumnTypeAdapter(pointType, null)
assertThat(adapter, notNullValue())
@@ -136,38 +152,53 @@
val bindScope = testCodeGenScope()
adapter!!.bindToStmt("stmt", "41", "fooVar", bindScope)
- assertThat(bindScope.generate().toString().trim(), `is`("""
+ assertThat(
+ bindScope.generate().toString().trim(),
+ `is`(
+ """
final int ${tmp(0)};
final boolean ${tmp(1)};
${tmp(1)} = foo.bar.Point.toBoolean(fooVar);
${tmp(0)} = ${tmp(1)} ? 1 : 0;
stmt.bindLong(41, ${tmp(0)});
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
val cursorScope = testCodeGenScope()
adapter.readFromCursor("res", "curs", "11", cursorScope).toString()
- assertThat(cursorScope.generate().toString().trim(), `is`("""
+ assertThat(
+ cursorScope.generate().toString().trim(),
+ `is`(
+ """
final int ${tmp(0)};
${tmp(0)} = curs.getInt(11);
final boolean ${tmp(1)};
${tmp(1)} = ${tmp(0)} != 0;
res = foo.bar.Point.fromBoolean(${tmp(1)});
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@Test
fun testDate() {
singleRun { (processingEnv) ->
- val store = TypeAdapterStore.create(Context(processingEnv),
- dateTypeConverters(processingEnv))
+ val store = TypeAdapterStore.create(
+ Context(processingEnv),
+ dateTypeConverters(processingEnv)
+ )
val tDate = processingEnv.requireType("java.util.Date")
val adapter = store.findCursorValueReader(tDate, SQLTypeAffinity.INTEGER)
assertThat(adapter, notNullValue())
assertThat(adapter?.typeMirror(), `is`(tDate))
val bindScope = testCodeGenScope()
adapter!!.readFromCursor("outDate", "curs", "0", bindScope)
- assertThat(bindScope.generate().toString().trim(), `is`("""
+ assertThat(
+ bindScope.generate().toString().trim(),
+ `is`(
+ """
final java.lang.Long _tmp;
if (curs.isNull(0)) {
_tmp = null;
@@ -175,7 +206,9 @@
_tmp = curs.getLong(0);
}
// convert Long to Date;
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@@ -183,15 +216,20 @@
fun testIntList() {
singleRun { invocation ->
val binders = createIntListToStringBinders(invocation)
- val store = TypeAdapterStore.create(Context(invocation.processingEnv), binders[0],
- binders[1])
+ val store = TypeAdapterStore.create(
+ Context(invocation.processingEnv), binders[0],
+ binders[1]
+ )
val adapter = store.findColumnTypeAdapter(binders[0].from, null)
assertThat(adapter, notNullValue())
val bindScope = testCodeGenScope()
adapter!!.bindToStmt("stmt", "41", "fooVar", bindScope)
- assertThat(bindScope.generate().toString().trim(), `is`("""
+ assertThat(
+ bindScope.generate().toString().trim(),
+ `is`(
+ """
final java.lang.String ${tmp(0)};
${tmp(0)} = androidx.room.util.StringUtil.joinIntoString(fooVar);
if (${tmp(0)} == null) {
@@ -199,10 +237,14 @@
} else {
stmt.bindString(41, ${tmp(0)});
}
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
- val converter = store.findTypeConverter(binders[0].from,
- invocation.context.COMMON_TYPES.STRING)
+ val converter = store.findTypeConverter(
+ binders[0].from,
+ invocation.context.COMMON_TYPES.STRING
+ )
assertThat(converter, notNullValue())
assertThat(store.reverse(converter!!), `is`(binders[1]))
}.compilesWithoutError()
@@ -219,8 +261,10 @@
val stmtBinder = store.findStatementValueBinder(binders[0].from, null)
assertThat(stmtBinder, notNullValue())
- val converter = store.findTypeConverter(binders[0].from,
- invocation.context.COMMON_TYPES.STRING)
+ val converter = store.findTypeConverter(
+ binders[0].from,
+ invocation.context.COMMON_TYPES.STRING
+ )
assertThat(converter, notNullValue())
assertThat(store.reverse(converter!!), nullValue())
}
@@ -230,12 +274,14 @@
fun testMissingRx2Room() {
simpleRun(jfos = arrayOf(COMMON.PUBLISHER, COMMON.RX2_FLOWABLE)) { invocation ->
val publisherElement = invocation.processingEnv
- .requireTypeElement(ReactiveStreamsTypeNames.PUBLISHER)
+ .requireTypeElement(ReactiveStreamsTypeNames.PUBLISHER)
assertThat(publisherElement, notNullValue())
assertThat(
RxQueryResultBinderProvider.getAll(invocation.context).any {
it.matches(publisherElement.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.failsToCompile().withErrorContaining(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
}
@@ -248,7 +294,9 @@
assertThat(
RxQueryResultBinderProvider.getAll(invocation.context).any {
it.matches(publisherElement.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.failsToCompile().withErrorContaining(ProcessorErrors.MISSING_ROOM_RXJAVA3_ARTIFACT)
}
@@ -259,14 +307,16 @@
COMMON.RX3_FLOWABLE to COMMON.RX3_ROOM
).forEach { (rxTypeSrc, rxRoomSrc) ->
simpleRun(jfos = arrayOf(COMMON.PUBLISHER, rxTypeSrc, rxRoomSrc)) {
- invocation ->
+ invocation ->
val publisher = invocation.processingEnv
.requireTypeElement(ReactiveStreamsTypeNames.PUBLISHER)
assertThat(publisher, notNullValue())
assertThat(
RxQueryResultBinderProvider.getAll(invocation.context).any {
it.matches(publisher.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.compilesWithoutError()
}
}
@@ -283,7 +333,9 @@
assertThat(
RxQueryResultBinderProvider.getAll(invocation.context).any {
it.matches(flowable.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.compilesWithoutError()
}
}
@@ -301,7 +353,9 @@
assertThat(
RxQueryResultBinderProvider.getAll(invocation.context).any {
it.matches(observable.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.compilesWithoutError()
}
}
@@ -319,7 +373,9 @@
assertThat(
RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
it.matches(single.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.compilesWithoutError()
}
}
@@ -336,7 +392,9 @@
assertThat(
RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
it.matches(maybe.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.compilesWithoutError()
}
}
@@ -353,7 +411,9 @@
assertThat(
RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
it.matches(completable.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.compilesWithoutError()
}
}
@@ -361,11 +421,15 @@
@Test
fun testFindInsertListenableFuture() {
simpleRun(jfos = arrayOf(COMMON.LISTENABLE_FUTURE)) {
- invocation ->
+ invocation ->
val future = invocation.processingEnv
.requireTypeElement(GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE)
- assertThat(GuavaListenableFutureInsertMethodBinderProvider(invocation.context).matches(
- future.asDeclaredType()), `is`(true))
+ assertThat(
+ GuavaListenableFutureInsertMethodBinderProvider(invocation.context).matches(
+ future.asDeclaredType()
+ ),
+ `is`(true)
+ )
}.compilesWithoutError()
}
@@ -378,7 +442,9 @@
assertThat(
RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
it.matches(single.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.compilesWithoutError()
}
@@ -391,7 +457,9 @@
assertThat(
RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
it.matches(maybe.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.compilesWithoutError()
}
@@ -400,24 +468,29 @@
simpleRun(jfos = arrayOf(COMMON.RX2_COMPLETABLE)) {
invocation ->
val completable = invocation.processingEnv
- .requireTypeElement(RxJava2TypeNames.COMPLETABLE)
+ .requireTypeElement(RxJava2TypeNames.COMPLETABLE)
assertThat(completable, notNullValue())
assertThat(
RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
it.matches(completable.asDeclaredType())
- }, `is`(true))
+ },
+ `is`(true)
+ )
}.compilesWithoutError()
}
@Test
fun testFindDeleteOrUpdateListenableFuture() {
simpleRun(jfos = arrayOf(COMMON.LISTENABLE_FUTURE)) {
- invocation ->
+ invocation ->
val future = invocation.processingEnv
.requireTypeElement(GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE)
assertThat(future, notNullValue())
- assertThat(GuavaListenableFutureDeleteOrUpdateMethodBinderProvider(invocation.context)
- .matches(future.asDeclaredType()), `is`(true))
+ assertThat(
+ GuavaListenableFutureDeleteOrUpdateMethodBinderProvider(invocation.context)
+ .matches(future.asDeclaredType()),
+ `is`(true)
+ )
}.compilesWithoutError()
}
@@ -426,10 +499,14 @@
simpleRun(jfos = arrayOf(COMMON.COMPUTABLE_LIVE_DATA, COMMON.LIVE_DATA)) {
invocation ->
val liveData = invocation.processingEnv
- .requireTypeElement(LifecyclesTypeNames.LIVE_DATA)
+ .requireTypeElement(LifecyclesTypeNames.LIVE_DATA)
assertThat(liveData, notNullValue())
- assertThat(LiveDataQueryResultBinderProvider(invocation.context).matches(
- liveData.asDeclaredType()), `is`(true))
+ assertThat(
+ LiveDataQueryResultBinderProvider(invocation.context).matches(
+ liveData.asDeclaredType()
+ ),
+ `is`(true)
+ )
}.compilesWithoutError()
}
@@ -443,8 +520,11 @@
.getDeclaredType(pagingSourceElement, intType, intType)
assertThat(pagingSourceIntIntType, notNullValue())
- assertThat(PagingSourceQueryResultBinderProvider(invocation.context)
- .matches(pagingSourceIntIntType.asDeclaredType()), `is`(true))
+ assertThat(
+ PagingSourceQueryResultBinderProvider(invocation.context)
+ .matches(pagingSourceIntIntType.asDeclaredType()),
+ `is`(true)
+ )
}
}
@@ -458,8 +538,11 @@
.getDeclaredType(pagingSourceElement, stringType, stringType)
assertThat(pagingSourceIntIntType, notNullValue())
- assertThat(PagingSourceQueryResultBinderProvider(invocation.context)
- .matches(pagingSourceIntIntType.asDeclaredType()), `is`(true))
+ assertThat(
+ PagingSourceQueryResultBinderProvider(invocation.context)
+ .matches(pagingSourceIntIntType.asDeclaredType()),
+ `is`(true)
+ )
}.failsToCompile().withErrorContaining(ProcessorErrors.PAGING_SPECIFY_PAGING_SOURCE_TYPE)
}
@@ -469,8 +552,12 @@
invocation ->
val dataSource = invocation.processingEnv.requireTypeElement(DataSource::class)
assertThat(dataSource, notNullValue())
- assertThat(DataSourceQueryResultBinderProvider(invocation.context).matches(
- dataSource.asDeclaredType()), `is`(true))
+ assertThat(
+ DataSourceQueryResultBinderProvider(invocation.context).matches(
+ dataSource.asDeclaredType()
+ ),
+ `is`(true)
+ )
}.failsToCompile().withErrorContaining(ProcessorErrors.PAGING_SPECIFY_DATA_SOURCE_TYPE)
}
@@ -482,8 +569,12 @@
val dataSource = invocation.processingEnv
.requireTypeElement(androidx.paging.PositionalDataSource::class)
assertThat(dataSource, notNullValue())
- assertThat(DataSourceQueryResultBinderProvider(invocation.context).matches(
- dataSource.asDeclaredType()), `is`(true))
+ assertThat(
+ DataSourceQueryResultBinderProvider(invocation.context).matches(
+ dataSource.asDeclaredType()
+ ),
+ `is`(true)
+ )
}.compilesWithoutError()
}
@@ -492,10 +583,14 @@
simpleRun(jfos = arrayOf(COMMON.DATA_SOURCE_FACTORY)) {
invocation ->
val pagedListProvider = invocation.processingEnv
- .requireTypeElement(PagingTypeNames.DATA_SOURCE_FACTORY)
+ .requireTypeElement(PagingTypeNames.DATA_SOURCE_FACTORY)
assertThat(pagedListProvider, notNullValue())
- assertThat(DataSourceFactoryQueryResultBinderProvider(invocation.context).matches(
- pagedListProvider.asDeclaredType()), `is`(true))
+ assertThat(
+ DataSourceFactoryQueryResultBinderProvider(invocation.context).matches(
+ pagedListProvider.asDeclaredType()
+ ),
+ `is`(true)
+ )
}.compilesWithoutError()
}
@@ -504,30 +599,37 @@
val listElement = invocation.processingEnv.requireTypeElement(java.util.List::class)
val listOfInts = invocation.processingEnv.getDeclaredType(listElement, intType)
- val intListConverter = object : TypeConverter(listOfInts,
- invocation.context.COMMON_TYPES.STRING) {
+ val intListConverter = object : TypeConverter(
+ listOfInts,
+ invocation.context.COMMON_TYPES.STRING
+ ) {
override fun convert(
inputVarName: String,
outputVarName: String,
scope: CodeGenScope
) {
scope.builder().apply {
- addStatement("$L = $T.joinIntoString($L)", outputVarName, STRING_UTIL,
- inputVarName)
+ addStatement(
+ "$L = $T.joinIntoString($L)", outputVarName, STRING_UTIL,
+ inputVarName
+ )
}
}
}
val stringToIntListConverter = object : TypeConverter(
- invocation.context.COMMON_TYPES.STRING, listOfInts) {
+ invocation.context.COMMON_TYPES.STRING, listOfInts
+ ) {
override fun convert(
inputVarName: String,
outputVarName: String,
scope: CodeGenScope
) {
scope.builder().apply {
- addStatement("$L = $T.splitToIntList($L)", outputVarName, STRING_UTIL,
- inputVarName)
+ addStatement(
+ "$L = $T.splitToIntList($L)", outputVarName, STRING_UTIL,
+ inputVarName
+ )
}
}
}
@@ -536,14 +638,19 @@
fun singleRun(handler: (TestInvocation) -> Unit): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(listOf(JavaFileObjects.forSourceString("foo.bar.DummyClass",
+ .that(
+ listOf(
+ JavaFileObjects.forSourceString(
+ "foo.bar.DummyClass",
"""
package foo.bar;
import androidx.room.*;
@Entity
public class DummyClass {}
"""
- ), JavaFileObjects.forSourceString("foo.bar.Point",
+ ),
+ JavaFileObjects.forSourceString(
+ "foo.bar.Point",
"""
package foo.bar;
import androidx.room.*;
@@ -562,44 +669,52 @@
}
}
"""
- )))
- .processedWith(TestProcessor.builder()
- .forAnnotations(Entity::class)
- .nextRunHandler { invocation ->
- handler(invocation)
- true
- }
- .build())
+ )
+ )
+ )
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(Entity::class)
+ .nextRunHandler { invocation ->
+ handler(invocation)
+ true
+ }
+ .build()
+ )
}
fun pointTypeConverters(env: XProcessingEnv): List<TypeConverter> {
val tPoint = env.requireType("foo.bar.Point")
val tBoolean = env.requireType(TypeName.BOOLEAN)
return listOf(
- object : TypeConverter(tPoint, tBoolean) {
- override fun convert(
- inputVarName: String,
- outputVarName: String,
- scope: CodeGenScope
- ) {
- scope.builder().apply {
- addStatement("$L = $T.toBoolean($L)", outputVarName, from.typeName,
- inputVarName)
- }
- }
- },
- object : TypeConverter(tBoolean, tPoint) {
- override fun convert(
- inputVarName: String,
- outputVarName: String,
- scope: CodeGenScope
- ) {
- scope.builder().apply {
- addStatement("$L = $T.fromBoolean($L)", outputVarName, tPoint.typeName,
- inputVarName)
- }
+ object : TypeConverter(tPoint, tBoolean) {
+ override fun convert(
+ inputVarName: String,
+ outputVarName: String,
+ scope: CodeGenScope
+ ) {
+ scope.builder().apply {
+ addStatement(
+ "$L = $T.toBoolean($L)", outputVarName, from.typeName,
+ inputVarName
+ )
}
}
+ },
+ object : TypeConverter(tBoolean, tPoint) {
+ override fun convert(
+ inputVarName: String,
+ outputVarName: String,
+ scope: CodeGenScope
+ ) {
+ scope.builder().apply {
+ addStatement(
+ "$L = $T.fromBoolean($L)", outputVarName, tPoint.typeName,
+ inputVarName
+ )
+ }
+ }
+ }
)
}
@@ -607,28 +722,28 @@
val tDate = env.requireType("java.util.Date")
val tLong = env.requireType("java.lang.Long")
return listOf(
- object : TypeConverter(tDate, tLong) {
- override fun convert(
- inputVarName: String,
- outputVarName: String,
- scope: CodeGenScope
- ) {
- scope.builder().apply {
- addStatement("// convert Date to Long")
- }
- }
- },
- object : TypeConverter(tLong, tDate) {
- override fun convert(
- inputVarName: String,
- outputVarName: String,
- scope: CodeGenScope
- ) {
- scope.builder().apply {
- addStatement("// convert Long to Date")
- }
+ object : TypeConverter(tDate, tLong) {
+ override fun convert(
+ inputVarName: String,
+ outputVarName: String,
+ scope: CodeGenScope
+ ) {
+ scope.builder().apply {
+ addStatement("// convert Date to Long")
}
}
+ },
+ object : TypeConverter(tLong, tDate) {
+ override fun convert(
+ inputVarName: String,
+ outputVarName: String,
+ scope: CodeGenScope
+ ) {
+ scope.builder().apply {
+ addStatement("// convert Long to Date")
+ }
+ }
+ }
)
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt
index 75f3edd..adefbd9 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAssignmentTest.kt
@@ -27,8 +27,9 @@
class TypeAssignmentTest {
companion object {
- private val TEST_OBJECT = JavaFileObjects.forSourceString("foo.bar.MyObject",
- """
+ private val TEST_OBJECT = JavaFileObjects.forSourceString(
+ "foo.bar.MyObject",
+ """
package foo.bar;
import java.util.Set;
import java.util.HashSet;
@@ -42,7 +43,8 @@
Map<String, ?> mUnboundedMap;
Map<String, String> mStringMap;
}
- """.trimIndent())
+ """.trimIndent()
+ )
}
@Test
@@ -51,9 +53,11 @@
val testObject = processingEnv.requireTypeElement("foo.bar.MyObject")
val string = testObject.getField("mString")
val integer = testObject.getField("mInteger")
- assertThat( integer.type
- .isAssignableFromWithoutVariance(string.type),
- `is`(false))
+ assertThat(
+ integer.type
+ .isAssignableFromWithoutVariance(string.type),
+ `is`(false)
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/query/QueryWriterTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/query/QueryWriterTest.kt
index 0634281..21b26a5 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/query/QueryWriterTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/query/QueryWriterTest.kt
@@ -51,28 +51,39 @@
@Test
fun simpleNoArgQuery() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users")
abstract java.util.List<Integer> selectAllIds();
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
- assertThat(scope.generate().toString().trim(), `is`("""
+ assertThat(
+ scope.generate().toString().trim(),
+ `is`(
+ """
final java.lang.String _sql = "SELECT id FROM users";
final $QUERY _stmt = $QUERY.acquire(_sql, 0);
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@Test
fun simpleStringArgs() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users WHERE name LIKE :name")
abstract java.util.List<Integer> selectAllIds(String name);
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
- assertThat(scope.generate().toString().trim(), `is`(
+ assertThat(
+ scope.generate().toString().trim(),
+ `is`(
"""
final java.lang.String _sql = "SELECT id FROM users WHERE name LIKE ?";
final $QUERY _stmt = $QUERY.acquire(_sql, 1);
@@ -82,19 +93,25 @@
} else {
_stmt.bindString(_argIndex, name);
}
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@Test
fun twoIntArgs() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users WHERE id IN(:id1,:id2)")
abstract java.util.List<Integer> selectAllIds(int id1, int id2);
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
- assertThat(scope.generate().toString().trim(), `is`(
+ assertThat(
+ scope.generate().toString().trim(),
+ `is`(
"""
final java.lang.String _sql = "SELECT id FROM users WHERE id IN(?,?)";
final $QUERY _stmt = $QUERY.acquire(_sql, 2);
@@ -102,19 +119,25 @@
_stmt.bindLong(_argIndex, id1);
_argIndex = 2;
_stmt.bindLong(_argIndex, id2);
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@Test
fun aLongAndIntVarArg() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users WHERE id IN(:ids) AND age > :time")
abstract java.util.List<Integer> selectAllIds(long time, int... ids);
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
- assertThat(scope.generate().toString().trim(), `is`(
+ assertThat(
+ scope.generate().toString().trim(),
+ `is`(
"""
java.lang.StringBuilder _stringBuilder = $STRING_UTIL.newStringBuilder();
_stringBuilder.append("SELECT id FROM users WHERE id IN(");
@@ -132,7 +155,9 @@
}
_argIndex = 1 + _inputSize;
_stmt.bindLong(_argIndex, time);
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@@ -157,14 +182,16 @@
}
_argIndex = 1 + _inputSize;
_stmt.bindLong(_argIndex, time);
- """.trimIndent()
+ """.trimIndent()
@Test
fun aLongAndIntegerList() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users WHERE id IN(:ids) AND age > :time")
abstract List<Integer> selectAllIds(long time, List<Integer> ids);
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
assertThat(scope.generate().toString().trim(), `is`(collectionOut))
@@ -173,10 +200,12 @@
@Test
fun aLongAndIntegerImmutableList() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users WHERE id IN(:ids) AND age > :time")
abstract ImmutableList<Integer> selectAllIds(long time, List<Integer> ids);
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
assertThat(scope.generate().toString().trim(), `is`(collectionOut))
@@ -185,10 +214,12 @@
@Test
fun aLongAndIntegerSet() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users WHERE id IN(:ids) AND age > :time")
abstract List<Integer> selectAllIds(long time, Set<Integer> ids);
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
assertThat(scope.generate().toString().trim(), `is`(collectionOut))
@@ -197,32 +228,44 @@
@Test
fun testMultipleBindParamsWithSameName() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users WHERE age > :age OR bage > :age")
abstract List<Integer> selectAllIds(int age);
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
- assertThat(scope.generate().toString().trim(), `is`("""
+ assertThat(
+ scope.generate().toString().trim(),
+ `is`(
+ """
final java.lang.String _sql = "SELECT id FROM users WHERE age > ? OR bage > ?";
final $QUERY _stmt = $QUERY.acquire(_sql, 2);
int _argIndex = 1;
_stmt.bindLong(_argIndex, age);
_argIndex = 2;
_stmt.bindLong(_argIndex, age);
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@Test
fun testMultipleBindParamsWithSameNameWithVarArg() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users WHERE age > :age OR bage > :age OR fage IN(:ages)")
abstract List<Integer> selectAllIds(int age, int... ages);
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
- assertThat(scope.generate().toString().trim(), `is`("""
+ assertThat(
+ scope.generate().toString().trim(),
+ `is`(
+ """
java.lang.StringBuilder _stringBuilder = $STRING_UTIL.newStringBuilder();
_stringBuilder.append("SELECT id FROM users WHERE age > ");
_stringBuilder.append("?");
@@ -244,19 +287,26 @@
_stmt.bindLong(_argIndex, _item);
_argIndex ++;
}
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@Test
fun testMultipleBindParamsWithSameNameWithVarArgInTwoBindings() {
- singleQueryMethod("""
+ singleQueryMethod(
+ """
@Query("SELECT id FROM users WHERE age IN (:ages) OR bage > :age OR fage IN(:ages)")
abstract List<Integer> selectAllIds(int age, int... ages);
- """) { writer ->
+ """
+ ) { writer ->
val scope = testCodeGenScope()
writer.prepareReadAndBind("_sql", "_stmt", scope)
- assertThat(scope.generate().toString().trim(), `is`("""
+ assertThat(
+ scope.generate().toString().trim(),
+ `is`(
+ """
java.lang.StringBuilder _stringBuilder = $STRING_UTIL.newStringBuilder();
_stringBuilder.append("SELECT id FROM users WHERE age IN (");
final int _inputSize = ages.length;
@@ -282,7 +332,9 @@
_stmt.bindLong(_argIndex, _item_1);
_argIndex ++;
}
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
}.compilesWithoutError()
}
@@ -291,29 +343,36 @@
handler: (QueryWriter) -> Unit
): CompileTester {
return Truth.assertAbout(JavaSourceSubjectFactory.javaSource())
- .that(JavaFileObjects.forSourceString("foo.bar.MyClass",
- DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
- ))
- .processedWith(TestProcessor.builder()
- .forAnnotations(Query::class, Dao::class)
- .nextRunHandler { invocation ->
- val (owner, methods) = invocation.roundEnv
- .getElementsAnnotatedWith(Dao::class.java)
- .map {
- Pair(it,
- it.asTypeElement().getAllMethods().filter {
- it.hasAnnotation(Query::class)
- }
- )
- }.first { it.second.isNotEmpty() }
- val parser = QueryMethodProcessor(
- baseContext = invocation.context,
- containing = owner.asDeclaredType(),
- executableElement = methods.first())
- val method = parser.process()
- handler(QueryWriter(method))
- true
- }
- .build())
+ .that(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyClass",
+ DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
+ )
+ )
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(Query::class, Dao::class)
+ .nextRunHandler { invocation ->
+ val (owner, methods) = invocation.roundEnv
+ .getElementsAnnotatedWith(Dao::class.java)
+ .map {
+ Pair(
+ it,
+ it.asTypeElement().getAllMethods().filter {
+ it.hasAnnotation(Query::class)
+ }
+ )
+ }.first { it.second.isNotEmpty() }
+ val parser = QueryMethodProcessor(
+ baseContext = invocation.context,
+ containing = owner.asDeclaredType(),
+ executableElement = methods.first()
+ )
+ val method = parser.process()
+ handler(QueryWriter(method))
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/testing/InProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/testing/InProcessorTest.kt
index d9904cb..2d00be6 100644
--- a/room/compiler/src/test/kotlin/androidx/room/testing/InProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/testing/InProcessorTest.kt
@@ -33,23 +33,29 @@
fun testInProcessorTestRuns() {
val didRun = AtomicBoolean(false)
Truth.assertAbout(JavaSourceSubjectFactory.javaSource())
- .that(JavaFileObjects.forSourceString("foo.bar.MyClass",
- """
+ .that(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyClass",
+ """
package foo.bar;
abstract public class MyClass {
@androidx.room.Query("foo")
abstract public void setFoo(String foo);
}
- """))
- .processedWith(TestProcessor.builder()
- .nextRunHandler { invocation ->
- didRun.set(true)
- assertThat(invocation.annotations.size, `is`(1))
- true
- }
- .forAnnotations(Query::class)
- .build())
- .compilesWithoutError()
+ """
+ )
+ )
+ .processedWith(
+ TestProcessor.builder()
+ .nextRunHandler { invocation ->
+ didRun.set(true)
+ assertThat(invocation.annotations.size, `is`(1))
+ true
+ }
+ .forAnnotations(Query::class)
+ .build()
+ )
+ .compilesWithoutError()
assertThat(didRun.get(), `is`(true))
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/testing/TestProcessor.kt b/room/compiler/src/test/kotlin/androidx/room/testing/TestProcessor.kt
index d9a3cea..d34a020 100644
--- a/room/compiler/src/test/kotlin/androidx/room/testing/TestProcessor.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/testing/TestProcessor.kt
@@ -30,7 +30,8 @@
var count = 0
override fun doProcess(annotations: Set<XTypeElement>, roundEnv: XRoundEnv): Boolean {
return handlers.getOrNull(count++)?.invoke(
- TestInvocation(xProcessingEnv, annotations, roundEnv)) ?: true
+ TestInvocation(xProcessingEnv, annotations, roundEnv)
+ ) ?: true
}
override fun getSupportedSourceVersion(): SourceVersion {
diff --git a/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt b/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt
index 6976a76..b186bff 100644
--- a/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt
@@ -93,32 +93,46 @@
loadJavaCode("common/input/LiveData.java", LifecyclesTypeNames.LIVE_DATA.toString())
}
val COMPUTABLE_LIVE_DATA by lazy {
- loadJavaCode("common/input/ComputableLiveData.java",
- LifecyclesTypeNames.COMPUTABLE_LIVE_DATA.toString())
+ loadJavaCode(
+ "common/input/ComputableLiveData.java",
+ LifecyclesTypeNames.COMPUTABLE_LIVE_DATA.toString()
+ )
}
val PUBLISHER by lazy {
- loadJavaCode("common/input/reactivestreams/Publisher.java",
- ReactiveStreamsTypeNames.PUBLISHER.toString())
+ loadJavaCode(
+ "common/input/reactivestreams/Publisher.java",
+ ReactiveStreamsTypeNames.PUBLISHER.toString()
+ )
}
val RX2_FLOWABLE by lazy {
- loadJavaCode("common/input/rxjava2/Flowable.java",
- RxJava2TypeNames.FLOWABLE.toString())
+ loadJavaCode(
+ "common/input/rxjava2/Flowable.java",
+ RxJava2TypeNames.FLOWABLE.toString()
+ )
}
val RX2_OBSERVABLE by lazy {
- loadJavaCode("common/input/rxjava2/Observable.java",
- RxJava2TypeNames.OBSERVABLE.toString())
+ loadJavaCode(
+ "common/input/rxjava2/Observable.java",
+ RxJava2TypeNames.OBSERVABLE.toString()
+ )
}
val RX2_SINGLE by lazy {
- loadJavaCode("common/input/rxjava2/Single.java",
- RxJava2TypeNames.SINGLE.toString())
+ loadJavaCode(
+ "common/input/rxjava2/Single.java",
+ RxJava2TypeNames.SINGLE.toString()
+ )
}
val RX2_MAYBE by lazy {
- loadJavaCode("common/input/rxjava2/Maybe.java",
- RxJava2TypeNames.MAYBE.toString())
+ loadJavaCode(
+ "common/input/rxjava2/Maybe.java",
+ RxJava2TypeNames.MAYBE.toString()
+ )
}
val RX2_COMPLETABLE by lazy {
- loadJavaCode("common/input/rxjava2/Completable.java",
- RxJava2TypeNames.COMPLETABLE.toString())
+ loadJavaCode(
+ "common/input/rxjava2/Completable.java",
+ RxJava2TypeNames.COMPLETABLE.toString()
+ )
}
val RX2_ROOM by lazy {
@@ -126,24 +140,34 @@
}
val RX3_FLOWABLE by lazy {
- loadJavaCode("common/input/rxjava3/Flowable.java",
- RxJava3TypeNames.FLOWABLE.toString())
+ loadJavaCode(
+ "common/input/rxjava3/Flowable.java",
+ RxJava3TypeNames.FLOWABLE.toString()
+ )
}
val RX3_OBSERVABLE by lazy {
- loadJavaCode("common/input/rxjava3/Observable.java",
- RxJava3TypeNames.OBSERVABLE.toString())
+ loadJavaCode(
+ "common/input/rxjava3/Observable.java",
+ RxJava3TypeNames.OBSERVABLE.toString()
+ )
}
val RX3_SINGLE by lazy {
- loadJavaCode("common/input/rxjava3/Single.java",
- RxJava3TypeNames.SINGLE.toString())
+ loadJavaCode(
+ "common/input/rxjava3/Single.java",
+ RxJava3TypeNames.SINGLE.toString()
+ )
}
val RX3_MAYBE by lazy {
- loadJavaCode("common/input/rxjava3/Maybe.java",
- RxJava3TypeNames.MAYBE.toString())
+ loadJavaCode(
+ "common/input/rxjava3/Maybe.java",
+ RxJava3TypeNames.MAYBE.toString()
+ )
}
val RX3_COMPLETABLE by lazy {
- loadJavaCode("common/input/rxjava3/Completable.java",
- RxJava3TypeNames.COMPLETABLE.toString())
+ loadJavaCode(
+ "common/input/rxjava3/Completable.java",
+ RxJava3TypeNames.COMPLETABLE.toString()
+ )
}
val RX3_ROOM by lazy {
@@ -155,33 +179,45 @@
}
val POSITIONAL_DATA_SOURCE by lazy {
- loadJavaCode("common/input/PositionalDataSource.java",
- PagingTypeNames.POSITIONAL_DATA_SOURCE.toString())
+ loadJavaCode(
+ "common/input/PositionalDataSource.java",
+ PagingTypeNames.POSITIONAL_DATA_SOURCE.toString()
+ )
}
val LISTENABLE_FUTURE by lazy {
- loadJavaCode("common/input/guava/ListenableFuture.java",
- GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE.toString())
+ loadJavaCode(
+ "common/input/guava/ListenableFuture.java",
+ GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE.toString()
+ )
}
val GUAVA_ROOM by lazy {
- loadJavaCode("common/input/GuavaRoom.java",
- RoomGuavaTypeNames.GUAVA_ROOM.toString())
+ loadJavaCode(
+ "common/input/GuavaRoom.java",
+ RoomGuavaTypeNames.GUAVA_ROOM.toString()
+ )
}
val CHANNEL by lazy {
- loadJavaCode("common/input/coroutines/Channel.java",
- KotlinTypeNames.CHANNEL.toString())
+ loadJavaCode(
+ "common/input/coroutines/Channel.java",
+ KotlinTypeNames.CHANNEL.toString()
+ )
}
val SEND_CHANNEL by lazy {
- loadJavaCode("common/input/coroutines/SendChannel.java",
- KotlinTypeNames.SEND_CHANNEL.toString())
+ loadJavaCode(
+ "common/input/coroutines/SendChannel.java",
+ KotlinTypeNames.SEND_CHANNEL.toString()
+ )
}
val RECEIVE_CHANNEL by lazy {
- loadJavaCode("common/input/coroutines/ReceiveChannel.java",
- KotlinTypeNames.RECEIVE_CHANNEL.toString())
+ loadJavaCode(
+ "common/input/coroutines/ReceiveChannel.java",
+ KotlinTypeNames.RECEIVE_CHANNEL.toString()
+ )
}
}
fun testCodeGenScope(): CodeGenScope {
@@ -195,20 +231,22 @@
f: (TestInvocation) -> Unit
): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(jfos.toList() + JavaFileObjects.forSourceLines("NoOp", "final class NoOp {}"))
- .apply {
- if (classpathFiles.isNotEmpty()) {
- withClasspath(classpathFiles)
- }
+ .that(jfos.toList() + JavaFileObjects.forSourceLines("NoOp", "final class NoOp {}"))
+ .apply {
+ if (classpathFiles.isNotEmpty()) {
+ withClasspath(classpathFiles)
}
- .withCompilerOptions(options)
- .processedWith(TestProcessor.builder()
- .nextRunHandler {
- f(it)
- true
- }
- .forAnnotations("*")
- .build())
+ }
+ .withCompilerOptions(options)
+ .processedWith(
+ TestProcessor.builder()
+ .nextRunHandler {
+ f(it)
+ true
+ }
+ .forAnnotations("*")
+ .build()
+ )
}
fun loadJavaCode(fileName: String, qName: String): JavaFileObject {
@@ -217,8 +255,10 @@
}
fun createVerifierFromEntitiesAndViews(invocation: TestInvocation): DatabaseVerifier {
- return DatabaseVerifier.create(invocation.context, mock(XElement::class.java),
- invocation.getEntities(), invocation.getViews())!!
+ return DatabaseVerifier.create(
+ invocation.context, mock(XElement::class.java),
+ invocation.getEntities(), invocation.getViews()
+ )!!
}
fun TestInvocation.getViews(): List<androidx.room.vo.DatabaseView> {
diff --git a/room/compiler/src/test/kotlin/androidx/room/util/SimpleJavaVersionTest.kt b/room/compiler/src/test/kotlin/androidx/room/util/SimpleJavaVersionTest.kt
index 33fd70b..830aeba 100644
--- a/room/compiler/src/test/kotlin/androidx/room/util/SimpleJavaVersionTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/util/SimpleJavaVersionTest.kt
@@ -26,15 +26,15 @@
assert(SimpleJavaVersion.tryParse("11.0.1+13-LTS") == SimpleJavaVersion(11, 0, null))
assert(
SimpleJavaVersion.tryParse("11.0.6+10-post-Ubuntu-1ubuntu118.04.1")
- == SimpleJavaVersion(11, 0, null)
+ == SimpleJavaVersion(11, 0, null)
)
assert(
SimpleJavaVersion.tryParse("1.8.0_202-release-1483-b39-5396753")
- == SimpleJavaVersion(8, 0, 202)
+ == SimpleJavaVersion(8, 0, 202)
)
assert(
SimpleJavaVersion.tryParse("1.8.0_181-google-v7-238857965-238857965")
- == SimpleJavaVersion(8, 0, 181)
+ == SimpleJavaVersion(8, 0, 181)
)
assert(SimpleJavaVersion.tryParse("a.b.c") == null)
}
@@ -44,15 +44,15 @@
assert(SimpleJavaVersion.parse("11.0.1+13-LTS") == SimpleJavaVersion(11, 0, null))
assert(
SimpleJavaVersion.parse("11.0.6+10-post-Ubuntu-1ubuntu118.04.1")
- == SimpleJavaVersion(11, 0, null)
+ == SimpleJavaVersion(11, 0, null)
)
assert(
SimpleJavaVersion.parse("1.8.0_202-release-1483-b39-5396753")
- == SimpleJavaVersion(8, 0, 202)
+ == SimpleJavaVersion(8, 0, 202)
)
assert(
SimpleJavaVersion.parse("1.8.0_181-google-v7-238857965-238857965")
- == SimpleJavaVersion(8, 0, 181)
+ == SimpleJavaVersion(8, 0, 181)
)
try {
SimpleJavaVersion.parse("a.b.c")
diff --git a/room/compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt b/room/compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt
index d4e059a..c8adabe 100644
--- a/room/compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/verifier/DatabaseVerifierTest.kt
@@ -62,7 +62,8 @@
val stmt = verifier.connection.createStatement()
val rs = stmt.executeQuery("select * from sqlite_master WHERE type='table'")
assertThat(
- rs.collect { set -> set.getString("name") }, hasItem(`is`("User")))
+ rs.collect { set -> set.getString("name") }, hasItem(`is`("User"))
+ )
val table = verifier.connection.prepareStatement("select * from User")
assertThat(table.columnNames(), `is`(listOf("id", "name", "lastName", "ratio")))
@@ -72,76 +73,114 @@
private fun createVerifier(invocation: TestInvocation): DatabaseVerifier {
val db = userDb(invocation)
- return DatabaseVerifier.create(invocation.context, mock(XElement::class.java),
- db.entities, db.views)!!
+ return DatabaseVerifier.create(
+ invocation.context, mock(XElement::class.java),
+ db.entities, db.views
+ )!!
}
@Test
fun testFullEntityQuery() {
validQueryTest("select * from User") {
- assertThat(it, `is`(
- QueryResultInfo(listOf(
+ assertThat(
+ it,
+ `is`(
+ QueryResultInfo(
+ listOf(
ColumnInfo("id", SQLTypeAffinity.INTEGER),
ColumnInfo("name", SQLTypeAffinity.TEXT),
ColumnInfo("lastName", SQLTypeAffinity.TEXT),
ColumnInfo("ratio", SQLTypeAffinity.REAL)
- ))))
+ )
+ )
+ )
+ )
}
}
@Test
fun testPartialFields() {
validQueryTest("select id, lastName from User") {
- assertThat(it, `is`(
- QueryResultInfo(listOf(
+ assertThat(
+ it,
+ `is`(
+ QueryResultInfo(
+ listOf(
ColumnInfo("id", SQLTypeAffinity.INTEGER),
ColumnInfo("lastName", SQLTypeAffinity.TEXT)
- ))))
+ )
+ )
+ )
+ )
}
}
@Test
fun testRenamedField() {
validQueryTest("select id as myId, lastName from User") {
- assertThat(it, `is`(
- QueryResultInfo(listOf(
+ assertThat(
+ it,
+ `is`(
+ QueryResultInfo(
+ listOf(
ColumnInfo("myId", SQLTypeAffinity.INTEGER),
ColumnInfo("lastName", SQLTypeAffinity.TEXT)
- ))))
+ )
+ )
+ )
+ )
}
}
@Test
fun testGrouped() {
validQueryTest("select MAX(ratio) from User GROUP BY name") {
- assertThat(it, `is`(
- QueryResultInfo(listOf(
+ assertThat(
+ it,
+ `is`(
+ QueryResultInfo(
+ listOf(
// unfortunately, we don't get this information
ColumnInfo("MAX(ratio)", SQLTypeAffinity.NULL)
- ))))
+ )
+ )
+ )
+ )
}
}
@Test
fun testConcat() {
validQueryTest("select name || lastName as mergedName from User") {
- assertThat(it, `is`(
- QueryResultInfo(listOf(
+ assertThat(
+ it,
+ `is`(
+ QueryResultInfo(
+ listOf(
// unfortunately, we don't get this information
ColumnInfo("mergedName", SQLTypeAffinity.NULL)
- ))))
+ )
+ )
+ )
+ )
}
}
@Test
fun testResultWithArgs() {
validQueryTest("select id, name || lastName as mergedName from User where name LIKE ?") {
- assertThat(it, `is`(
- QueryResultInfo(listOf(
+ assertThat(
+ it,
+ `is`(
+ QueryResultInfo(
+ listOf(
// unfortunately, we don't get this information
ColumnInfo("id", SQLTypeAffinity.INTEGER),
ColumnInfo("mergedName", SQLTypeAffinity.NULL)
- ))))
+ )
+ )
+ )
+ )
}
}
@@ -171,12 +210,18 @@
@Test
fun testCollate() {
validQueryTest("SELECT id, name FROM user ORDER BY name COLLATE LOCALIZED ASC") {
- assertThat(it, `is`(
- QueryResultInfo(listOf(
+ assertThat(
+ it,
+ `is`(
+ QueryResultInfo(
+ listOf(
// unfortunately, we don't get this information
ColumnInfo("id", SQLTypeAffinity.INTEGER),
ColumnInfo("name", SQLTypeAffinity.TEXT)
- ))))
+ )
+ )
+ )
+ )
}
}
@@ -185,7 +230,8 @@
simpleRun { invocation ->
val verifier = createVerifier(invocation)
val (_, error) = verifier.analyze(
- "SELECT id, name FROM user ORDER BY name COLLATE LOCALIZEDASC")
+ "SELECT id, name FROM user ORDER BY name COLLATE LOCALIZEDASC"
+ )
assertThat(error, notNullValue())
}.compilesWithoutError()
}
@@ -193,12 +239,17 @@
@Test
fun testFullViewQuery() {
validQueryTest("select * from UserSummary") {
- assertThat(it, `is`(
- QueryResultInfo(listOf(
+ assertThat(
+ it,
+ `is`(
+ QueryResultInfo(
+ listOf(
ColumnInfo("id", SQLTypeAffinity.INTEGER),
ColumnInfo("name", SQLTypeAffinity.TEXT)
- ))
- ))
+ )
+ )
+ )
+ )
}
}
@@ -207,7 +258,8 @@
simpleRun { invocation ->
val verifier = createVerifier(invocation)
val (_, error) = verifier.analyze(
- "SELECT ratio FROM UserSummary")
+ "SELECT ratio FROM UserSummary"
+ )
assertThat(error, notNullValue())
assertThat(error?.message, containsString("no such column: ratio"))
}.compilesWithoutError()
@@ -274,14 +326,15 @@
private fun database(entities: List<Entity>, views: List<DatabaseView>): Database {
return Database(
- element = mock(XTypeElement::class.java),
- type = mock(XType::class.java),
- entities = entities,
- views = views,
- daoMethods = emptyList(),
- version = -1,
- exportSchema = false,
- enableForeignKeys = false)
+ element = mock(XTypeElement::class.java),
+ type = mock(XType::class.java),
+ entities = entities,
+ views = views,
+ daoMethods = emptyList(),
+ version = -1,
+ exportSchema = false,
+ enableForeignKeys = false
+ )
}
private fun entity(
@@ -306,13 +359,13 @@
private fun view(viewName: String, query: String, vararg fields: Field): DatabaseView {
return DatabaseView(
- element = mock(XTypeElement::class.java),
- viewName = viewName,
- type = mock(XDeclaredType::class.java),
- fields = fields.toList(),
- embeddedFields = emptyList(),
- query = SqlParser.parse(query),
- constructor = Constructor(mock(XConstructorElement::class.java), emptyList())
+ element = mock(XTypeElement::class.java),
+ viewName = viewName,
+ type = mock(XDeclaredType::class.java),
+ fields = fields.toList(),
+ embeddedFields = emptyList(),
+ query = SqlParser.parse(query),
+ constructor = Constructor(mock(XConstructorElement::class.java), emptyList())
)
}
@@ -356,9 +409,9 @@
return resultSet.collect {
Pair(it.getString("name"), it.getInt("pk"))
}
- .filter { it.second > 0 }
- .sortedBy { it.second }
- .map { it.first }
+ .filter { it.second > 0 }
+ .sortedBy { it.second }
+ .map { it.first }
}
companion object {
diff --git a/room/compiler/src/test/kotlin/androidx/room/vo/DatabaseTest.kt b/room/compiler/src/test/kotlin/androidx/room/vo/DatabaseTest.kt
index 34b0b0a..550fe3c 100644
--- a/room/compiler/src/test/kotlin/androidx/room/vo/DatabaseTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/vo/DatabaseTest.kt
@@ -48,11 +48,13 @@
Index(
name = "leIndex",
unique = false,
- fields = Fields()),
+ fields = Fields()
+ ),
Index(
name = "leIndex2",
unique = true,
- fields = Fields())
+ fields = Fields()
+ )
),
foreignKeys = emptyList(),
constructor = Constructor(mock(XConstructorElement::class.java), emptyList()),
@@ -68,8 +70,9 @@
val expectedLegacyHash = DigestUtils.md5Hex(
"CREATE TABLE IF NOT EXISTS `TheTable` ()¯\\_(ツ)_/¯" +
- "CREATE INDEX `leIndex` ON `TheTable` ()¯\\_(ツ)_/¯" +
- "CREATE UNIQUE INDEX `leIndex2` ON `TheTable` ()")
+ "CREATE INDEX `leIndex` ON `TheTable` ()¯\\_(ツ)_/¯" +
+ "CREATE UNIQUE INDEX `leIndex2` ON `TheTable` ()"
+ )
assertEquals(expectedLegacyHash, database.legacyIdentityHash)
}
}
\ No newline at end of file
diff --git a/room/compiler/src/test/kotlin/androidx/room/vo/EntityTest.kt b/room/compiler/src/test/kotlin/androidx/room/vo/EntityTest.kt
index 15756e7..192026d 100644
--- a/room/compiler/src/test/kotlin/androidx/room/vo/EntityTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/vo/EntityTest.kt
@@ -32,7 +32,9 @@
@Test
fun shouldBeDeletedAfter() {
- val child = createEntity("Child", listOf(
+ val child = createEntity(
+ "Child",
+ listOf(
createForeignKey("NoAction", ForeignKeyAction.NO_ACTION, false),
createForeignKey("NoActionDeferred", ForeignKeyAction.NO_ACTION, true),
createForeignKey("Restrict", ForeignKeyAction.RESTRICT, false),
@@ -42,7 +44,9 @@
createForeignKey("SetDefault", ForeignKeyAction.SET_DEFAULT, false),
createForeignKey("SetDefaultDeferred", ForeignKeyAction.SET_DEFAULT, true),
createForeignKey("Cascade", ForeignKeyAction.CASCADE, false),
- createForeignKey("CascadeDeferred", ForeignKeyAction.CASCADE, true)))
+ createForeignKey("CascadeDeferred", ForeignKeyAction.CASCADE, true)
+ )
+ )
val noAction = createEntity("NoAction")
val noActionDeferred = createEntity("NoActionDeferred")
val restrict = createEntity("Restrict")
@@ -72,16 +76,17 @@
foreignKeys: List<ForeignKey> = emptyList()
): Entity {
return Entity(
- element = mock(XTypeElement::class.java),
- tableName = tableName,
- type = mock(XDeclaredType::class.java),
- fields = emptyList(),
- embeddedFields = emptyList(),
- primaryKey = PrimaryKey(mock(XElement::class.java), Fields(), false),
- indices = emptyList(),
- foreignKeys = foreignKeys,
- constructor = Constructor(mock(XConstructorElement::class.java), emptyList()),
- shadowTableName = null)
+ element = mock(XTypeElement::class.java),
+ tableName = tableName,
+ type = mock(XDeclaredType::class.java),
+ fields = emptyList(),
+ embeddedFields = emptyList(),
+ primaryKey = PrimaryKey(mock(XElement::class.java), Fields(), false),
+ indices = emptyList(),
+ foreignKeys = foreignKeys,
+ constructor = Constructor(mock(XConstructorElement::class.java), emptyList()),
+ shadowTableName = null
+ )
}
private fun createForeignKey(
@@ -90,11 +95,12 @@
deferred: Boolean
): ForeignKey {
return ForeignKey(
- parentTable = parentTable,
- parentColumns = emptyList(),
- childFields = emptyList(),
- onDelete = onDelete,
- onUpdate = ForeignKeyAction.NO_ACTION,
- deferred = deferred)
+ parentTable = parentTable,
+ parentColumns = emptyList(),
+ childFields = emptyList(),
+ onDelete = onDelete,
+ onUpdate = ForeignKeyAction.NO_ACTION,
+ deferred = deferred
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/vo/FtsEntityTest.kt b/room/compiler/src/test/kotlin/androidx/room/vo/FtsEntityTest.kt
index 6efc50e..0aa8d97 100644
--- a/room/compiler/src/test/kotlin/androidx/room/vo/FtsEntityTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/vo/FtsEntityTest.kt
@@ -39,43 +39,50 @@
val dontIndexMe1Field = createField("dontIndexMe1")
val dontIndexMe2Field = createField("dontIndexMe2")
val entity = FtsEntity(
- element = mock(XTypeElement::class.java),
- tableName = "Mail",
- type = mock(XDeclaredType::class.java),
- fields = listOf(primaryKeyField, bodyField, languageIdField, dontIndexMe1Field,
- dontIndexMe2Field),
- embeddedFields = emptyList(),
- primaryKey = PrimaryKey(
- declaredIn = mock(XElement::class.java),
- fields = Fields(primaryKeyField),
- autoGenerateId = true),
- constructor = null,
- shadowTableName = "Mail_context",
- ftsVersion = FtsVersion.FTS4,
- ftsOptions = FtsOptions(
- tokenizer = androidx.room.FtsOptions.TOKENIZER_PORTER,
- tokenizerArgs = emptyList(),
- contentEntity = null,
- languageIdColumnName = "lid",
- matchInfo = androidx.room.FtsOptions.MatchInfo.FTS3,
- notIndexedColumns = listOf("dontIndexMe1", "dontIndexMe2"),
- prefixSizes = listOf(2, 4),
- preferredOrder = androidx.room.FtsOptions.Order.DESC))
+ element = mock(XTypeElement::class.java),
+ tableName = "Mail",
+ type = mock(XDeclaredType::class.java),
+ fields = listOf(
+ primaryKeyField, bodyField, languageIdField, dontIndexMe1Field,
+ dontIndexMe2Field
+ ),
+ embeddedFields = emptyList(),
+ primaryKey = PrimaryKey(
+ declaredIn = mock(XElement::class.java),
+ fields = Fields(primaryKeyField),
+ autoGenerateId = true
+ ),
+ constructor = null,
+ shadowTableName = "Mail_context",
+ ftsVersion = FtsVersion.FTS4,
+ ftsOptions = FtsOptions(
+ tokenizer = androidx.room.FtsOptions.TOKENIZER_PORTER,
+ tokenizerArgs = emptyList(),
+ contentEntity = null,
+ languageIdColumnName = "lid",
+ matchInfo = androidx.room.FtsOptions.MatchInfo.FTS3,
+ notIndexedColumns = listOf("dontIndexMe1", "dontIndexMe2"),
+ prefixSizes = listOf(2, 4),
+ preferredOrder = androidx.room.FtsOptions.Order.DESC
+ )
+ )
- assertThat(entity.createTableQuery,
- `is`("CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
- "`body` TEXT, " +
- "`dontIndexMe1` TEXT, " +
- "`dontIndexMe2` TEXT, " +
- "tokenize=porter, " +
- "languageid=`lid`, " +
- "matchinfo=fts3, " +
- "notindexed=`dontIndexMe1`, " +
- "notindexed=`dontIndexMe2`, " +
- "prefix=`2,4`, " +
- "order=DESC" +
- ")"
- )
+ assertThat(
+ entity.createTableQuery,
+ `is`(
+ "CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
+ "`body` TEXT, " +
+ "`dontIndexMe1` TEXT, " +
+ "`dontIndexMe2` TEXT, " +
+ "tokenize=porter, " +
+ "languageid=`lid`, " +
+ "matchinfo=fts3, " +
+ "notindexed=`dontIndexMe1`, " +
+ "notindexed=`dontIndexMe2`, " +
+ "prefix=`2,4`, " +
+ "order=DESC" +
+ ")"
+ )
)
}
@@ -92,7 +99,8 @@
primaryKey = PrimaryKey(
declaredIn = mock(XElement::class.java),
fields = Fields(primaryKeyField),
- autoGenerateId = true),
+ autoGenerateId = true
+ ),
constructor = null,
shadowTableName = "Mail_context",
ftsVersion = FtsVersion.FTS4,
@@ -104,10 +112,14 @@
matchInfo = androidx.room.FtsOptions.MatchInfo.FTS4,
notIndexedColumns = emptyList(),
prefixSizes = emptyList(),
- preferredOrder = androidx.room.FtsOptions.Order.ASC))
+ preferredOrder = androidx.room.FtsOptions.Order.ASC
+ )
+ )
- assertThat(entity.createTableQuery,
- `is`("CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
+ assertThat(
+ entity.createTableQuery,
+ `is`(
+ "CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
"`body` TEXT, " +
"tokenize=simple `tokenchars=.=` `separators=X`" +
")"
@@ -128,7 +140,8 @@
primaryKey = PrimaryKey(
declaredIn = mock(XElement::class.java),
fields = Fields(primaryKeyField),
- autoGenerateId = true),
+ autoGenerateId = true
+ ),
constructor = null,
shadowTableName = "Mail_context",
ftsVersion = FtsVersion.FTS4,
@@ -140,10 +153,14 @@
matchInfo = androidx.room.FtsOptions.MatchInfo.FTS4,
notIndexedColumns = emptyList(),
prefixSizes = emptyList(),
- preferredOrder = androidx.room.FtsOptions.Order.ASC))
+ preferredOrder = androidx.room.FtsOptions.Order.ASC
+ )
+ )
- assertThat(entity.createTableQuery,
- `is`("CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
+ assertThat(
+ entity.createTableQuery,
+ `is`(
+ "CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
"`body` TEXT" +
")"
)
@@ -163,7 +180,8 @@
primaryKey = PrimaryKey(
declaredIn = mock(XElement::class.java),
fields = Fields(primaryKeyField),
- autoGenerateId = true),
+ autoGenerateId = true
+ ),
constructor = null,
shadowTableName = "Mail_context",
ftsVersion = FtsVersion.FTS4,
@@ -175,10 +193,14 @@
matchInfo = androidx.room.FtsOptions.MatchInfo.FTS4,
notIndexedColumns = emptyList(),
prefixSizes = emptyList(),
- preferredOrder = androidx.room.FtsOptions.Order.ASC))
+ preferredOrder = androidx.room.FtsOptions.Order.ASC
+ )
+ )
- assertThat(entity.createTableQuery,
- `is`("CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
+ assertThat(
+ entity.createTableQuery,
+ `is`(
+ "CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
"`body` TEXT, " +
"tokenize=porter `tokenchars=.=` `separators=X`" +
")"
@@ -199,7 +221,8 @@
primaryKey = PrimaryKey(
declaredIn = mock(XElement::class.java),
fields = Fields(primaryKeyField),
- autoGenerateId = true),
+ autoGenerateId = true
+ ),
constructor = null,
shadowTableName = "Mail_context",
ftsVersion = FtsVersion.FTS4,
@@ -211,10 +234,14 @@
matchInfo = androidx.room.FtsOptions.MatchInfo.FTS4,
notIndexedColumns = emptyList(),
prefixSizes = emptyList(),
- preferredOrder = androidx.room.FtsOptions.Order.ASC))
+ preferredOrder = androidx.room.FtsOptions.Order.ASC
+ )
+ )
- assertThat(entity.createTableQuery,
- `is`("CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
+ assertThat(
+ entity.createTableQuery,
+ `is`(
+ "CREATE VIRTUAL TABLE IF NOT EXISTS `Mail` USING FTS4(" +
"`body` TEXT, " +
"tokenize=porter" +
")"
@@ -225,11 +252,12 @@
fun createField(name: String): Field {
val (element, type) = mockElementAndType()
return Field(
- element = element,
- name = name,
- type = type,
- affinity = null,
- collate = null,
- columnName = name)
+ element = element,
+ name = name,
+ type = type,
+ affinity = null,
+ collate = null,
+ columnName = name
+ )
}
}
\ No newline at end of file
diff --git a/room/compiler/src/test/kotlin/androidx/room/vo/IndexTest.kt b/room/compiler/src/test/kotlin/androidx/room/vo/IndexTest.kt
index 0034a37..248b681 100644
--- a/room/compiler/src/test/kotlin/androidx/room/vo/IndexTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/vo/IndexTest.kt
@@ -29,27 +29,33 @@
@Test
fun createSimpleSQL() {
val index = Index("foo", false, listOf(mockField("bar"), mockField("baz")))
- MatcherAssert.assertThat(index.createQuery("my_table"), CoreMatchers.`is`(
+ MatcherAssert.assertThat(
+ index.createQuery("my_table"),
+ CoreMatchers.`is`(
"CREATE INDEX IF NOT EXISTS `foo` ON `my_table` (`bar`, `baz`)"
- ))
+ )
+ )
}
@Test
fun createUnique() {
val index = Index("foo", true, listOf(mockField("bar"), mockField("baz")))
- MatcherAssert.assertThat(index.createQuery("my_table"), CoreMatchers.`is`(
+ MatcherAssert.assertThat(
+ index.createQuery("my_table"),
+ CoreMatchers.`is`(
"CREATE UNIQUE INDEX IF NOT EXISTS `foo` ON `my_table` (`bar`, `baz`)"
- ))
+ )
+ )
}
private fun mockField(columnName: String): Field {
val (element, type) = mockElementAndType()
return Field(
- element = element,
- name = columnName + "_field",
- affinity = SQLTypeAffinity.TEXT,
- type = type,
- columnName = columnName
+ element = element,
+ name = columnName + "_field",
+ affinity = SQLTypeAffinity.TEXT,
+ type = type,
+ columnName = columnName
)
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt b/room/compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt
index 0397a3f..f835074 100644
--- a/room/compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt
@@ -36,11 +36,13 @@
@Test
fun complexDao() {
singleDao(
- loadJavaCode("databasewriter/input/ComplexDatabase.java",
- "foo.bar.ComplexDatabase"),
- loadJavaCode("daoWriter/input/ComplexDao.java", "foo.bar.ComplexDao")
+ loadJavaCode(
+ "databasewriter/input/ComplexDatabase.java",
+ "foo.bar.ComplexDatabase"
+ ),
+ loadJavaCode("daoWriter/input/ComplexDao.java", "foo.bar.ComplexDao")
).compilesWithoutError().and().generatesSources(
- loadJavaCode("daoWriter/output/ComplexDao.java", "foo.bar.ComplexDao_Impl")
+ loadJavaCode("daoWriter/output/ComplexDao.java", "foo.bar.ComplexDao_Impl")
)
}
@@ -58,61 +60,68 @@
@Test
fun writerDao() {
singleDao(
- loadJavaCode("daoWriter/input/WriterDao.java", "foo.bar.WriterDao")
+ loadJavaCode("daoWriter/input/WriterDao.java", "foo.bar.WriterDao")
).compilesWithoutError().and().generatesSources(
- loadJavaCode("daoWriter/output/WriterDao.java", "foo.bar.WriterDao_Impl")
+ loadJavaCode("daoWriter/output/WriterDao.java", "foo.bar.WriterDao_Impl")
)
}
@Test
fun deletionDao() {
singleDao(
- loadJavaCode("daoWriter/input/DeletionDao.java", "foo.bar.DeletionDao")
+ loadJavaCode("daoWriter/input/DeletionDao.java", "foo.bar.DeletionDao")
).compilesWithoutError().and().generatesSources(
- loadJavaCode("daoWriter/output/DeletionDao.java", "foo.bar.DeletionDao_Impl")
+ loadJavaCode("daoWriter/output/DeletionDao.java", "foo.bar.DeletionDao_Impl")
)
}
@Test
fun updateDao() {
singleDao(
- loadJavaCode("daoWriter/input/UpdateDao.java", "foo.bar.UpdateDao")
+ loadJavaCode("daoWriter/input/UpdateDao.java", "foo.bar.UpdateDao")
).compilesWithoutError().and().generatesSources(
- loadJavaCode("daoWriter/output/UpdateDao.java", "foo.bar.UpdateDao_Impl")
+ loadJavaCode("daoWriter/output/UpdateDao.java", "foo.bar.UpdateDao_Impl")
)
}
private fun singleDao(vararg jfo: JavaFileObject): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(jfo.toList() + COMMON.USER + COMMON.MULTI_PKEY_ENTITY + COMMON.BOOK +
- COMMON.LIVE_DATA + COMMON.COMPUTABLE_LIVE_DATA + COMMON.RX2_SINGLE +
- COMMON.RX2_MAYBE + COMMON.RX2_COMPLETABLE + COMMON.USER_SUMMARY +
- COMMON.RX2_ROOM + COMMON.PARENT + COMMON.CHILD1 + COMMON.CHILD2 +
- COMMON.INFO + COMMON.LISTENABLE_FUTURE + COMMON.GUAVA_ROOM)
- .processedWith(TestProcessor.builder()
- .forAnnotations(androidx.room.Dao::class)
- .nextRunHandler { invocation ->
- val dao = invocation.roundEnv
- .getElementsAnnotatedWith(
- androidx.room.Dao::class.java)
- .first()
- val db = invocation.roundEnv
- .getElementsAnnotatedWith(
- androidx.room.Database::class.java)
- .firstOrNull()
- ?: invocation.context.processingEnv
- .requireTypeElement(RoomTypeNames.ROOM_DB)
- val dbType = db.asDeclaredType()
- val parser = DaoProcessor(
- baseContext = invocation.context,
- element = dao.asTypeElement(),
- dbType = dbType,
- dbVerifier = createVerifierFromEntitiesAndViews(invocation))
- val parsedDao = parser.process()
- DaoWriter(parsedDao, db, invocation.processingEnv)
- .write(invocation.processingEnv)
- true
- }
- .build())
+ .that(
+ jfo.toList() + COMMON.USER + COMMON.MULTI_PKEY_ENTITY + COMMON.BOOK +
+ COMMON.LIVE_DATA + COMMON.COMPUTABLE_LIVE_DATA + COMMON.RX2_SINGLE +
+ COMMON.RX2_MAYBE + COMMON.RX2_COMPLETABLE + COMMON.USER_SUMMARY +
+ COMMON.RX2_ROOM + COMMON.PARENT + COMMON.CHILD1 + COMMON.CHILD2 +
+ COMMON.INFO + COMMON.LISTENABLE_FUTURE + COMMON.GUAVA_ROOM
+ )
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(androidx.room.Dao::class)
+ .nextRunHandler { invocation ->
+ val dao = invocation.roundEnv
+ .getElementsAnnotatedWith(
+ androidx.room.Dao::class.java
+ )
+ .first()
+ val db = invocation.roundEnv
+ .getElementsAnnotatedWith(
+ androidx.room.Database::class.java
+ )
+ .firstOrNull()
+ ?: invocation.context.processingEnv
+ .requireTypeElement(RoomTypeNames.ROOM_DB)
+ val dbType = db.asDeclaredType()
+ val parser = DaoProcessor(
+ baseContext = invocation.context,
+ element = dao.asTypeElement(),
+ dbType = dbType,
+ dbVerifier = createVerifierFromEntitiesAndViews(invocation)
+ )
+ val parsedDao = parser.process()
+ DaoWriter(parsedDao, db, invocation.processingEnv)
+ .write(invocation.processingEnv)
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/writer/DatabaseWriterTest.kt b/room/compiler/src/test/kotlin/androidx/room/writer/DatabaseWriterTest.kt
index 45f646c..2ab8515 100644
--- a/room/compiler/src/test/kotlin/androidx/room/writer/DatabaseWriterTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/writer/DatabaseWriterTest.kt
@@ -37,13 +37,19 @@
@Test
fun testCompileAndVerifySources() {
singleDb(
- loadJavaCode("databasewriter/input/ComplexDatabase.java",
- "foo.bar.ComplexDatabase"),
- loadJavaCode("daoWriter/input/ComplexDao.java",
- "foo.bar.ComplexDao")
+ loadJavaCode(
+ "databasewriter/input/ComplexDatabase.java",
+ "foo.bar.ComplexDatabase"
+ ),
+ loadJavaCode(
+ "daoWriter/input/ComplexDao.java",
+ "foo.bar.ComplexDao"
+ )
).compilesWithoutError().and().generatesSources(
- loadJavaCode("databasewriter/output/ComplexDatabase.java",
- "foo.bar.ComplexDatabase_Impl")
+ loadJavaCode(
+ "databasewriter/output/ComplexDatabase.java",
+ "foo.bar.ComplexDatabase_Impl"
+ )
)
}
}
@@ -60,16 +66,19 @@
while (statementCount < maxStatementCount) {
val entityValues = StringBuilder().apply {
for (i in 1..valuesPerEntity) {
- append("""
+ append(
+ """
private String value$i;
public String getValue$i() { return this.value$i; }
public void setValue$i(String value) { this.value$i = value; }
- """)
+ """
+ )
}
}
- val entitySource = JavaFileObjects.forSourceLines("foo.bar.Entity$entityCount",
- """
+ val entitySource = JavaFileObjects.forSourceLines(
+ "foo.bar.Entity$entityCount",
+ """
package foo.bar;
import androidx.room.*;
@@ -85,23 +94,26 @@
$entityValues
}
- """)
+ """
+ )
entitySources.add("Entity$entityCount" to entitySource)
statementCount += valuesPerEntity
entityCount++
}
val entityClasses = entitySources.joinToString { "${it.first}.class" }
- val dbSource = JavaFileObjects.forSourceLines("foo.bar.TestDatabase",
- """
+ val dbSource = JavaFileObjects.forSourceLines(
+ "foo.bar.TestDatabase",
+ """
package foo.bar;
import androidx.room.*;
@Database(entities = {$entityClasses}, version = 1)
public abstract class TestDatabase extends RoomDatabase {}
- """)
+ """
+ )
singleDb(*(listOf(dbSource) + entitySources.map { it.second }).toTypedArray())
- .compilesWithoutError()
+ .compilesWithoutError()
}
companion object {
@@ -122,8 +134,10 @@
private fun singleDb(vararg jfo: JavaFileObject): CompileTester {
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(jfo.toList() + COMMON.USER + COMMON.USER_SUMMARY + COMMON.LIVE_DATA +
- COMMON.COMPUTABLE_LIVE_DATA + COMMON.PARENT + COMMON.CHILD1 + COMMON.CHILD2 +
- COMMON.INFO + COMMON.GUAVA_ROOM + COMMON.LISTENABLE_FUTURE)
- .processedWith(RoomProcessor())
+ .that(
+ jfo.toList() + COMMON.USER + COMMON.USER_SUMMARY + COMMON.LIVE_DATA +
+ COMMON.COMPUTABLE_LIVE_DATA + COMMON.PARENT + COMMON.CHILD1 + COMMON.CHILD2 +
+ COMMON.INFO + COMMON.GUAVA_ROOM + COMMON.LISTENABLE_FUTURE
+ )
+ .processedWith(RoomProcessor())
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt b/room/compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt
index 7eae18a..185e79f 100644
--- a/room/compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt
@@ -37,14 +37,14 @@
@Generated("androidx.room.RoomProcessor")
@SuppressWarnings({"unchecked", "deprecation"})
public class MyContainerClass {
- """.trimIndent()
+ """.trimIndent()
const val OUT_SUFFIX = "}"
}
@Test
fun generateSimple() {
generateAndMatch(
- """
+ """
@PrimaryKey
private int id;
String name;
@@ -53,7 +53,7 @@
public int getId() { return id; }
public void setId(int id) { this.id = id; }
""",
- """
+ """
private MyEntity __entityCursorConverter_fooBarMyEntity(Cursor cursor) {
final MyEntity _entity;
final int _cursorIndexOfId = cursor.getColumnIndex("id");
@@ -77,7 +77,8 @@
}
return _entity;
}
- """.trimIndent())
+ """.trimIndent()
+ )
}
fun generateAndMatch(
@@ -86,11 +87,14 @@
attributes: Map<String, String> = mapOf()
) {
generate(input, attributes)
- .compilesWithoutError()
- .and()
- .generatesSources(JavaFileObjects.forSourceString(
- "foo.bar.MyEntity_CursorConverter",
- listOf(OUT_PREFIX, output, OUT_SUFFIX).joinToString("\n")))
+ .compilesWithoutError()
+ .and()
+ .generatesSources(
+ JavaFileObjects.forSourceString(
+ "foo.bar.MyEntity_CursorConverter",
+ listOf(OUT_PREFIX, output, OUT_SUFFIX).joinToString("\n")
+ )
+ )
}
fun generate(input: String, attributes: Map<String, String> = mapOf()): CompileTester {
diff --git a/room/compiler/src/test/kotlin/androidx/room/writer/SQLiteOpenHelperWriterTest.kt b/room/compiler/src/test/kotlin/androidx/room/writer/SQLiteOpenHelperWriterTest.kt
index 72cfd81..c1dbb7a 100644
--- a/room/compiler/src/test/kotlin/androidx/room/writer/SQLiteOpenHelperWriterTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/writer/SQLiteOpenHelperWriterTest.kt
@@ -50,38 +50,49 @@
@Test
fun createSimpleEntity() {
singleEntity(
- """
+ """
@PrimaryKey
@NonNull
String uuid;
String name;
int age;
- """.trimIndent()
+ """.trimIndent()
) { database, _ ->
val query = SQLiteOpenHelperWriter(database)
- .createTableQuery(database.entities.first())
- assertThat(query, `is`("CREATE TABLE IF NOT EXISTS" +
- " `MyEntity` (`uuid` TEXT NOT NULL, `name` TEXT, `age` INTEGER NOT NULL," +
- " PRIMARY KEY(`uuid`))"))
+ .createTableQuery(database.entities.first())
+ assertThat(
+ query,
+ `is`(
+ "CREATE TABLE IF NOT EXISTS" +
+ " `MyEntity` (`uuid` TEXT NOT NULL, `name` TEXT, `age` INTEGER NOT NULL," +
+ " PRIMARY KEY(`uuid`))"
+ )
+ )
}.compilesWithoutError()
}
@Test
fun multiplePrimaryKeys() {
singleEntity(
- """
+ """
@NonNull
String uuid;
@NonNull
String name;
int age;
- """.trimIndent(), attributes = mapOf("primaryKeys" to "{\"uuid\", \"name\"}")
+ """.trimIndent(),
+ attributes = mapOf("primaryKeys" to "{\"uuid\", \"name\"}")
) { database, _ ->
val query = SQLiteOpenHelperWriter(database)
- .createTableQuery(database.entities.first())
- assertThat(query, `is`("CREATE TABLE IF NOT EXISTS" +
- " `MyEntity` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, " +
- "`age` INTEGER NOT NULL, PRIMARY KEY(`uuid`, `name`))"))
+ .createTableQuery(database.entities.first())
+ assertThat(
+ query,
+ `is`(
+ "CREATE TABLE IF NOT EXISTS" +
+ " `MyEntity` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, " +
+ "`age` INTEGER NOT NULL, PRIMARY KEY(`uuid`, `name`))"
+ )
+ )
}.compilesWithoutError()
}
@@ -89,7 +100,7 @@
fun autoIncrementObject() {
listOf("Long", "Integer").forEach { type ->
singleEntity(
- """
+ """
@PrimaryKey(autoGenerate = true)
$type uuid;
String name;
@@ -97,10 +108,15 @@
""".trimIndent()
) { database, _ ->
val query = SQLiteOpenHelperWriter(database)
- .createTableQuery(database.entities.first())
- assertThat(query, `is`("CREATE TABLE IF NOT EXISTS" +
- " `MyEntity` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT," +
- " `name` TEXT, `age` INTEGER NOT NULL)"))
+ .createTableQuery(database.entities.first())
+ assertThat(
+ query,
+ `is`(
+ "CREATE TABLE IF NOT EXISTS" +
+ " `MyEntity` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT," +
+ " `name` TEXT, `age` INTEGER NOT NULL)"
+ )
+ )
}.compilesWithoutError()
}
}
@@ -109,7 +125,7 @@
fun autoIncrementPrimitives() {
listOf("long", "int").forEach { type ->
singleEntity(
- """
+ """
@PrimaryKey(autoGenerate = true)
$type uuid;
String name;
@@ -117,10 +133,15 @@
""".trimIndent()
) { database, _ ->
val query = SQLiteOpenHelperWriter(database)
- .createTableQuery(database.entities.first())
- assertThat(query, `is`("CREATE TABLE IF NOT EXISTS" +
- " `MyEntity` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
- " `name` TEXT, `age` INTEGER NOT NULL)"))
+ .createTableQuery(database.entities.first())
+ assertThat(
+ query,
+ `is`(
+ "CREATE TABLE IF NOT EXISTS" +
+ " `MyEntity` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
+ " `name` TEXT, `age` INTEGER NOT NULL)"
+ )
+ )
}.compilesWithoutError()
}
}
@@ -143,8 +164,10 @@
} else {
"(" + attributes.entries.joinToString(",") { "${it.key} = ${it.value}" } + ")"
}
- val entity = JavaFileObjects.forSourceString("foo.bar.MyEntity",
- ENTITY_PREFIX.format(attributesReplacement) + input + ENTITY_SUFFIX)
+ val entity = JavaFileObjects.forSourceString(
+ "foo.bar.MyEntity",
+ ENTITY_PREFIX.format(attributesReplacement) + input + ENTITY_SUFFIX
+ )
return verify(listOf(entity), "", handler)
}
@@ -152,23 +175,27 @@
query: String,
handler: (Database, TestInvocation) -> Unit
): CompileTester {
- val entity = JavaFileObjects.forSourceString("foo.bar.MyEntity",
- ENTITY_PREFIX.format("") + """
+ val entity = JavaFileObjects.forSourceString(
+ "foo.bar.MyEntity",
+ ENTITY_PREFIX.format("") + """
@PrimaryKey
@NonNull
String uuid;
@NonNull
String name;
int age;
- """ + ENTITY_SUFFIX)
- val view = JavaFileObjects.forSourceString("foo.bar.MyView",
- DATABASE_PREFIX + """
+ """ + ENTITY_SUFFIX
+ )
+ val view = JavaFileObjects.forSourceString(
+ "foo.bar.MyView",
+ DATABASE_PREFIX + """
@DatabaseView("$query")
public class MyView {
public String uuid;
public String name;
}
- """)
+ """
+ )
return verify(listOf(entity, view), "views = {MyView.class},", handler)
}
@@ -185,17 +212,21 @@
}
"""
return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(jfos + JavaFileObjects.forSourceString("foo.bar.MyDatabase", databaseCode))
- .processedWith(TestProcessor.builder()
- .forAnnotations(androidx.room.Database::class,
- NonNull::class)
- .nextRunHandler { invocation ->
- val db = invocation.roundEnv
- .getElementsAnnotatedWith(androidx.room.Database::class.java)
- .first().asTypeElement()
- handler(DatabaseProcessor(invocation.context, db).process(), invocation)
- true
- }
- .build())
+ .that(jfos + JavaFileObjects.forSourceString("foo.bar.MyDatabase", databaseCode))
+ .processedWith(
+ TestProcessor.builder()
+ .forAnnotations(
+ androidx.room.Database::class,
+ NonNull::class
+ )
+ .nextRunHandler { invocation ->
+ val db = invocation.roundEnv
+ .getElementsAnnotatedWith(androidx.room.Database::class.java)
+ .first().asTypeElement()
+ handler(DatabaseProcessor(invocation.context, db).process(), invocation)
+ true
+ }
+ .build()
+ )
}
}
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/TestDatabase.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/TestDatabase.kt
index df906b2..1a85492 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/TestDatabase.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/TestDatabase.kt
@@ -32,9 +32,11 @@
import androidx.room.integration.kotlintestapp.vo.Publisher
@Database(
- entities = [Book::class, Author::class, Publisher::class, BookAuthor::class,
+ entities = [
+ Book::class, Author::class, Publisher::class, BookAuthor::class,
NoArgClass::class, DataClassFromDependency::class, JavaEntity::class,
- EntityWithJavaPojoList::class],
+ EntityWithJavaPojoList::class
+ ],
version = 1,
exportSchema = false
)
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/BooksDao.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/BooksDao.kt
index 6d91da7..49ee2911 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/BooksDao.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/BooksDao.kt
@@ -242,9 +242,11 @@
@Update
suspend fun updateBookWithResultSuspend(book: Book): Int
- @Query("""SELECT * FROM book WHERE
+ @Query(
+ """SELECT * FROM book WHERE
bookId IN(:bookIds)
- order by bookId DESC""")
+ order by bookId DESC"""
+ )
fun getBooksMultiLineQuery(bookIds: List<String>): List<Book>
@Query("SELECT * FROM book WHERE bookId = :bookId")
@@ -275,23 +277,31 @@
fun getBookMaybe(bookId: String): Maybe<Book>
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
- @Query("SELECT * FROM book INNER JOIN publisher " +
- "ON book.bookPublisherId = publisher.publisherId ")
+ @Query(
+ "SELECT * FROM book INNER JOIN publisher " +
+ "ON book.bookPublisherId = publisher.publisherId "
+ )
fun getBooksWithPublisher(): List<BookWithPublisher>
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
- @Query("SELECT * FROM book INNER JOIN publisher " +
- "ON book.bookPublisherId = publisher.publisherId ")
+ @Query(
+ "SELECT * FROM book INNER JOIN publisher " +
+ "ON book.bookPublisherId = publisher.publisherId "
+ )
fun getBooksWithPublisherLiveData(): LiveData<List<BookWithPublisher>>
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
- @Query("SELECT * FROM book INNER JOIN publisher " +
- "ON book.bookPublisherId = publisher.publisherId ")
+ @Query(
+ "SELECT * FROM book INNER JOIN publisher " +
+ "ON book.bookPublisherId = publisher.publisherId "
+ )
fun getBooksWithPublisherFlowable(): Flowable<List<BookWithPublisher>>
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
- @Query("SELECT * FROM book INNER JOIN publisher " +
- "ON book.bookPublisherId = publisher.publisherId ")
+ @Query(
+ "SELECT * FROM book INNER JOIN publisher " +
+ "ON book.bookPublisherId = publisher.publisherId "
+ )
fun getBooksWithPublisherListenableFuture(): ListenableFuture<List<BookWithPublisher>>
@Transaction
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationDbKotlin.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationDbKotlin.kt
index 3d7219b..1f774baf 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationDbKotlin.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationDbKotlin.kt
@@ -31,9 +31,13 @@
import androidx.room.RoomWarnings
import androidx.sqlite.db.SupportSQLiteDatabase
-@Database(version = MigrationDbKotlin.LATEST_VERSION,
- entities = arrayOf(MigrationDbKotlin.Entity1::class, MigrationDbKotlin.Entity2::class,
- MigrationDbKotlin.Entity4::class))
+@Database(
+ version = MigrationDbKotlin.LATEST_VERSION,
+ entities = arrayOf(
+ MigrationDbKotlin.Entity1::class, MigrationDbKotlin.Entity2::class,
+ MigrationDbKotlin.Entity4::class
+ )
+)
abstract class MigrationDbKotlin : RoomDatabase() {
internal abstract fun dao(): MigrationDao
@@ -65,10 +69,16 @@
}
@SuppressWarnings(RoomWarnings.MISSING_INDEX_ON_FOREIGN_KEY_CHILD)
- @Entity(foreignKeys = arrayOf(ForeignKey(entity = Entity1::class,
- parentColumns = arrayOf("name"),
- childColumns = arrayOf("name"),
- deferred = true)))
+ @Entity(
+ foreignKeys = arrayOf(
+ ForeignKey(
+ entity = Entity1::class,
+ parentColumns = arrayOf("name"),
+ childColumns = arrayOf("name"),
+ deferred = true
+ )
+ )
+ )
data class Entity4(@PrimaryKey var id: Int = 0, var name: String?) {
companion object {
val TABLE_NAME = "Entity4"
@@ -102,8 +112,10 @@
val values = ContentValues()
values.put("id", id)
values.put("name", name)
- val insertionId = mDb.insert(Entity1.TABLE_NAME,
- SQLiteDatabase.CONFLICT_REPLACE, values)
+ val insertionId = mDb.insert(
+ Entity1.TABLE_NAME,
+ SQLiteDatabase.CONFLICT_REPLACE, values
+ )
if (insertionId == -1L) {
throw RuntimeException("test failure")
}
@@ -119,8 +131,10 @@
val values = ContentValues()
values.put("id", id)
values.put("name", name)
- val insertionId = mDb.insert(Entity2.TABLE_NAME,
- SQLiteDatabase.CONFLICT_REPLACE, values)
+ val insertionId = mDb.insert(
+ Entity2.TABLE_NAME,
+ SQLiteDatabase.CONFLICT_REPLACE, values
+ )
if (insertionId == -1L) {
throw RuntimeException("test failure")
}
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
index dde8ddd..faabb9d 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
@@ -39,9 +39,10 @@
@get:Rule
var helper: MigrationTestHelper = MigrationTestHelper(
- InstrumentationRegistry.getInstrumentation(),
- MigrationDbKotlin::class.java.canonicalName,
- FrameworkSQLiteOpenHelperFactory())
+ InstrumentationRegistry.getInstrumentation(),
+ MigrationDbKotlin::class.java.canonicalName,
+ FrameworkSQLiteOpenHelperFactory()
+ )
companion object {
val TEST_DB = "migration-test"
@@ -51,8 +52,9 @@
@Throws(IOException::class)
fun giveBadResource() {
val helper = MigrationTestHelper(
- InstrumentationRegistry.getInstrumentation(),
- "foo", FrameworkSQLiteOpenHelperFactory())
+ InstrumentationRegistry.getInstrumentation(),
+ "foo", FrameworkSQLiteOpenHelperFactory()
+ )
try {
helper.createDatabase(TEST_DB, 1)
throw AssertionError("must have failed with missing file exception")
@@ -64,8 +66,10 @@
@Test
@Throws(IOException::class)
fun startInCurrentVersion() {
- val db = helper.createDatabase(TEST_DB,
- MigrationDbKotlin.LATEST_VERSION)
+ val db = helper.createDatabase(
+ TEST_DB,
+ MigrationDbKotlin.LATEST_VERSION
+ )
val dao = MigrationDbKotlin.Dao_V1(db)
dao.insertIntoEntity1(2, "x")
db.close()
@@ -83,8 +87,10 @@
dao.insertIntoEntity1(2, "foo")
dao.insertIntoEntity1(3, "bar")
db.close()
- db = helper.runMigrationsAndValidate(TEST_DB, 2, true,
- MIGRATION_1_2)
+ db = helper.runMigrationsAndValidate(
+ TEST_DB, 2, true,
+ MIGRATION_1_2
+ )
MigrationDbKotlin.Dao_V2(db).insertIntoEntity2(3, "blah")
db.close()
val migrationDb = getLatestDb()
@@ -101,8 +107,9 @@
@Suppress("DEPRECATION")
private fun getLatestDb(): MigrationDbKotlin {
val db = Room.databaseBuilder(
- InstrumentationRegistry.getInstrumentation().targetContext,
- MigrationDbKotlin::class.java, TEST_DB).addMigrations(*ALL_MIGRATIONS).build()
+ InstrumentationRegistry.getInstrumentation().targetContext,
+ MigrationDbKotlin::class.java, TEST_DB
+ ).addMigrations(*ALL_MIGRATIONS).build()
// trigger open
db.beginTransaction()
db.endTransaction()
@@ -123,14 +130,18 @@
db.close()
var caught: IllegalStateException? = null
try {
- helper.runMigrationsAndValidate(TEST_DB, 3, true,
- EmptyMigration(2, 3))
+ helper.runMigrationsAndValidate(
+ TEST_DB, 3, true,
+ EmptyMigration(2, 3)
+ )
} catch (ex: IllegalStateException) {
caught = ex
}
- assertThat<IllegalStateException>(caught,
- instanceOf<IllegalStateException>(IllegalStateException::class.java))
+ assertThat<IllegalStateException>(
+ caught,
+ instanceOf<IllegalStateException>(IllegalStateException::class.java)
+ )
}
@Test
@@ -164,8 +175,10 @@
@Throws(IOException::class)
fun removeColumn() {
helper.createDatabase(TEST_DB, 4)
- val db = helper.runMigrationsAndValidate(TEST_DB,
- 5, true, MIGRATION_4_5)
+ val db = helper.runMigrationsAndValidate(
+ TEST_DB,
+ 5, true, MIGRATION_4_5
+ )
val info = TableInfo.read(db, MigrationDbKotlin.Entity3.TABLE_NAME)
assertThat(info.columns.size, `is`(2))
}
@@ -174,8 +187,10 @@
@Throws(IOException::class)
fun dropTable() {
helper.createDatabase(TEST_DB, 5)
- val db = helper.runMigrationsAndValidate(TEST_DB,
- 6, true, MIGRATION_5_6)
+ val db = helper.runMigrationsAndValidate(
+ TEST_DB,
+ 6, true, MIGRATION_5_6
+ )
val info = TableInfo.read(db, MigrationDbKotlin.Entity3.TABLE_NAME)
assertThat(info.columns.size, `is`(0))
}
@@ -190,8 +205,10 @@
@Throws(IOException::class)
fun failedToDropTableDontVerify() {
helper.createDatabase(TEST_DB, 5)
- val db = helper.runMigrationsAndValidate(TEST_DB,
- 6, false, EmptyMigration(5, 6))
+ val db = helper.runMigrationsAndValidate(
+ TEST_DB,
+ 6, false, EmptyMigration(5, 6)
+ )
val info = TableInfo.read(db, MigrationDbKotlin.Entity3.TABLE_NAME)
assertThat(info.columns.size, `is`(2))
}
@@ -203,15 +220,18 @@
db.close()
var throwable: Throwable? = null
try {
- helper.runMigrationsAndValidate(TEST_DB,
- 7, false, object : Migration(6, 7) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL(
- "CREATE TABLE Entity4 (`id` INTEGER, `name` TEXT," +
+ helper.runMigrationsAndValidate(
+ TEST_DB,
+ 7, false,
+ object : Migration(6, 7) {
+ override fun migrate(database: SupportSQLiteDatabase) {
+ database.execSQL(
+ "CREATE TABLE Entity4 (`id` INTEGER, `name` TEXT," +
" PRIMARY KEY(`id`))"
- )
+ )
+ }
}
- })
+ )
} catch (t: Throwable) {
throwable = t
}
@@ -225,8 +245,10 @@
@Throws(IOException::class)
fun newTableWithForeignKey() {
helper.createDatabase(TEST_DB, 6)
- val db = helper.runMigrationsAndValidate(TEST_DB,
- 7, false, MIGRATION_6_7)
+ val db = helper.runMigrationsAndValidate(
+ TEST_DB,
+ 7, false, MIGRATION_6_7
+ )
val info = TableInfo.read(db, MigrationDbKotlin.Entity4.TABLE_NAME)
assertThat(info.foreignKeys.size, `is`(1))
}
@@ -237,8 +259,10 @@
db.close()
var throwable: Throwable? = null
try {
- helper.runMigrationsAndValidate(TEST_DB, endVersion, true,
- EmptyMigration(startVersion, endVersion))
+ helper.runMigrationsAndValidate(
+ TEST_DB, endVersion, true,
+ EmptyMigration(startVersion, endVersion)
+ )
} catch (t: Throwable) {
throwable = t
}
@@ -251,7 +275,7 @@
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(
"CREATE TABLE IF NOT EXISTS `Entity2` (`id` INTEGER NOT NULL," +
- " `name` TEXT, PRIMARY KEY(`id`))"
+ " `name` TEXT, PRIMARY KEY(`id`))"
)
}
}
@@ -260,7 +284,7 @@
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(
"ALTER TABLE " + MigrationDbKotlin.Entity2.TABLE_NAME +
- " ADD COLUMN addedInV3 TEXT"
+ " ADD COLUMN addedInV3 TEXT"
)
}
}
@@ -269,7 +293,7 @@
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(
"CREATE TABLE IF NOT EXISTS `Entity3` (`id` INTEGER NOT NULL," +
- " `removedInV5` TEXT, `name` TEXT, PRIMARY KEY(`id`))"
+ " `removedInV5` TEXT, `name` TEXT, PRIMARY KEY(`id`))"
)
}
}
@@ -278,11 +302,11 @@
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(
"CREATE TABLE IF NOT EXISTS `Entity3_New` (`id` INTEGER NOT NULL," +
- " `name` TEXT, PRIMARY KEY(`id`))"
+ " `name` TEXT, PRIMARY KEY(`id`))"
)
database.execSQL(
"INSERT INTO Entity3_New(`id`, `name`) " +
- "SELECT `id`, `name` FROM Entity3"
+ "SELECT `id`, `name` FROM Entity3"
)
database.execSQL("DROP TABLE Entity3")
database.execSQL("ALTER TABLE Entity3_New RENAME TO Entity3")
@@ -299,20 +323,22 @@
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(
"CREATE TABLE IF NOT EXISTS " +
- MigrationDbKotlin.Entity4.TABLE_NAME +
- " (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`)," +
- " FOREIGN KEY(`name`) REFERENCES `Entity1`(`name`)" +
- " ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED)"
+ MigrationDbKotlin.Entity4.TABLE_NAME +
+ " (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`)," +
+ " FOREIGN KEY(`name`) REFERENCES `Entity1`(`name`)" +
+ " ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED)"
)
database.execSQL(
"CREATE UNIQUE INDEX `index_entity1` ON " +
- MigrationDbKotlin.Entity1.TABLE_NAME + " (`name`)"
+ MigrationDbKotlin.Entity1.TABLE_NAME + " (`name`)"
)
}
}
- private val ALL_MIGRATIONS = arrayOf(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5,
- MIGRATION_5_6, MIGRATION_6_7)
+ private val ALL_MIGRATIONS = arrayOf(
+ MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5,
+ MIGRATION_5_6, MIGRATION_6_7
+ )
internal class EmptyMigration(startVersion: Int, endVersion: Int) :
Migration(startVersion, endVersion) {
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/BooksDaoTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/BooksDaoTest.kt
index 1b3d4ae..a3c2112 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/BooksDaoTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/BooksDaoTest.kt
@@ -63,16 +63,18 @@
booksDao.addBooks(TestUtil.BOOK_1)
assertThat(
- booksDao.getBookJavaOptional(TestUtil.BOOK_1.bookId),
- `is`<java.util.Optional<Book>>(java.util.Optional.of(TestUtil.BOOK_1)))
+ booksDao.getBookJavaOptional(TestUtil.BOOK_1.bookId),
+ `is`<java.util.Optional<Book>>(java.util.Optional.of(TestUtil.BOOK_1))
+ )
}
@SdkSuppress(minSdkVersion = 24)
@Test
fun bookByIdJavaOptionalEmpty() {
assertThat(
- booksDao.getBookJavaOptional(TestUtil.BOOK_1.bookId),
- `is`<java.util.Optional<Book>>(java.util.Optional.empty()))
+ booksDao.getBookJavaOptional(TestUtil.BOOK_1.bookId),
+ `is`<java.util.Optional<Book>>(java.util.Optional.empty())
+ )
}
@Test
@@ -82,8 +84,9 @@
booksDao.addBooks(TestUtil.BOOK_1)
assertThat(
- booksDao.getBookListenableFuture(TestUtil.BOOK_1.bookId).get(),
- `is`<Book>(TestUtil.BOOK_1))
+ booksDao.getBookListenableFuture(TestUtil.BOOK_1.bookId).get(),
+ `is`<Book>(TestUtil.BOOK_1)
+ )
}
@Test
@@ -93,8 +96,9 @@
booksDao.addBooks(TestUtil.BOOK_1)
assertThat(
- booksDao.getBookOptional(TestUtil.BOOK_1.bookId),
- `is`<Optional<Book>>(Optional.of(TestUtil.BOOK_1)))
+ booksDao.getBookOptional(TestUtil.BOOK_1.bookId),
+ `is`<Optional<Book>>(Optional.of(TestUtil.BOOK_1))
+ )
}
@Test
@@ -104,22 +108,25 @@
booksDao.addBooks(TestUtil.BOOK_1)
assertThat(
- booksDao.getBookOptionalListenableFuture(TestUtil.BOOK_1.bookId).get(),
- `is`<Optional<Book>>(Optional.of(TestUtil.BOOK_1)))
+ booksDao.getBookOptionalListenableFuture(TestUtil.BOOK_1.bookId).get(),
+ `is`<Optional<Book>>(Optional.of(TestUtil.BOOK_1))
+ )
}
@Test
fun bookByIdOptionalListenableFutureAbsent() {
assertThat(
- booksDao.getBookOptionalListenableFuture(TestUtil.BOOK_1.bookId).get(),
- `is`<Optional<Book>>(Optional.absent()))
+ booksDao.getBookOptionalListenableFuture(TestUtil.BOOK_1.bookId).get(),
+ `is`<Optional<Book>>(Optional.absent())
+ )
}
@Test
fun bookByIdOptionalAbsent() {
assertThat(
- booksDao.getBookOptional(TestUtil.BOOK_1.bookId),
- `is`<Optional<Book>>(Optional.absent()))
+ booksDao.getBookOptional(TestUtil.BOOK_1.bookId),
+ `is`<Optional<Book>>(Optional.absent())
+ )
}
@Test
@@ -130,9 +137,9 @@
val subscriber = TestSubscriber<Optional<Book>>()
val flowable: Flowable<Optional<Book>> =
- booksDao.getBookOptionalFlowable(TestUtil.BOOK_1.bookId)
+ booksDao.getBookOptionalFlowable(TestUtil.BOOK_1.bookId)
flowable.observeOn(Schedulers.from(ArchTaskExecutor.getMainThreadExecutor()))
- .subscribeWith(subscriber)
+ .subscribeWith(subscriber)
drain()
assertThat(subscriber.values().size, `is`(1))
assertThat(subscriber.values()[0], `is`(Optional.of(TestUtil.BOOK_1)))
@@ -142,9 +149,9 @@
fun bookByIdOptionalFlowableAbsent() {
val subscriber = TestSubscriber<Optional<Book>>()
val flowable: Flowable<Optional<Book>> =
- booksDao.getBookOptionalFlowable(TestUtil.BOOK_1.bookId)
+ booksDao.getBookOptionalFlowable(TestUtil.BOOK_1.bookId)
flowable.observeOn(Schedulers.from(ArchTaskExecutor.getMainThreadExecutor()))
- .subscribeWith(subscriber)
+ .subscribeWith(subscriber)
drain()
assertThat(subscriber.values().size, `is`(1))
assertThat(subscriber.values()[0], `is`(Optional.absent()))
@@ -156,13 +163,17 @@
booksDao.addPublishers(TestUtil.PUBLISHER)
booksDao.addBooks(TestUtil.BOOK_1)
- val expected = BookWithPublisher(TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
- TestUtil.PUBLISHER)
+ val expected = BookWithPublisher(
+ TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
+ TestUtil.PUBLISHER
+ )
val expectedList = ArrayList<BookWithPublisher>()
expectedList.add(expected)
- assertThat(database.booksDao().getBooksWithPublisher(),
- `is`<List<BookWithPublisher>>(expectedList))
+ assertThat(
+ database.booksDao().getBooksWithPublisher(),
+ `is`<List<BookWithPublisher>>(expectedList)
+ )
}
@Test
@@ -171,13 +182,17 @@
booksDao.addPublishers(TestUtil.PUBLISHER)
booksDao.addBooks(TestUtil.BOOK_1)
- val expected = BookWithPublisher(TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
- TestUtil.PUBLISHER)
+ val expected = BookWithPublisher(
+ TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
+ TestUtil.PUBLISHER
+ )
val expectedList = ArrayList<BookWithPublisher>()
expectedList.add(expected)
- assertThat(database.booksDao().getBooksWithPublisherListenableFuture().get(),
- `is`<List<BookWithPublisher>>(expectedList))
+ assertThat(
+ database.booksDao().getBooksWithPublisherListenableFuture().get(),
+ `is`<List<BookWithPublisher>>(expectedList)
+ )
}
@Test
@@ -192,8 +207,13 @@
throwable = t
}
assertNotNull(throwable)
- assertThat<Throwable>(throwable, instanceOf<Throwable>(SQLiteConstraintException::class
- .java))
+ assertThat<Throwable>(
+ throwable,
+ instanceOf<Throwable>(
+ SQLiteConstraintException::class
+ .java
+ )
+ )
}
@Test
@@ -203,7 +223,8 @@
booksDao.addBooks(TestUtil.BOOK_1, TestUtil.BOOK_2)
val actualPublisherWithBooks = booksDao.getPublisherWithBooks(
- TestUtil.PUBLISHER.publisherId)
+ TestUtil.PUBLISHER.publisherId
+ )
assertThat(actualPublisherWithBooks.publisher, `is`<Publisher>(TestUtil.PUBLISHER))
assertThat(actualPublisherWithBooks.books?.size, `is`(2))
@@ -217,11 +238,19 @@
booksDao.addPublishers(TestUtil.PUBLISHER)
booksDao.addBooks(TestUtil.BOOK_1, TestUtil.BOOK_2)
val actualPublisherWithBooks = booksDao.getPublisherWithBookSales(
- TestUtil.PUBLISHER.publisherId)
+ TestUtil.PUBLISHER.publisherId
+ )
assertThat(actualPublisherWithBooks.publisher, `is`<Publisher>(TestUtil.PUBLISHER))
- assertThat(actualPublisherWithBooks.sales, `is`(listOf(TestUtil.BOOK_1.salesCnt,
- TestUtil.BOOK_2.salesCnt)))
+ assertThat(
+ actualPublisherWithBooks.sales,
+ `is`(
+ listOf(
+ TestUtil.BOOK_1.salesCnt,
+ TestUtil.BOOK_2.salesCnt
+ )
+ )
+ )
}
@Test
@@ -249,9 +278,12 @@
booksDao.addBooks(TestUtil.BOOK_1)
booksDao.addBooks(TestUtil.BOOK_2)
- val books = database.booksDao().getBooksMultiLineQuery(arrayListOf(
+ val books = database.booksDao().getBooksMultiLineQuery(
+ arrayListOf(
TestUtil.BOOK_1.bookId,
- TestUtil.BOOK_2.bookId))
+ TestUtil.BOOK_2.bookId
+ )
+ )
assertThat(books, `is`(listOf(TestUtil.BOOK_2, TestUtil.BOOK_1)))
}
@@ -263,17 +295,25 @@
val book3 = TestUtil.BOOK_3.copy(languages = setOf(Lang.EN))
booksDao.addBooks(book1, book2, book3)
- assertThat(booksDao.findByLanguages(setOf(Lang.EN, Lang.TR)),
- `is`(listOf(book1, book2, book3)))
+ assertThat(
+ booksDao.findByLanguages(setOf(Lang.EN, Lang.TR)),
+ `is`(listOf(book1, book2, book3))
+ )
- assertThat(booksDao.findByLanguages(setOf(Lang.TR)),
- `is`(listOf(book1, book2)))
+ assertThat(
+ booksDao.findByLanguages(setOf(Lang.TR)),
+ `is`(listOf(book1, book2))
+ )
- assertThat(booksDao.findByLanguages(setOf(Lang.ES)),
- `is`(listOf(book2)))
+ assertThat(
+ booksDao.findByLanguages(setOf(Lang.ES)),
+ `is`(listOf(book2))
+ )
- assertThat(booksDao.findByLanguages(setOf(Lang.EN)),
- `is`(listOf(book3)))
+ assertThat(
+ booksDao.findByLanguages(setOf(Lang.EN)),
+ `is`(listOf(book3))
+ )
}
@Test
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/ConstructorInheritanceTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/ConstructorInheritanceTest.kt
index bad312f..f5af52b 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/ConstructorInheritanceTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/ConstructorInheritanceTest.kt
@@ -135,9 +135,13 @@
val childGroup = dao.loadGroupById2(1)
assertThat(childGroup.child1.id, `is`(1L))
assertThat(childGroup.children2, hasSize(2))
- assertThat(childGroup.children2, hasItems(
- Child2(2, Info("123")),
- Child2(3, Info("123"))))
+ assertThat(
+ childGroup.children2,
+ hasItems(
+ Child2(2, Info("123")),
+ Child2(3, Info("123"))
+ )
+ )
}
private fun openDatabase(): EmbeddedDatabase {
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoPrimitiveTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoPrimitiveTest.kt
index 227c5d9..32368bd 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoPrimitiveTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoPrimitiveTest.kt
@@ -122,8 +122,11 @@
@Test
fun testLongFooDao() {
- val db = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getInstrumentation()
- .getTargetContext(), TestDatabase::class.java).build()
+ val db = Room.inMemoryDatabaseBuilder(
+ InstrumentationRegistry.getInstrumentation()
+ .getTargetContext(),
+ TestDatabase::class.java
+ ).build()
val foo = LongFoo(1, "Elif")
db.longFooDao().insert(foo)
@@ -135,8 +138,11 @@
@Test
fun testStringFooDao() {
- val db = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getInstrumentation()
- .getTargetContext(), TestDatabase::class.java).build()
+ val db = Room.inMemoryDatabaseBuilder(
+ InstrumentationRegistry.getInstrumentation()
+ .getTargetContext(),
+ TestDatabase::class.java
+ ).build()
val foo = StringFoo("Key", "Elif")
db.stringFooDao().insert(foo)
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DeferredBooksDaoTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DeferredBooksDaoTest.kt
index aac4d59..1ad5028 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DeferredBooksDaoTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DeferredBooksDaoTest.kt
@@ -39,16 +39,20 @@
@Test
fun increaseBookSales() {
booksDao.increaseBookSales(TestUtil.BOOK_1.bookId)
- assertThat(booksDao.getBook(TestUtil.BOOK_1.bookId).salesCnt,
- `is`(TestUtil.BOOK_1.salesCnt + 1))
+ assertThat(
+ booksDao.getBook(TestUtil.BOOK_1.bookId).salesCnt,
+ `is`(TestUtil.BOOK_1.salesCnt + 1)
+ )
}
@Test
fun increaseBookSalesSuspend() {
runBlocking {
booksDao.increaseBookSalesSuspend(TestUtil.BOOK_1.bookId)
- assertThat(booksDao.getBookSuspend(TestUtil.BOOK_1.bookId).salesCnt,
- `is`(TestUtil.BOOK_1.salesCnt + 1))
+ assertThat(
+ booksDao.getBookSuspend(TestUtil.BOOK_1.bookId).salesCnt,
+ `is`(TestUtil.BOOK_1.salesCnt + 1)
+ )
}
}
@@ -83,8 +87,10 @@
@Test
fun increaseBookSalesVoidFuture() {
booksDao.increaseBookSalesVoidFuture(TestUtil.BOOK_1.bookId).get()
- assertThat(booksDao.getBook(TestUtil.BOOK_1.bookId).salesCnt,
- `is`(TestUtil.BOOK_1.salesCnt + 1))
+ assertThat(
+ booksDao.getBook(TestUtil.BOOK_1.bookId).salesCnt,
+ `is`(TestUtil.BOOK_1.salesCnt + 1)
+ )
}
@Test
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DependencyDaoTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DependencyDaoTest.kt
index 1ec69ed..7e9e88b 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DependencyDaoTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DependencyDaoTest.kt
@@ -63,9 +63,15 @@
@Test
fun insertAndGetByQuery_pojo() {
val data = insertSample(3)
- assertThat(dao.findPojo(3), `is`(PojoFromDependency(
- id = data.id,
- name = data.name)))
+ assertThat(
+ dao.findPojo(3),
+ `is`(
+ PojoFromDependency(
+ id = data.id,
+ name = data.name
+ )
+ )
+ )
assertThat(dao.findPojo(5), `is`(nullValue()))
}
@@ -73,16 +79,16 @@
@Test
fun getRelation() {
val foo1 = DataClassFromDependency(
- id = 3,
- name = "foo"
+ id = 3,
+ name = "foo"
)
val foo2 = DataClassFromDependency(
- id = 4,
- name = "foo"
+ id = 4,
+ name = "foo"
)
val bar = DataClassFromDependency(
- id = 5,
- name = "bar"
+ id = 5,
+ name = "bar"
)
dao.insert(foo1, foo2, bar)
val fooList = dao.relation("foo")
@@ -103,8 +109,8 @@
private fun insertSample(id: Int): DataClassFromDependency {
val data = DataClassFromDependency(
- id = id,
- name = "foo"
+ id = id,
+ name = "foo"
)
dao.insert(data)
return data
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/ItemWithNullableConstructor.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/ItemWithNullableConstructor.kt
index c0223fe..328559f 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/ItemWithNullableConstructor.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/ItemWithNullableConstructor.kt
@@ -42,7 +42,8 @@
fun initDb() {
db = Room.inMemoryDatabaseBuilder(
ApplicationProvider.getApplicationContext(),
- Db::class.java).build()
+ Db::class.java
+ ).build()
}
@After
@@ -73,9 +74,9 @@
}
@Database(
- version = 1,
- entities = [TestItem::class],
- exportSchema = false
+ version = 1,
+ entities = [TestItem::class],
+ exportSchema = false
)
@SuppressWarnings(RoomWarnings.MISSING_SCHEMA_LOCATION)
abstract class Db : RoomDatabase() {
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/LiveDataQueryTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/LiveDataQueryTest.kt
index fecb9ef..f6b37834 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/LiveDataQueryTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/LiveDataQueryTest.kt
@@ -34,7 +34,8 @@
booksDao.addBooks(TestUtil.BOOK_1)
val book = LiveDataTestUtil.awaitValue(
- booksDao.getBookLiveData(TestUtil.BOOK_1.bookId))
+ booksDao.getBookLiveData(TestUtil.BOOK_1.bookId)
+ )
assertThat(book, `is`<Book>(TestUtil.BOOK_1))
}
@@ -45,12 +46,15 @@
booksDao.addPublishers(TestUtil.PUBLISHER)
booksDao.addBooks(TestUtil.BOOK_1)
- var expected = BookWithPublisher(TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
- TestUtil.PUBLISHER)
+ var expected = BookWithPublisher(
+ TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
+ TestUtil.PUBLISHER
+ )
var expectedList = ArrayList<BookWithPublisher>()
expectedList.add(expected)
val actual = LiveDataTestUtil.awaitValue(
- booksDao.getBooksWithPublisherLiveData())
+ booksDao.getBooksWithPublisherLiveData()
+ )
assertThat(actual, `is`<List<BookWithPublisher>>(expectedList))
}
@@ -61,7 +65,8 @@
booksDao.addBooks(TestUtil.BOOK_1, TestUtil.BOOK_2)
var actualPublisherWithBooks = LiveDataTestUtil.awaitValue(
- booksDao.getPublisherWithBooksLiveData(TestUtil.PUBLISHER.publisherId))
+ booksDao.getPublisherWithBooksLiveData(TestUtil.PUBLISHER.publisherId)
+ )
assertThat(actualPublisherWithBooks.publisher, `is`<Publisher>(TestUtil.PUBLISHER))
assertThat(actualPublisherWithBooks.books?.size, `is`(2))
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/RxJava2QueryTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/RxJava2QueryTest.kt
index 4f7db1b..4b6e866 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/RxJava2QueryTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/RxJava2QueryTest.kt
@@ -32,11 +32,11 @@
booksDao.addPublishers(TestUtil.PUBLISHER)
booksDao.addBooks(TestUtil.BOOK_1)
booksDao.getBookFlowable(TestUtil.BOOK_1.bookId)
- .test()
- .also {
- drain()
- }
- .assertValue { book -> book == TestUtil.BOOK_1 }
+ .test()
+ .also {
+ drain()
+ }
+ .assertValue { book -> book == TestUtil.BOOK_1 }
}
@Test
@@ -46,16 +46,16 @@
booksDao.addBooks(TestUtil.BOOK_1)
booksDao.getBookSingle(TestUtil.BOOK_1.bookId)
- .test()
- .assertComplete()
- .assertValue { book -> book == TestUtil.BOOK_1 }
+ .test()
+ .assertComplete()
+ .assertValue { book -> book == TestUtil.BOOK_1 }
}
@Test
fun observeBooksByIdSingle_noBook() {
booksDao.getBookSingle("x")
- .test()
- .assertError(EmptyResultSetException::class.java)
+ .test()
+ .assertError(EmptyResultSetException::class.java)
}
@Test
@@ -65,18 +65,18 @@
booksDao.addBooks(TestUtil.BOOK_1)
booksDao.getBookMaybe(TestUtil.BOOK_1.bookId)
- .test()
- .assertComplete()
- .assertValue { book -> book == TestUtil.BOOK_1 }
+ .test()
+ .assertComplete()
+ .assertValue { book -> book == TestUtil.BOOK_1 }
}
@Test
fun observeBooksByIdMaybe_noBook() {
booksDao.getBookMaybe("x")
- .test()
- .assertComplete()
- .assertNoErrors()
- .assertNoValues()
+ .test()
+ .assertComplete()
+ .assertNoErrors()
+ .assertNoValues()
}
@Test
@@ -85,16 +85,18 @@
booksDao.addPublishers(TestUtil.PUBLISHER)
booksDao.addBooks(TestUtil.BOOK_1)
- var expected = BookWithPublisher(TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
- TestUtil.PUBLISHER)
+ var expected = BookWithPublisher(
+ TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
+ TestUtil.PUBLISHER
+ )
var expectedList = ArrayList<BookWithPublisher>()
expectedList.add(expected)
booksDao.getBooksWithPublisherFlowable()
- .test()
- .also {
- drain()
- }
- .assertValue(expectedList)
+ .test()
+ .also {
+ drain()
+ }
+ .assertValue(expectedList)
}
@Test
@@ -103,16 +105,16 @@
booksDao.addPublishers(TestUtil.PUBLISHER)
booksDao.addBooks(TestUtil.BOOK_1, TestUtil.BOOK_2)
booksDao.getPublisherWithBooksFlowable(TestUtil.PUBLISHER.publisherId)
- .test()
- .also {
- drain()
- }
- .assertValue {
- it.publisher == TestUtil.PUBLISHER &&
- it.books?.size == 2 &&
- it.books?.get(0) == TestUtil.BOOK_1 &&
- it.books?.get(1) == TestUtil.BOOK_2
- }
+ .test()
+ .also {
+ drain()
+ }
+ .assertValue {
+ it.publisher == TestUtil.PUBLISHER &&
+ it.books?.size == 2 &&
+ it.books?.get(0) == TestUtil.BOOK_1 &&
+ it.books?.get(1) == TestUtil.BOOK_2
+ }
}
@Test
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SneakyThrowTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SneakyThrowTest.kt
index f462d00..2fee4f7 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SneakyThrowTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SneakyThrowTest.kt
@@ -32,10 +32,12 @@
@Test
fun testCheckedException() {
try {
- database.runInTransaction(Callable<String> {
- val json = JSONObject()
- json.getString("key") // method declares that it throws JSONException
- })
+ database.runInTransaction(
+ Callable<String> {
+ val json = JSONObject()
+ json.getString("key") // method declares that it throws JSONException
+ }
+ )
fail("runInTransaction should have thrown an exception")
} catch (ex: JSONException) {
// no-op on purpose
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SuspendingQueryTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SuspendingQueryTest.kt
index 9d2ce74..6998bfe 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SuspendingQueryTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SuspendingQueryTest.kt
@@ -667,7 +667,8 @@
}
val wrappedExecutor = WrappedService(Executors.newCachedThreadPool())
val localDatabase = Room.inMemoryDatabaseBuilder(
- ApplicationProvider.getApplicationContext(), TestDatabase::class.java)
+ ApplicationProvider.getApplicationContext(), TestDatabase::class.java
+ )
.setQueryExecutor(ArchTaskExecutor.getIOThreadExecutor())
.setTransactionExecutor(wrappedExecutor)
.build()
@@ -699,7 +700,8 @@
runBlocking {
val executorService = Executors.newSingleThreadExecutor()
val localDatabase = Room.inMemoryDatabaseBuilder(
- ApplicationProvider.getApplicationContext(), TestDatabase::class.java)
+ ApplicationProvider.getApplicationContext(), TestDatabase::class.java
+ )
.setTransactionExecutor(executorService)
.build()
@@ -734,7 +736,8 @@
runBlocking {
val executorService = Executors.newCachedThreadPool()
val localDatabase = Room.inMemoryDatabaseBuilder(
- ApplicationProvider.getApplicationContext(), TestDatabase::class.java)
+ ApplicationProvider.getApplicationContext(), TestDatabase::class.java
+ )
.setTransactionExecutor(executorService)
.build()
@@ -756,7 +759,8 @@
fun withTransaction_databaseOpenError() {
runBlocking {
val localDatabase = Room.inMemoryDatabaseBuilder(
- ApplicationProvider.getApplicationContext(), TestDatabase::class.java)
+ ApplicationProvider.getApplicationContext(), TestDatabase::class.java
+ )
.addCallback(object : RoomDatabase.Callback() {
override fun onOpen(db: SupportSQLiteDatabase) {
// this causes all transaction methods to throw, this can happen IRL
@@ -781,7 +785,8 @@
runBlocking {
// delegate and delegate just so that we can throw in beginTransaction()
val localDatabase = Room.inMemoryDatabaseBuilder(
- ApplicationProvider.getApplicationContext(), TestDatabase::class.java)
+ ApplicationProvider.getApplicationContext(), TestDatabase::class.java
+ )
.openHelperFactory(
object : SupportSQLiteOpenHelper.Factory {
val factoryDelegate = FrameworkSQLiteOpenHelperFactory()
@@ -830,7 +835,7 @@
assertThat(ex).hasMessageThat()
.contains(
"Cannot perform this operation because there is no current " +
- "transaction"
+ "transaction"
)
} else {
assertThat(ex).hasMessageThat()
@@ -858,7 +863,7 @@
assertThat(ex).hasMessageThat()
.contains(
"Cannot perform this operation because there is no current " +
- "transaction"
+ "transaction"
)
} else {
assertThat(ex).hasMessageThat()
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestDatabaseTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestDatabaseTest.kt
index 52fe1f9..a89694d 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestDatabaseTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestDatabaseTest.kt
@@ -38,8 +38,9 @@
fun setUp() {
database = Room.inMemoryDatabaseBuilder(
ApplicationProvider.getApplicationContext(),
- TestDatabase::class.java)
- .build()
+ TestDatabase::class.java
+ )
+ .build()
booksDao = database.booksDao()
}
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestUtil.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestUtil.kt
index dfb4841..66cf87b 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestUtil.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestUtil.kt
@@ -32,12 +32,18 @@
val AUTHOR_1 = Author("a1", "author 1")
val AUTHOR_2 = Author("a2", "author 2")
- val BOOK_1 = Book("b1", "book title 1", "ph1",
- setOf(Lang.EN), 3)
- val BOOK_2 = Book("b2", "book title 2", "ph1",
- setOf(Lang.TR), 5)
- val BOOK_3 = Book("b3", "book title 2", "ph1",
- setOf(Lang.ES), 7)
+ val BOOK_1 = Book(
+ "b1", "book title 1", "ph1",
+ setOf(Lang.EN), 3
+ )
+ val BOOK_2 = Book(
+ "b2", "book title 2", "ph1",
+ setOf(Lang.TR), 5
+ )
+ val BOOK_3 = Book(
+ "b3", "book title 2", "ph1",
+ setOf(Lang.ES), 7
+ )
val BOOK_AUTHOR_1_1 = BookAuthor(BOOK_1.bookId, AUTHOR_1.authorId)
val BOOK_AUTHOR_1_2 = BookAuthor(BOOK_1.bookId, AUTHOR_2.authorId)
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Book.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Book.kt
index 08fd444..e5be81c 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Book.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Book.kt
@@ -24,11 +24,16 @@
import androidx.room.TypeConverters
@SuppressWarnings(RoomWarnings.MISSING_INDEX_ON_FOREIGN_KEY_CHILD)
-@Entity(foreignKeys = arrayOf(
- ForeignKey(entity = Publisher::class,
- parentColumns = arrayOf("publisherId"),
- childColumns = arrayOf("bookPublisherId"),
- deferred = true)))
+@Entity(
+ foreignKeys = arrayOf(
+ ForeignKey(
+ entity = Publisher::class,
+ parentColumns = arrayOf("publisherId"),
+ childColumns = arrayOf("bookPublisherId"),
+ deferred = true
+ )
+ )
+)
data class Book(
@PrimaryKey val bookId: String,
val title: String,
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/BookAuthor.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/BookAuthor.kt
index b8b06c5..a7a0777 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/BookAuthor.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/BookAuthor.kt
@@ -20,20 +20,26 @@
import androidx.room.ForeignKey
import androidx.room.Index
-@Entity(foreignKeys = arrayOf(
- ForeignKey(entity = Book::class,
- parentColumns = arrayOf("bookId"),
- childColumns = arrayOf("bookId"),
- onUpdate = ForeignKey.CASCADE,
- onDelete = ForeignKey.CASCADE,
- deferred = true),
- ForeignKey(entity = Author::class,
- parentColumns = arrayOf("authorId"),
- childColumns = arrayOf("authorId"),
- onUpdate = ForeignKey.CASCADE,
- onDelete = ForeignKey.CASCADE,
- deferred = true)),
- primaryKeys = arrayOf("bookId", "authorId"),
- indices = [Index("bookId"), Index("authorId")]
+@Entity(
+ foreignKeys = arrayOf(
+ ForeignKey(
+ entity = Book::class,
+ parentColumns = arrayOf("bookId"),
+ childColumns = arrayOf("bookId"),
+ onUpdate = ForeignKey.CASCADE,
+ onDelete = ForeignKey.CASCADE,
+ deferred = true
+ ),
+ ForeignKey(
+ entity = Author::class,
+ parentColumns = arrayOf("authorId"),
+ childColumns = arrayOf("authorId"),
+ onUpdate = ForeignKey.CASCADE,
+ onDelete = ForeignKey.CASCADE,
+ deferred = true
+ )
+ ),
+ primaryKeys = arrayOf("bookId", "authorId"),
+ indices = [Index("bookId"), Index("authorId")]
)
data class BookAuthor(val bookId: String, val authorId: String)
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PublisherWithBookSales.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PublisherWithBookSales.kt
index bbfb253..55e50b2 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PublisherWithBookSales.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PublisherWithBookSales.kt
@@ -22,9 +22,11 @@
data class PublisherWithBookSales @JvmOverloads constructor(
@Embedded
val publisher: Publisher,
- @Relation(parentColumn = "publisherId", // publisher.publisherId
- entityColumn = "bookPublisherId", // book.bookPublisherId
- entity = Book::class,
- projection = ["salesCnt"])
+ @Relation(
+ parentColumn = "publisherId", // publisher.publisherId
+ entityColumn = "bookPublisherId", // book.bookPublisherId
+ entity = Book::class,
+ projection = ["salesCnt"]
+ )
var sales: List<Int>? = emptyList()
)
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PublisherWithBooks.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PublisherWithBooks.kt
index 8a6e0d1..e184c7b 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PublisherWithBooks.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PublisherWithBooks.kt
@@ -21,8 +21,10 @@
class PublisherWithBooks {
@Embedded var publisher: Publisher? = null
- @Relation(parentColumn = "publisherId", // publisher.publisherId
- entityColumn = "bookPublisherId", // book.bookPublisherId
- entity = Book::class)
+ @Relation(
+ parentColumn = "publisherId", // publisher.publisherId
+ entityColumn = "bookPublisherId", // book.bookPublisherId
+ entity = Book::class
+ )
var books: List<Book>? = null
}
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/StringToIntListConverters.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/StringToIntListConverters.kt
index 38f552a..5911be6 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/StringToIntListConverters.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/StringToIntListConverters.kt
@@ -9,10 +9,10 @@
// constructor of the class, and a object has a private constructor.
@JvmStatic
fun stringToIntList(data: String?): List<Int>? =
- if (data == null) null else StringUtil.splitToIntList(data)
+ if (data == null) null else StringUtil.splitToIntList(data)
@TypeConverter
@JvmStatic
fun intListToString(ints: List<Int>?): String? =
- if (ints == null) null else StringUtil.joinIntoString(ints)
+ if (ints == null) null else StringUtil.joinIntoString(ints)
}
diff --git a/room/integration-tests/kotlintestapp/src/main/java/androidx/room/integration/kotlintestapp/vo/RelationFromDependency.kt b/room/integration-tests/kotlintestapp/src/main/java/androidx/room/integration/kotlintestapp/vo/RelationFromDependency.kt
index 8f0b48b..7d3a0d0 100644
--- a/room/integration-tests/kotlintestapp/src/main/java/androidx/room/integration/kotlintestapp/vo/RelationFromDependency.kt
+++ b/room/integration-tests/kotlintestapp/src/main/java/androidx/room/integration/kotlintestapp/vo/RelationFromDependency.kt
@@ -19,8 +19,8 @@
class RelationFromDependency(val sharedName: String) {
@Relation(
- parentColumn = "sharedName",
- entityColumn = "name"
+ parentColumn = "sharedName",
+ entityColumn = "name"
)
lateinit var dataItems: List<DataClassFromDependency>
}
\ No newline at end of file
diff --git a/room/runtime/src/main/java/androidx/room/Room.java b/room/runtime/src/main/java/androidx/room/Room.java
index cadf56c..6a570c4 100644
--- a/room/runtime/src/main/java/androidx/room/Room.java
+++ b/room/runtime/src/main/java/androidx/room/Room.java
@@ -85,9 +85,12 @@
//noinspection TryWithIdenticalCatches
try {
+ final String fullClassName = fullPackage.isEmpty()
+ ? implName
+ : fullPackage + "." + implName;
@SuppressWarnings("unchecked")
final Class<T> aClass = (Class<T>) Class.forName(
- fullPackage.isEmpty() ? implName : fullPackage + "." + implName);
+ fullClassName, true, klass.getClassLoader());
return aClass.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException("cannot find implementation for "
diff --git a/room/runtime/src/test/java/androidx/room/SQLiteCopyOpenHelperTest.kt b/room/runtime/src/test/java/androidx/room/SQLiteCopyOpenHelperTest.kt
index 4e5e069..7f4cb20 100644
--- a/room/runtime/src/test/java/androidx/room/SQLiteCopyOpenHelperTest.kt
+++ b/room/runtime/src/test/java/androidx/room/SQLiteCopyOpenHelperTest.kt
@@ -132,8 +132,10 @@
}
val exitCode = it.exitValue()
if (exitCode != 0) {
- throw IllegalStateException("Copy process exited with non-zero code. " +
- "Code: $exitCode")
+ throw IllegalStateException(
+ "Copy process exited with non-zero code. " +
+ "Code: $exitCode"
+ )
}
}
} finally {
diff --git a/samples/Support4Demos/src/main/AndroidManifest.xml b/samples/Support4Demos/src/main/AndroidManifest.xml
index 2f8f5df3..98fc5b7 100644
--- a/samples/Support4Demos/src/main/AndroidManifest.xml
+++ b/samples/Support4Demos/src/main/AndroidManifest.xml
@@ -437,6 +437,17 @@
</intent-filter>
</activity>
+ <activity
+ android:name=".view.WindowInsetsControllerPlayground"
+ android:label="@string/insets_controller_playground"
+ android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar"
+ android:windowSoftInputMode="adjustResize">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.example.android.supportv4.SUPPORT4_SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
<!-- (OPTIONAL) use this meta data to indicate which icon should be used in media
notifications (for example, when the music changes and the user is
looking at another app) -->
diff --git a/samples/Support4Demos/src/main/java/com/example/android/supportv4/view/WindowInsetsControllerPlayground.kt b/samples/Support4Demos/src/main/java/com/example/android/supportv4/view/WindowInsetsControllerPlayground.kt
new file mode 100644
index 0000000..dc518c6
--- /dev/null
+++ b/samples/Support4Demos/src/main/java/com/example/android/supportv4/view/WindowInsetsControllerPlayground.kt
@@ -0,0 +1,176 @@
+/*
+ * 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 com.example.android.supportv4.view
+
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.os.Build
+import android.os.Bundle
+import android.os.SystemClock
+import android.util.Log
+import android.view.View
+import android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.Button
+import android.widget.CheckBox
+import android.widget.EditText
+import android.widget.Spinner
+import android.widget.TextView
+import androidx.annotation.RequiresApi
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.WindowInsetsCompat.Type.ime
+import androidx.core.view.WindowInsetsControllerCompat
+import com.example.android.supportv4.R
+import kotlin.concurrent.thread
+
+@SuppressLint("InlinedApi")
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+class WindowInsetsControllerPlayground : Activity() {
+
+ private val TAG = WindowInsetsControllerPlayground::class.java.name
+
+ var currentType: Int? = null
+
+ private lateinit var mRoot: View
+ private lateinit var editText: EditText
+ private lateinit var visibility: TextView
+ private lateinit var checkbox: CheckBox
+
+ @SuppressLint("SetTextI18n")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_insets_controller)
+ setActionBar(findViewById(R.id.toolbar))
+
+ mRoot = findViewById(R.id.root)
+ editText = findViewById(R.id.editText)
+ visibility = findViewById(R.id.visibility)
+ checkbox = findViewById(R.id.decorFitsSystemWindows)
+
+ WindowCompat.setDecorFitsSystemWindows(window, false)
+ ViewCompat.getWindowInsetsController(mRoot)!!.systemBarsBehavior =
+ WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+
+ Log.e(
+ TAG,
+ "FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS: " + (
+ window.attributes.flags and
+ FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS != 0
+ )
+ )
+
+ checkbox.apply {
+ isChecked = false
+ setOnCheckedChangeListener { _, isChecked ->
+ WindowCompat.setDecorFitsSystemWindows(window, isChecked)
+ }
+ }
+
+ setupTypeSpinner()
+ setupHideShowButtons()
+
+ ViewCompat.setOnApplyWindowInsetsListener(mRoot) { _: View?, insets: WindowInsetsCompat ->
+ val systemBarInsets = insets.getInsets(
+ ime() or
+ WindowInsetsCompat.Type.systemBars()
+ )
+ mRoot.setPadding(
+ systemBarInsets.left,
+ systemBarInsets.top,
+ systemBarInsets.right,
+ systemBarInsets.bottom
+ )
+ visibility.text =
+ "Inset visibility: " + currentType?.let { insets.isVisible(it) }?.toString()
+
+ WindowInsetsCompat.CONSUMED
+ }
+ }
+
+ private var visibilityThreadRunning = true
+
+ @SuppressLint("SetTextI18n")
+ override fun onResume() {
+ super.onResume()
+ thread {
+ visibilityThreadRunning = true
+ while (visibilityThreadRunning) {
+ visibility.post {
+ visibility.text =
+ currentType?.let {
+ ViewCompat.getRootWindowInsets(mRoot)?.isVisible(it).toString()
+ } + " " + window.attributes.flags + " " + SystemClock.elapsedRealtime()
+ }
+ Thread.sleep(500)
+ }
+ }
+ }
+
+ override fun onPause() {
+ super.onPause()
+ visibilityThreadRunning = false
+ }
+
+ private fun setupHideShowButtons() {
+ findViewById<Button>(R.id.btn_show).apply {
+ setOnClickListener { view ->
+ currentType?.let { type ->
+ ViewCompat.getWindowInsetsController(view)?.show(type)
+ }
+ }
+ }
+ findViewById<Button>(R.id.btn_hide).apply {
+ setOnClickListener {
+ currentType?.let { type ->
+ ViewCompat.getWindowInsetsController(it)?.hide(type)
+ }
+ }
+ }
+ }
+
+ private fun setupTypeSpinner() {
+ val types = mapOf(
+ "IME" to ime(),
+ "Navigation" to WindowInsetsCompat.Type.navigationBars(),
+ "System" to WindowInsetsCompat.Type.systemBars(),
+ "Status" to WindowInsetsCompat.Type.statusBars()
+ )
+ findViewById<Spinner>(R.id.spn_insets_type).apply {
+ adapter = ArrayAdapter<String>(
+ context, android.R.layout.simple_spinner_dropdown_item,
+ types.keys.toTypedArray()
+ )
+ onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onNothingSelected(parent: AdapterView<*>?) {
+ }
+
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (parent != null) {
+ currentType = types[parent.selectedItem]
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/Support4Demos/src/main/res/layout/activity_insets_controller.xml b/samples/Support4Demos/src/main/res/layout/activity_insets_controller.xml
new file mode 100644
index 0000000..f6230dc
--- /dev/null
+++ b/samples/Support4Demos/src/main/res/layout/activity_insets_controller.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2018 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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipToPadding="false"
+ android:id="@+id/root"
+ tools:targetApi="lollipop">
+
+ <Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="56dp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Spinner
+ android:id="@+id/spn_insets_type"
+ android:layout_width="200dp"
+ android:layout_height="wrap_content" />
+
+ <Button
+ android:id="@+id/btn_show"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Show" />
+
+ <Button
+ android:id="@+id/btn_hide"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Hide" />
+
+ </LinearLayout>
+
+ <CheckBox
+ android:id="@+id/decorFitsSystemWindows"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="setDecorFitsSystemWindows" />
+
+ <TextView
+ android:id="@+id/visibility"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="TextView" />
+
+ <FrameLayout
+ android:id="@+id/scrollView"
+ android:layout_height="0dp"
+ android:layout_width="match_parent"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:layout_weight="1">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_gravity="bottom"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="56dp"
+ android:background="@color/color1"
+ android:layout_gravity="start"
+ android:text="Hey, look at this buttery smooth animation!"
+ android:layout_marginRight="56dp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="56dp"
+ android:background="@color/color2"
+ android:layout_gravity="end"
+ android:text="Wow, that's pretty neat, how does this work?"
+ android:layout_marginRight="56dp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="56dp"
+ android:background="@color/color1"
+ android:layout_gravity="start"
+ android:text="Using the new WindowInsets animation system of course!"
+ android:layout_marginRight="56dp" />
+
+ </LinearLayout>
+
+ </FrameLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:orientation="horizontal">
+
+ <EditText
+ android:id="@+id/editText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0.9"
+ android:hint="Text message" />
+
+ <Button
+ android:id="@+id/floating_action_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:layout_weight="0.1"
+ android:drawableLeft="@drawable/ic_favorite"
+ android:drawableStart="@drawable/ic_favorite" />
+
+ </LinearLayout>
+</LinearLayout>
+
diff --git a/samples/Support4Demos/src/main/res/values/strings.xml b/samples/Support4Demos/src/main/res/values/strings.xml
index f1d3421..143b556 100644
--- a/samples/Support4Demos/src/main/res/values/strings.xml
+++ b/samples/Support4Demos/src/main/res/values/strings.xml
@@ -246,5 +246,6 @@
<string name="commit_content_support">View/Input Method/Commit Content</string>
<string name="insets_playground">View/WindowInsetsCompat</string>
+ <string name="insets_controller_playground">View/WindowInsetsControllerCompat</string>
<string name="insets_none">None yet...</string>
</resources>
diff --git a/security/security-crypto-ktx/src/androidTest/java/androidx/security/crypto/KtxTests.kt b/security/security-crypto-ktx/src/androidTest/java/androidx/security/crypto/KtxTests.kt
index c63c225..76ccfc6 100644
--- a/security/security-crypto-ktx/src/androidTest/java/androidx/security/crypto/KtxTests.kt
+++ b/security/security-crypto-ktx/src/androidTest/java/androidx/security/crypto/KtxTests.kt
@@ -41,8 +41,10 @@
// Delete all previous keys and shared preferences.
val parentDir = context.filesDir?.parent
?: throw IllegalStateException("filesDir?.parent is null?")
- var filePath = (parentDir + "/shared_prefs/" +
- "__androidx_security__crypto_encrypted_prefs__")
+ var filePath = (
+ parentDir + "/shared_prefs/" +
+ "__androidx_security__crypto_encrypted_prefs__"
+ )
var deletePrefFile = File(filePath)
deletePrefFile.delete()
val notEncryptedSharedPrefs = context.getSharedPreferences(
diff --git a/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/codegen/java/EnumSerializer.kt b/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/codegen/java/EnumSerializer.kt
index a2864c1..a8c0bcd 100644
--- a/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/codegen/java/EnumSerializer.kt
+++ b/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/codegen/java/EnumSerializer.kt
@@ -68,7 +68,7 @@
switchDefault {
addStatement(
"throw new \$T(\"Enum value \" + value.toString()\$W+ " +
- "\" does not have a serialization ID.\")",
+ "\" does not have a serialization ID.\")",
IllegalArgumentException::class.java
)
}
diff --git a/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/codegen/java/ext/TypeSpecExt.kt b/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/codegen/java/ext/TypeSpecExt.kt
index f6002ac..a798f93 100644
--- a/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/codegen/java/ext/TypeSpecExt.kt
+++ b/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/codegen/java/ext/TypeSpecExt.kt
@@ -60,11 +60,13 @@
vararg modifiers: Modifier,
init: MethodSpec.Builder.() -> Unit
) {
- addMethod(MethodSpec.methodBuilder(name).run {
- addModifiers(*modifiers)
- init()
- build()
- })
+ addMethod(
+ MethodSpec.methodBuilder(name).run {
+ addModifiers(*modifiers)
+ init()
+ build()
+ }
+ )
}
internal inline fun TypeSpec.Builder.overrideMethod(
diff --git a/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/processing/steps/EnumProcessingStep.kt b/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/processing/steps/EnumProcessingStep.kt
index d3e9f03..df770b2 100644
--- a/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/processing/steps/EnumProcessingStep.kt
+++ b/serialization/serialization-compiler/src/main/kotlin/androidx/serialization/compiler/processing/steps/EnumProcessingStep.kt
@@ -104,7 +104,7 @@
} else {
messager.error(enumClass) {
"Enum ${enumClass.qualifiedName} is not visible to its package and cannot " +
- "be serialized"
+ "be serialized"
}
}
@@ -126,7 +126,7 @@
} else {
messager.error(element) {
"To avoid unexpected behavior, all enum constants in a serializable " +
- "enum must be annotated with @EnumValue"
+ "enum must be annotated with @EnumValue"
}
hasError = true
}
diff --git a/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/EnumSerializerTest.kt b/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/EnumSerializerTest.kt
index 0827a49..bb7581c 100644
--- a/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/EnumSerializerTest.kt
+++ b/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/EnumSerializerTest.kt
@@ -27,7 +27,9 @@
class EnumSerializerTest {
@Test
fun test() {
- val enum = JavaFileObjects.forSourceString("com.example.TestEnum", """
+ val enum = JavaFileObjects.forSourceString(
+ "com.example.TestEnum",
+ """
package com.example;
import androidx.serialization.EnumValue;
@@ -40,10 +42,13 @@
@EnumValue(2)
TWO
}
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-disable max-line-length */
- val serializer = JavaFileObjects.forSourceString("com.example.TestEnumSerializer", """
+ val serializer = JavaFileObjects.forSourceString(
+ "com.example.TestEnumSerializer",
+ """
package com.example;
import androidx.annotation.NonNull;
@@ -83,7 +88,8 @@
}
}
}
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
assertThat(compile(enum))
diff --git a/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/processing/parsers/ParseReservedTest.kt b/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/processing/parsers/ParseReservedTest.kt
index 2964d8e..1e00920 100644
--- a/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/processing/parsers/ParseReservedTest.kt
+++ b/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/processing/parsers/ParseReservedTest.kt
@@ -56,12 +56,15 @@
private fun compile(reserved: String): Reserved {
val processor =
ReservedProcessor()
- val source = JavaFileObjects.forSourceString("TestClass", """
+ val source = JavaFileObjects.forSourceString(
+ "TestClass",
+ """
import androidx.serialization.Reserved;
$reserved
public final class TestClass {}
- """.trimIndent())
+ """.trimIndent()
+ )
assertThat(javac().withProcessors(processor).compile(source)).succeededWithoutWarnings()
return processor.reserved
}
diff --git a/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/processing/steps/EnumProcessingStepTest.kt b/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/processing/steps/EnumProcessingStepTest.kt
index 3d89f4e..8aefd65 100644
--- a/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/processing/steps/EnumProcessingStepTest.kt
+++ b/serialization/serialization-compiler/src/test/kotlin/androidx/serialization/compiler/processing/steps/EnumProcessingStepTest.kt
@@ -31,18 +31,25 @@
/** Unit tests for [EnumProcessingStep]. */
class EnumProcessingStepTest {
- private val enumValueCorrespondence = Correspondence.from({
+ private val enumValueCorrespondence = Correspondence.from(
+ {
actual: Enum.Value?, expected: Pair<Int, String>? ->
- if (actual != null && expected != null) {
- actual.id == expected.first && actual.element.simpleName.contentEquals(expected.second)
- } else {
- actual == null && expected == null
- }
- }, "has ID and name")
+ if (actual != null && expected != null) {
+ actual.id == expected.first &&
+ actual.element.simpleName.contentEquals(expected.second)
+ } else {
+ actual == null && expected == null
+ }
+ },
+ "has ID and name"
+ )
@Test
fun testParsing() {
- val enum = compileEnum(JavaFileObjects.forSourceString("TestEnum", """
+ val enum = compileEnum(
+ JavaFileObjects.forSourceString(
+ "TestEnum",
+ """
import androidx.serialization.EnumValue;
public enum TestEnum {
@@ -51,7 +58,9 @@
@EnumValue(1)
ONE
}
- """.trimIndent()))
+ """.trimIndent()
+ )
+ )
assertThat(enum.values)
.comparingElementsUsing(enumValueCorrespondence)
@@ -61,7 +70,9 @@
@Test
fun testInvalidPrivateEnum() {
- val testEnum = JavaFileObjects.forSourceString("com.example.PrivateEnumTest", """
+ val testEnum = JavaFileObjects.forSourceString(
+ "com.example.PrivateEnumTest",
+ """
package com.example;
import androidx.serialization.EnumValue;
@@ -71,15 +82,19 @@
@EnumValue(0) TEST
}
}
- """.trimIndent())
+ """.trimIndent()
+ )
assertThat(compile(testEnum)).hadErrorContaining(
- "Enum com.example.PrivateEnumTest.PrivateEnum is private and cannot be serialized")
+ "Enum com.example.PrivateEnumTest.PrivateEnum is private and cannot be serialized"
+ )
}
@Test
fun testInvalidPrivateNestedEnum() {
- val testEnum = JavaFileObjects.forSourceString("PrivateNestedEnumTest", """
+ val testEnum = JavaFileObjects.forSourceString(
+ "PrivateNestedEnumTest",
+ """
import androidx.serialization.EnumValue;
public class PrivateNestedEnumTest {
@@ -89,22 +104,27 @@
}
}
}
- """.trimIndent())
+ """.trimIndent()
+ )
assertThat(compile(testEnum)).hadErrorContaining(
- "Enum PrivateNestedEnumTest.NestedClass.NestedEnum is not visible to its package")
+ "Enum PrivateNestedEnumTest.NestedClass.NestedEnum is not visible to its package"
+ )
}
@Test
fun testInvalidEnumValueAnnotationLocation() {
- val testField = JavaFileObjects.forSourceString("EnumValueFieldTest", """
+ val testField = JavaFileObjects.forSourceString(
+ "EnumValueFieldTest",
+ """
import androidx.serialization.EnumValue;
public class EnumValueFieldTest {
@EnumValue(0)
public int foo;
}
- """.trimIndent())
+ """.trimIndent()
+ )
assertThat(compile(testField))
.hadErrorContaining("@EnumValue must annotate an enum constant")
@@ -112,7 +132,9 @@
@Test
fun testInvalidMissingEnumValue() {
- val testEnum = JavaFileObjects.forSourceString("MissingEnumValue", """
+ val testEnum = JavaFileObjects.forSourceString(
+ "MissingEnumValue",
+ """
import androidx.serialization.EnumValue;
public enum MissingEnumValue {
@@ -120,11 +142,13 @@
ZERO,
ONE
}
- """.trimIndent())
+ """.trimIndent()
+ )
assertThat(compile(testEnum)).hadErrorContaining(
"To avoid unexpected behavior, all enum constants in a serializable enum must be " +
- "annotated with @EnumValue")
+ "annotated with @EnumValue"
+ )
}
private fun compile(vararg sources: JavaFileObject): Compilation {
@@ -144,7 +168,7 @@
override fun initSteps(): List<ProcessingStep> {
return listOf(EnumProcessingStep(processingEnv) { enum = it })
- }
+ }
override fun getSupportedSourceVersion(): SourceVersion {
return SourceVersion.latest()
diff --git a/settings.gradle b/settings.gradle
index 0aec9fb..df822e9 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -62,17 +62,17 @@
includeProject(":activity:activity-lint", "activity/activity-lint")
includeProject(":activity:integration-tests:testapp", "activity/integration-tests/testapp")
includeProject(":ads-identifier", "ads/ads-identifier")
-includeProject(":ads-identifier:integration-tests:testapp", "ads/ads-identifier/integration-tests/testapp")
includeProject(":ads-identifier-benchmark", "ads/ads-identifier-benchmark")
includeProject(":ads-identifier-common", "ads/ads-identifier-common")
includeProject(":ads-identifier-provider", "ads/ads-identifier-provider")
includeProject(":ads-identifier-provider:integration-tests:testapp", "ads/ads-identifier-provider/integration-tests/testapp")
includeProject(":ads-identifier-testing", "ads/ads-identifier-testing")
+includeProject(":ads-identifier:integration-tests:testapp", "ads/ads-identifier/integration-tests/testapp")
includeProject(":annotation:annotation", "annotation/annotation")
-includeProject(":annotation:annotation-sampled", "annotation/annotation-sampled")
includeProject(":annotation:annotation-experimental", "annotation/annotation-experimental")
includeProject(":annotation:annotation-experimental-lint", "annotation/annotation-experimental-lint")
includeProject(":annotation:annotation-experimental-lint-integration-tests", "annotation/annotation-experimental-lint/integration-tests")
+includeProject(":annotation:annotation-sampled", "annotation/annotation-sampled")
includeProject(":appcompat:appcompat", "appcompat/appcompat")
includeProject(":appcompat:appcompat-benchmark", "appcompat/appcompat-benchmark")
includeProject(":appcompat:appcompat-lint", "appcompat/appcompat-lint")
@@ -81,15 +81,15 @@
includeProject(":appsearch:appsearch-compiler", "appsearch/compiler")
includeProject(":appsearch:appsearch-local-backend", "appsearch/local-backend")
includeProject(":arch:core-common", "arch/core-common")
-includeProject(":arch:core-testing", "arch/core-testing")
includeProject(":arch:core-runtime", "arch/core-runtime")
+includeProject(":arch:core-testing", "arch/core-testing")
includeProject(":asynclayoutinflater:asynclayoutinflater", "asynclayoutinflater/asynclayoutinflater")
includeProject(":autofill:autofill", "autofill/autofill")
+includeProject(":benchmark:benchmark-benchmark", "benchmark/benchmark")
includeProject(":benchmark:benchmark-common", "benchmark/common")
+includeProject(":benchmark:benchmark-gradle-plugin", "benchmark/gradle-plugin")
includeProject(":benchmark:benchmark-junit4", "benchmark/junit4")
includeProject(":benchmark:benchmark-macro", "benchmark/macro")
-includeProject(":benchmark:benchmark-benchmark", "benchmark/benchmark")
-includeProject(":benchmark:benchmark-gradle-plugin", "benchmark/gradle-plugin")
includeProject(":benchmark:integration-tests:dry-run-benchmark", "benchmark/integration-tests/dry-run-benchmark")
includeProject(":benchmark:integration-tests:startup-benchmark", "benchmark/integration-tests/startup-benchmark")
includeProject(":biometric:biometric", "biometric/biometric")
@@ -127,18 +127,18 @@
includeProject(":contentaccess:contentaccess-annotations", "contentaccess/contentaccess-annotations")
includeProject(":contentaccess:contentaccess-compiler", "contentaccess/contentaccess-compiler")
includeProject(":contentaccess:contentaccess-entities", "contentaccess/contentaccess-entities")
+includeProject(":contentaccess:contentaccess-runtime", "contentaccess/contentaccess-runtime")
includeProject(":contentaccess:integration-tests:testapp",
"contentaccess/integration-tests/testapp")
-includeProject(":contentaccess:contentaccess-runtime", "contentaccess/contentaccess-runtime")
includeProject(":contentpager:contentpager", "contentpager/contentpager")
includeProject(":coordinatorlayout:coordinatorlayout", "coordinatorlayout/coordinatorlayout")
+includeProject(":core-role", "core/core-role")
includeProject(":core:core", "core/core")
includeProject(":core:core-animation", "core/core-animation")
-includeProject(":core:core-animation-testing", "core/core-animation-testing")
includeProject(":core:core-animation-integration-tests:testapp", "core/core-animation-integration-tests/testapp")
+includeProject(":core:core-animation-testing", "core/core-animation-testing")
includeProject(":core:core-appdigest", "core/core-appdigest")
includeProject(":core:core-ktx", "core/core-ktx")
-includeProject(":core-role", "core/core-role")
includeProject(":cursoradapter:cursoradapter", "cursoradapter/cursoradapter")
includeProject(":customview:customview", "customview/customview")
includeProject(":datastore:datastore-core", "datastore/datastore-core")
@@ -153,19 +153,19 @@
includeProject(":dynamicanimation:dynamicanimation", "dynamic-animation/dynamic-animation")
includeProject(":dynamicanimation:dynamicanimation-ktx", "dynamic-animation/dynamic-animation-ktx")
includeProject(":emoji", "emoji/core")
-includeProject(":emoji-bundled", "emoji/bundled")
includeProject(":emoji-appcompat", "emoji/appcompat")
+includeProject(":emoji-bundled", "emoji/bundled")
includeProject(":enterprise-feedback", "enterprise/feedback")
includeProject(":enterprise-feedback-testing", "enterprise/feedback/testing")
includeProject(":exifinterface:exifinterface", "exifinterface/exifinterface")
+includeProject(":fakeannotations", "fakeannotations")
includeProject(":fragment:fragment", "fragment/fragment")
-includeProject(":fragment:integration-tests:testapp", "fragment/integration-tests/testapp")
includeProject(":fragment:fragment-ktx", "fragment/fragment-ktx")
includeProject(":fragment:fragment-lint", "fragment/fragment-lint")
includeProject(":fragment:fragment-testing", "fragment/fragment-testing")
includeProject(":fragment:fragment-testing-lint", "fragment/fragment-testing-lint")
includeProject(":fragment:fragment-truth", "fragment/fragment-truth")
-includeProject(":fakeannotations", "fakeannotations")
+includeProject(":fragment:integration-tests:testapp", "fragment/integration-tests/testapp")
includeProject(":gridlayout:gridlayout", "gridlayout/gridlayout")
includeProject(":heifwriter:heifwriter", "heifwriter/heifwriter")
includeProject(":hilt:hilt-common", "hilt/hilt-common")
@@ -182,11 +182,9 @@
includeProject(":ipc:ipc-compiler", "ipc/ipc-compiler")
includeProject(":ipc:ipc-runtime", "ipc/ipc-runtime")
includeProject(":jetifier-core", "jetifier/jetifier/core")
+includeProject(":jetifier-preprocessor", "jetifier/jetifier/preprocessor")
includeProject(":jetifier-processor", "jetifier/jetifier/processor")
includeProject(":jetifier-standalone", "jetifier/jetifier/standalone")
-includeProject(":jetifier-preprocessor", "jetifier/jetifier/preprocessor")
-includeProject(":lint-checks", "lint-checks")
-includeProject(":lint-checks:tests", "lint-checks/tests")
includeProject(":leanback:leanback", "leanback/leanback")
includeProject(":leanback:leanback-paging", "leanback/leanback-paging")
includeProject(":leanback:leanback-preference", "leanback/leanback-preference")
@@ -198,11 +196,11 @@
includeProject(":lifecycle:lifecycle-common-java8", "lifecycle/lifecycle-common-java8")
includeProject(":lifecycle:lifecycle-compiler", "lifecycle/lifecycle-compiler")
includeProject(":lifecycle:lifecycle-extensions", "lifecycle/lifecycle-extensions")
+includeProject(":lifecycle:lifecycle-livedata", "lifecycle/lifecycle-livedata")
includeProject(":lifecycle:lifecycle-livedata-core", "lifecycle/lifecycle-livedata-core")
includeProject(":lifecycle:lifecycle-livedata-core-ktx", "lifecycle/lifecycle-livedata-core-ktx")
includeProject(":lifecycle:lifecycle-livedata-core-ktx-lint", "lifecycle/lifecycle-livedata-core-ktx-lint")
includeProject(":lifecycle:lifecycle-livedata-core-truth", "lifecycle/lifecycle-livedata-core-truth")
-includeProject(":lifecycle:lifecycle-livedata", "lifecycle/lifecycle-livedata")
includeProject(":lifecycle:lifecycle-livedata-ktx", "lifecycle/lifecycle-livedata-ktx")
includeProject(":lifecycle:lifecycle-process", "lifecycle/lifecycle-process")
includeProject(":lifecycle:lifecycle-reactivestreams", "lifecycle/lifecycle-reactivestreams")
@@ -215,44 +213,46 @@
includeProject(":lifecycle:lifecycle-viewmodel", "lifecycle/lifecycle-viewmodel")
includeProject(":lifecycle:lifecycle-viewmodel-ktx", "lifecycle/lifecycle-viewmodel-ktx")
includeProject(":lifecycle:lifecycle-viewmodel-savedstate", "lifecycle/lifecycle-viewmodel-savedstate")
+includeProject(":lint-checks", "lint-checks")
+includeProject(":lint-checks:tests", "lint-checks/tests")
includeProject(":lint-demos:lint-demo-appcompat", "lint-demos/lint-demo-appcompat")
includeProject(":loader:loader", "loader/loader")
includeProject(":loader:loader-ktx", "loader/loader-ktx")
includeProject(":localbroadcastmanager:localbroadcastmanager", "localbroadcastmanager/localbroadcastmanager")
-includeProject(":media:media", "media/media")
+includeProject(":media2:integration-tests:testapp", "media2/integration-tests/testapp")
includeProject(":media2:media2-common", "media2/common")
+includeProject(":media2:media2-exoplayer", "media2/media2-exoplayer")
includeProject(":media2:media2-player", "media2/player")
includeProject(":media2:media2-session", "media2/session")
includeProject(":media2:media2-widget", "media2/widget")
-includeProject(":media2:media2-exoplayer", "media2/media2-exoplayer")
-includeProject(":media2:integration-tests:testapp", "media2/integration-tests/testapp")
+includeProject(":media:media", "media/media")
includeProject(":mediarouter:mediarouter", "mediarouter/mediarouter")
includeProject(":navigation:navigation-benchmark", "navigation/benchmark")
includeProject(":navigation:navigation-common", "navigation/navigation-common")
includeProject(":navigation:navigation-common-ktx", "navigation/navigation-common-ktx")
-includeProject(":navigation:navigation-dynamic-features-runtime", "navigation/navigation-dynamic-features-runtime")
includeProject(":navigation:navigation-dynamic-features-fragment", "navigation/navigation-dynamic-features-fragment")
+includeProject(":navigation:navigation-dynamic-features-runtime", "navigation/navigation-dynamic-features-runtime")
+includeProject(":navigation:navigation-fragment", "navigation/navigation-fragment")
+includeProject(":navigation:navigation-fragment-ktx", "navigation/navigation-fragment-ktx")
+includeProject(":navigation:navigation-integration-tests", "navigation/integration-tests")
+includeProject(":navigation:navigation-integration-tests:testapp", "navigation/integration-tests/testapp")
includeProject(":navigation:navigation-runtime", "navigation/navigation-runtime")
includeProject(":navigation:navigation-runtime-ktx", "navigation/navigation-runtime-ktx")
includeProject(":navigation:navigation-runtime-truth", "navigation/navigation-runtime-truth")
-includeProject(":navigation:navigation-testing", "navigation/navigation-testing")
-includeProject(":navigation:navigation-fragment", "navigation/navigation-fragment")
-includeProject(":navigation:navigation-fragment-ktx", "navigation/navigation-fragment-ktx")
-includeProject(":navigation:navigation-ui", "navigation/navigation-ui")
-includeProject(":navigation:navigation-ui-ktx", "navigation/navigation-ui-ktx")
-includeProject(":navigation:navigation-integration-tests", "navigation/integration-tests")
-includeProject(":navigation:navigation-integration-tests:testapp", "navigation/integration-tests/testapp")
includeProject(":navigation:navigation-safe-args-generator", "navigation/navigation-safe-args-generator")
includeProject(":navigation:navigation-safe-args-gradle-plugin", "navigation/navigation-safe-args-gradle-plugin")
+includeProject(":navigation:navigation-testing", "navigation/navigation-testing")
+includeProject(":navigation:navigation-ui", "navigation/navigation-ui")
+includeProject(":navigation:navigation-ui-ktx", "navigation/navigation-ui-ktx")
includeProject(":paging:integration-tests:testapp", "paging/integration-tests/testapp")
includeProject(":paging:paging-common", "paging/common")
includeProject(":paging:paging-common-ktx", "paging/common/ktx")
+includeProject(":paging:paging-guava", "paging/guava")
includeProject(":paging:paging-runtime", "paging/runtime")
includeProject(":paging:paging-runtime-ktx", "paging/runtime/ktx")
includeProject(":paging:paging-rxjava2", "paging/rxjava2")
includeProject(":paging:paging-rxjava2-ktx", "paging/rxjava2/ktx")
includeProject(":paging:paging-rxjava3", "paging/rxjava3")
-includeProject(":paging:paging-guava", "paging/guava")
includeProject(":paging:paging-samples", "paging/samples")
includeProject(":palette:palette", "palette/palette")
includeProject(":palette:palette-ktx", "palette/palette-ktx")
@@ -265,11 +265,13 @@
includeProject(":recyclerview:recyclerview-benchmark", "recyclerview/recyclerview-benchmark")
includeProject(":recyclerview:recyclerview-lint", "recyclerview/recyclerview-lint")
includeProject(":recyclerview:recyclerview-selection", "recyclerview/recyclerview-selection")
+includeProject(":remotecallback:remotecallback", "remotecallback/remotecallback")
+includeProject(":remotecallback:remotecallback-processor", "remotecallback/processor")
includeProject(":room:integration-tests:room-incremental-annotation-processing", "room/integration-tests/incremental-annotation-processing")
-includeProject(":room:integration-tests:room-testapp-noappcompat", "room/integration-tests/noappcompattestapp")
-includeProject(":room:integration-tests:room-testapp-autovalue", "room/integration-tests/autovaluetestapp")
includeProject(":room:integration-tests:room-testapp", "room/integration-tests/testapp")
+includeProject(":room:integration-tests:room-testapp-autovalue", "room/integration-tests/autovaluetestapp")
includeProject(":room:integration-tests:room-testapp-kotlin", "room/integration-tests/kotlintestapp")
+includeProject(":room:integration-tests:room-testapp-noappcompat", "room/integration-tests/noappcompattestapp")
includeProject(":room:room-benchmark", "room/benchmark")
includeProject(":room:room-common", "room/common")
includeProject(":room:room-compiler", "room/compiler")
@@ -281,10 +283,6 @@
includeProject(":room:room-rxjava2", "room/rxjava2")
includeProject(":room:room-rxjava3", "room/rxjava3")
includeProject(":room:room-testing", "room/testing")
-includeProject(":remotecallback:remotecallback-processor", "remotecallback/processor")
-includeProject(":remotecallback:remotecallback", "remotecallback/remotecallback")
-includeProject(":versionedparcelable:versionedparcelable-compiler", "versionedparcelable/versionedparcelable-compiler")
-includeProject(":versionedparcelable:versionedparcelable", "versionedparcelable/versionedparcelable")
includeProject(":savedstate:savedstate", "savedstate/savedstate")
includeProject(":savedstate:savedstate-ktx", "savedstate/savedstate-ktx")
includeProject(":security:security-biometric", "security/security-biometric")
@@ -297,72 +295,74 @@
includeProject(":serialization:serialization-runtime", "serialization/serialization-runtime")
includeProject(":serialization:serialization-runtime-parcel", "serialization/serialization-runtime-parcel")
includeProject(":serialization:serialization-runtime-proto", "serialization/serialization-runtime-proto")
-includeProject(":sharetarget:sharetarget", "sharetarget/sharetarget")
includeProject(":sharetarget:integration-tests:testapp", "sharetarget/integration-tests/testapp")
-includeProject(":slice-core", "slices/core")
-includeProject(":slice-view", "slices/view")
-includeProject(":slice-builders", "slices/builders")
-includeProject(":slice-test", "slices/test")
-includeProject(":slice-builders-ktx", "slices/builders/ktx")
+includeProject(":sharetarget:sharetarget", "sharetarget/sharetarget")
includeProject(":slice-benchmark", "slices/benchmark")
+includeProject(":slice-builders", "slices/builders")
+includeProject(":slice-builders-ktx", "slices/builders/ktx")
+includeProject(":slice-core", "slices/core")
includeProject(":slice-remotecallback", "slices/remotecallback")
+includeProject(":slice-test", "slices/test")
+includeProject(":slice-view", "slices/view")
includeProject(":slidingpanelayout:slidingpanelayout", "slidingpanelayout/slidingpanelayout")
-includeProject(":startup:startup-runtime", "startup/startup-runtime")
-includeProject(":startup:startup-runtime-lint", "startup/startup-runtime-lint")
+includeProject(":sqlite:integration-tests:inspection-room-testapp", "sqlite/integration-tests/inspection-room-testapp")
+includeProject(":sqlite:integration-tests:inspection-sqldelight-testapp", "sqlite/integration-tests/inspection-sqldelight-testapp")
+includeProject(":sqlite:sqlite", "sqlite/sqlite")
+includeProject(":sqlite:sqlite-framework", "sqlite/sqlite-framework")
+includeProject(":sqlite:sqlite-inspection", "sqlite/sqlite-inspection")
+includeProject(":sqlite:sqlite-ktx", "sqlite/sqlite-ktx")
includeProject(":startup:integration-tests:first-library", "startup/integration-tests/first-library")
includeProject(":startup:integration-tests:second-library", "startup/integration-tests/second-library")
includeProject(":startup:integration-tests:test-app", "startup/integration-tests/test-app")
-includeProject(":sqlite:sqlite", "sqlite/sqlite")
-includeProject(":sqlite:sqlite-ktx", "sqlite/sqlite-ktx")
-includeProject(":sqlite:sqlite-framework", "sqlite/sqlite-framework")
-includeProject(":sqlite:sqlite-inspection", "sqlite/sqlite-inspection")
-includeProject(":sqlite:integration-tests:inspection-room-testapp", "sqlite/integration-tests/inspection-room-testapp")
-includeProject(":sqlite:integration-tests:inspection-sqldelight-testapp", "sqlite/integration-tests/inspection-sqldelight-testapp")
+includeProject(":startup:startup-runtime", "startup/startup-runtime")
+includeProject(":startup:startup-runtime-lint", "startup/startup-runtime-lint")
includeProject(":swiperefreshlayout:swiperefreshlayout", "swiperefreshlayout/swiperefreshlayout")
includeProject(":test-screenshot", "test/screenshot")
includeProject(":test-screenshot-proto", "test/screenshot/proto")
-includeProject(":textclassifier:textclassifier", "textclassifier/textclassifier")
includeProject(":textclassifier:integration-tests:testapp", "textclassifier/integration-tests/testapp")
+includeProject(":textclassifier:textclassifier", "textclassifier/textclassifier")
includeProject(":tracing:tracing", "tracing/tracing")
includeProject(":tracing:tracing-ktx", "tracing/tracing-ktx")
includeProject(":transition:transition", "transition/transition")
includeProject(":transition:transition-ktx", "transition/transition-ktx")
includeProject(":tvprovider", "tv-provider")
includeProject(":tvprovider:tvprovider", "tv-provider/tv-provider")
+includeProject(":vectordrawable:integration-tests:testapp", "vectordrawable/integration-tests/testapp")
includeProject(":vectordrawable:vectordrawable", "vectordrawable/vectordrawable")
includeProject(":vectordrawable:vectordrawable-animated", "vectordrawable/vectordrawable-animated")
includeProject(":vectordrawable:vectordrawable-seekable", "vectordrawable/vectordrawable-seekable")
-includeProject(":vectordrawable:integration-tests:testapp", "vectordrawable/integration-tests/testapp")
-includeProject(":viewpager:viewpager", "viewpager/viewpager")
-includeProject(":viewpager2:viewpager2", "viewpager2/viewpager2")
+includeProject(":versionedparcelable:versionedparcelable", "versionedparcelable/versionedparcelable")
+includeProject(":versionedparcelable:versionedparcelable-compiler", "versionedparcelable/versionedparcelable-compiler")
includeProject(":viewpager2:integration-tests:testapp", "viewpager2/integration-tests/testapp")
+includeProject(":viewpager2:viewpager2", "viewpager2/viewpager2")
+includeProject(":viewpager:viewpager", "viewpager/viewpager")
includeProject(":wear:wear", "wear/wear")
includeProject(":wear:wear-complications-data", "wear/wear-complications-data")
includeProject(":wear:wear-complications-data-samples", "wear/wear-complications-data/samples")
-includeProject(":wear:wear-complications-rendering", "wear/wear-complications-rendering")
includeProject(":wear:wear-input", "wear/wear-input")
includeProject(":wear:wear-input-testing", "wear/wear-input-testing")
includeProject(":wear:wear-watchface", "wear/wear-watchface")
+includeProject(":wear:wear-watchface-complications-rendering", "wear/wear-watchface-complications-rendering")
includeProject(":wear:wear-watchface-data", "wear/wear-watchface-data")
includeProject(":wear:wear-watchface-samples", "wear/wear-watchface/samples")
includeProject(":wear:wear-watchface-style", "wear/wear-watchface-style")
-includeProject(":webkit:webkit", "webkit/webkit")
includeProject(":webkit:integration-tests:testapp", "webkit/integration-tests/testapp")
+includeProject(":webkit:webkit", "webkit/webkit")
includeProject(":window:window", "window/window")
includeProject(":window:window-extensions", "window/window-extensions")
-includeProject(":window:window-sidecar", "window/window-sidecar")
includeProject(":window:window-samples", "window/window-samples")
-includeProject(":work:work-runtime", "work/workmanager")
+includeProject(":window:window-sidecar", "window/window-sidecar")
+includeProject(":work:integration-tests:testapp", "work/integration-tests/testapp")
+includeProject(":work:work-benchmark", "work/workmanager-benchmark")
includeProject(":work:work-gcm", "work/workmanager-gcm")
+includeProject(":work:work-inspection", "work/workmanager-inspection")
+includeProject(":work:work-multiprocess", "work/workmanager-multiprocess")
+includeProject(":work:work-runtime", "work/workmanager")
includeProject(":work:work-runtime-ktx", "work/workmanager-ktx")
+includeProject(":work:work-runtime-lint", "work/workmanager-lint")
includeProject(":work:work-rxjava2", "work/workmanager-rxjava2")
includeProject(":work:work-rxjava3", "work/workmanager-rxjava3")
includeProject(":work:work-testing", "work/workmanager-testing")
-includeProject(":work:work-runtime-lint", "work/workmanager-lint")
-includeProject(":work:work-benchmark", "work/workmanager-benchmark")
-includeProject(":work:work-multiprocess", "work/workmanager-multiprocess")
-includeProject(":work:work-inspection", "work/workmanager-inspection")
-includeProject(":work:integration-tests:testapp", "work/integration-tests/testapp")
/////////////////////////////
//
diff --git a/sqlite/integration-tests/inspection-sqldelight-testapp/src/androidTest/java/androidx/sqlite/inspection/SqlDelightInvalidationTest.kt b/sqlite/integration-tests/inspection-sqldelight-testapp/src/androidTest/java/androidx/sqlite/inspection/SqlDelightInvalidationTest.kt
index 69c6847..7770c1d 100644
--- a/sqlite/integration-tests/inspection-sqldelight-testapp/src/androidTest/java/androidx/sqlite/inspection/SqlDelightInvalidationTest.kt
+++ b/sqlite/integration-tests/inspection-sqldelight-testapp/src/androidTest/java/androidx/sqlite/inspection/SqlDelightInvalidationTest.kt
@@ -65,7 +65,8 @@
openedDb = db
super.onCreate(db)
}
- })
+ }
+ )
}
@Test
diff --git a/sqlite/integration-tests/inspection-sqldelight-testapp/src/main/generated/androidx/sqlite/inspection/sqldeligttestapp/app/DatabaseImpl.kt b/sqlite/integration-tests/inspection-sqldelight-testapp/src/main/generated/androidx/sqlite/inspection/sqldeligttestapp/app/DatabaseImpl.kt
index 1c56ea4..cb63403 100644
--- a/sqlite/integration-tests/inspection-sqldelight-testapp/src/main/generated/androidx/sqlite/inspection/sqldeligttestapp/app/DatabaseImpl.kt
+++ b/sqlite/integration-tests/inspection-sqldelight-testapp/src/main/generated/androidx/sqlite/inspection/sqldeligttestapp/app/DatabaseImpl.kt
@@ -52,12 +52,14 @@
override fun create(driver: SqlDriver) {
driver.execute(
- null, """
+ null,
+ """
|CREATE TABLE TestEntity(
| id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
| value TEXT NOT NULL
|)
- """.trimMargin(), 0
+ """.trimMargin(),
+ 0
)
}
@@ -95,12 +97,14 @@
override fun insertOrReplace(value: String) {
driver.execute(
- -2020431062, """
+ -2020431062,
+ """
|INSERT OR REPLACE INTO TestEntity(
| value
|)
|VALUES (?1)
- """.trimMargin(), 1
+ """.trimMargin(),
+ 1
) {
bindString(1, value)
}
diff --git a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/DatabaseExtensions.kt b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/DatabaseExtensions.kt
index 718f39b..d72b712 100644
--- a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/DatabaseExtensions.kt
+++ b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/DatabaseExtensions.kt
@@ -35,10 +35,12 @@
fun SQLiteDatabase.insertValues(table: Table, vararg values: String) {
assertThat(values).isNotEmpty()
assertThat(values).hasLength(table.columns.size)
- execSQL(values.joinToString(
- prefix = "INSERT INTO ${table.name} VALUES(",
- postfix = ");"
- ) { it })
+ execSQL(
+ values.joinToString(
+ prefix = "INSERT INTO ${table.name} VALUES(",
+ postfix = ");"
+ ) { it }
+ )
}
fun Database.createInstance(
@@ -75,8 +77,8 @@
postfix = "$primaryKeyPart )${if (isView) " AS $viewQuery" else ""};"
) {
it.name +
- "${if (isView) "" else " ${it.type}"} " +
- (if (it.isNotNull) "NOT NULL " else "") +
- (if (it.isUnique) "UNIQUE " else "")
+ "${if (isView) "" else " ${it.type}"} " +
+ (if (it.isNotNull) "NOT NULL " else "") +
+ (if (it.isUnique) "UNIQUE " else "")
}
}
diff --git a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/GetSchemaTest.kt b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/GetSchemaTest.kt
index 65e475d..7c482d6 100644
--- a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/GetSchemaTest.kt
+++ b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/GetSchemaTest.kt
@@ -152,7 +152,8 @@
Database("db1").createInstance(temporaryFolder).also {
it.execSQL("CREATE TABLE t1 (c2 INTEGER PRIMARY KEY AUTOINCREMENT)")
it.execSQL("INSERT INTO t1 VALUES(3)")
- })
+ }
+ )
testEnvironment.sendCommand(createGetSchemaCommand(databaseId)).let { response ->
val tableNames = response.getSchema.tablesList.map { it.name }
assertThat(tableNames).isEqualTo(listOf("t1"))
@@ -166,7 +167,8 @@
assertThat(response.hasErrorOccurred()).isEqualTo(true)
val error = response.errorOccurred.content
assertThat(error.message).contains(
- "Unable to perform an operation on database (id=$databaseId).")
+ "Unable to perform an operation on database (id=$databaseId)."
+ )
assertThat(error.message).contains("The database may have already been closed.")
assertThat(error.recoverability.isRecoverable).isEqualTo(true)
assertThat(error.errorCodeValue).isEqualTo(
@@ -180,54 +182,56 @@
onDatabaseCreated: (SQLiteDatabase) -> Unit = {}
) =
runBlocking {
- assertThat(alreadyOpenDatabases).isNotEmpty() // sanity check
+ assertThat(alreadyOpenDatabases).isNotEmpty() // sanity check
- testEnvironment.registerAlreadyOpenDatabases(alreadyOpenDatabases.map {
- it.createInstance(temporaryFolder).also { db -> onDatabaseCreated(db) }
- })
- testEnvironment.sendCommand(createTrackDatabasesCommand())
- val databaseConnections =
- alreadyOpenDatabases.indices.map { testEnvironment.receiveEvent().databaseOpened }
-
- val schemas =
- databaseConnections
- .sortedBy { it.path }
- .map {
- testEnvironment.sendCommand(createGetSchemaCommand(it.databaseId)).getSchema
+ testEnvironment.registerAlreadyOpenDatabases(
+ alreadyOpenDatabases.map {
+ it.createInstance(temporaryFolder).also { db -> onDatabaseCreated(db) }
}
+ )
+ testEnvironment.sendCommand(createTrackDatabasesCommand())
+ val databaseConnections =
+ alreadyOpenDatabases.indices.map { testEnvironment.receiveEvent().databaseOpened }
- alreadyOpenDatabases
- .sortedBy { it.name }
- .zipSameSize(schemas)
- .forEach { (expectedSchema, actualSchema) ->
- val expectedTables = expectedSchema.tables.sortedBy { it.name }
- val actualTables = actualSchema.tablesList.sortedBy { it.name }
-
- expectedTables
- .zipSameSize(actualTables)
- .forEach { (expectedTable, actualTable) ->
- assertThat(actualTable.name).isEqualTo(expectedTable.name)
- assertThat(actualTable.isView).isEqualTo(expectedTable.isView)
-
- val expectedColumns = expectedTable.columns.sortedBy { it.name }
- val actualColumns = actualTable.columnsList.sortedBy { it.name }
-
- expectedColumns
- .adjustForSinglePrimaryKey()
- .zipSameSize(actualColumns)
- .forEach { (expectedColumn, actualColumnProto) ->
- val actualColumn = Column(
- name = actualColumnProto.name,
- type = actualColumnProto.type,
- primaryKey = actualColumnProto.primaryKey,
- isNotNull = actualColumnProto.isNotNull,
- isUnique = actualColumnProto.isUnique
- )
- assertThat(actualColumn).isEqualTo(expectedColumn)
- }
+ val schemas =
+ databaseConnections
+ .sortedBy { it.path }
+ .map {
+ testEnvironment.sendCommand(createGetSchemaCommand(it.databaseId)).getSchema
}
- }
- }
+
+ alreadyOpenDatabases
+ .sortedBy { it.name }
+ .zipSameSize(schemas)
+ .forEach { (expectedSchema, actualSchema) ->
+ val expectedTables = expectedSchema.tables.sortedBy { it.name }
+ val actualTables = actualSchema.tablesList.sortedBy { it.name }
+
+ expectedTables
+ .zipSameSize(actualTables)
+ .forEach { (expectedTable, actualTable) ->
+ assertThat(actualTable.name).isEqualTo(expectedTable.name)
+ assertThat(actualTable.isView).isEqualTo(expectedTable.isView)
+
+ val expectedColumns = expectedTable.columns.sortedBy { it.name }
+ val actualColumns = actualTable.columnsList.sortedBy { it.name }
+
+ expectedColumns
+ .adjustForSinglePrimaryKey()
+ .zipSameSize(actualColumns)
+ .forEach { (expectedColumn, actualColumnProto) ->
+ val actualColumn = Column(
+ name = actualColumnProto.name,
+ type = actualColumnProto.type,
+ primaryKey = actualColumnProto.primaryKey,
+ isNotNull = actualColumnProto.isNotNull,
+ isUnique = actualColumnProto.isUnique
+ )
+ assertThat(actualColumn).isEqualTo(expectedColumn)
+ }
+ }
+ }
+ }
// The sole primary key in a table is by definition unique
private fun List<Column>.adjustForSinglePrimaryKey(): List<Column> =
diff --git a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/InvalidationTest.kt b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/InvalidationTest.kt
index 3d4d6b3..7918eea 100644
--- a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/InvalidationTest.kt
+++ b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/InvalidationTest.kt
@@ -53,7 +53,8 @@
"execute()V",
"executeInsert()J",
"executeUpdateDelete()I"
- ).map { it to SQLiteStatement::class.java })
+ ).map { it to SQLiteStatement::class.java }
+ )
@Test
fun test_end_transaction_hook_method() =
@@ -69,7 +70,7 @@
expectedHooks.forEach { (method, clazz) ->
val hook = hooks.filter { hook ->
hook.originMethod == method &&
- hook.originClass == clazz
+ hook.originClass == clazz
}
assertThat(hook).hasSize(1)
@@ -124,12 +125,12 @@
// Hook method signatures
val rawQueryMethodSignature = "rawQueryWithFactory(" +
- "Landroid/database/sqlite/SQLiteDatabase\$CursorFactory;" +
- "Ljava/lang/String;" +
- "[Ljava/lang/String;" +
- "Ljava/lang/String;" +
- "Landroid/os/CancellationSignal;" +
- ")Landroid/database/Cursor;"
+ "Landroid/database/sqlite/SQLiteDatabase\$CursorFactory;" +
+ "Ljava/lang/String;" +
+ "[Ljava/lang/String;" +
+ "Ljava/lang/String;" +
+ "Landroid/os/CancellationSignal;" +
+ ")Landroid/database/Cursor;"
val getCountMethodSignature = "getCount()I"
val onMoveSignatureMethodSignature = "onMove(II)Z"
diff --git a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/ProtoExtensions.kt b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/ProtoExtensions.kt
index 2527dd90..333f1e7 100644
--- a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/ProtoExtensions.kt
+++ b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/ProtoExtensions.kt
@@ -81,7 +81,8 @@
QueryParameterValue.newBuilder()
.also { builder -> if (param != null) builder.stringValue = param }
.build()
- })
+ }
+ )
}
.build()
).build()
diff --git a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/QueryTest.kt b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/QueryTest.kt
index b4e0595..03581a9 100644
--- a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/QueryTest.kt
+++ b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/QueryTest.kt
@@ -124,7 +124,8 @@
assertThat(response.hasErrorOccurred()).isEqualTo(true)
val error = response.errorOccurred.content
assertThat(error.message).contains(
- "Unable to perform an operation on database (id=$databaseId).")
+ "Unable to perform an operation on database (id=$databaseId)."
+ )
assertThat(error.message).contains("The database may have already been closed.")
assertThat(error.stackTrace).isEqualTo("")
assertThat(error.recoverability.isRecoverable).isEqualTo(true)
@@ -258,8 +259,8 @@
table2 to arrayOf("3", "'C'")
),
query = "select * from " +
- "(select * from ${table2.name} where id > $paramNameLeft) " +
- "where id < $paramNameRight",
+ "(select * from ${table2.name} where id > $paramNameLeft) " +
+ "where id < $paramNameRight",
queryParams = listOf("1", "3"),
expectedValues = listOf(listOf(2, "B")),
expectedTypes = listOf(listOf("integer", "text")),
@@ -462,10 +463,12 @@
fun test_drop_table() = runBlocking {
// given
val database = Database("db1", table1, table2)
- val databaseId = inspectDatabase(database.createInstance(temporaryFolder).also {
- it.insertValues(table2, "1", "'1'")
- it.insertValues(table2, "2", "'2'")
- })
+ val databaseId = inspectDatabase(
+ database.createInstance(temporaryFolder).also {
+ it.insertValues(table2, "1", "'1'")
+ it.insertValues(table2, "2", "'2'")
+ }
+ )
val initialTotalChanges = queryTotalChanges(databaseId)
assertThat(querySchema(databaseId)).isNotEmpty()
diff --git a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/SqliteInspectorTestEnvironment.kt b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/SqliteInspectorTestEnvironment.kt
index 59a8edb..706dced 100644
--- a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/SqliteInspectorTestEnvironment.kt
+++ b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/SqliteInspectorTestEnvironment.kt
@@ -51,7 +51,8 @@
InspectorTester(
inspectorId = SQLITE_INSPECTOR_ID,
environment = DefaultTestInspectorEnvironment(
- TestInspectorExecutors(job, ioExecutorOverride), artTooling)
+ TestInspectorExecutors(job, ioExecutorOverride), artTooling
+ )
)
}
}
diff --git a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/TrackDatabasesTest.kt b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/TrackDatabasesTest.kt
index 583dcfc..01b9625 100644
--- a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/TrackDatabasesTest.kt
+++ b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/TrackDatabasesTest.kt
@@ -39,26 +39,26 @@
import java.io.File
private const val OPEN_DATABASE_COMMAND_SIGNATURE_API11: String = "openDatabase" +
- "(" +
- "Ljava/lang/String;" +
- "Landroid/database/sqlite/SQLiteDatabase\$CursorFactory;" +
- "I" +
- "Landroid/database/DatabaseErrorHandler;" +
- ")" +
- "Landroid/database/sqlite/SQLiteDatabase;"
+ "(" +
+ "Ljava/lang/String;" +
+ "Landroid/database/sqlite/SQLiteDatabase\$CursorFactory;" +
+ "I" +
+ "Landroid/database/DatabaseErrorHandler;" +
+ ")" +
+ "Landroid/database/sqlite/SQLiteDatabase;"
private const val OPEN_DATABASE_COMMAND_SIGNATURE_API27: String = "openDatabase" +
- "(" +
- "Ljava/io/File;" +
- "Landroid/database/sqlite/SQLiteDatabase\$OpenParams;" +
- ")" +
- "Landroid/database/sqlite/SQLiteDatabase;"
+ "(" +
+ "Ljava/io/File;" +
+ "Landroid/database/sqlite/SQLiteDatabase\$OpenParams;" +
+ ")" +
+ "Landroid/database/sqlite/SQLiteDatabase;"
private const val CREATE_IN_MEMORY_DATABASE_COMMAND_SIGNATURE_API27 = "createInMemory" +
- "(" +
- "Landroid/database/sqlite/SQLiteDatabase\$OpenParams;" +
- ")" +
- "Landroid/database/sqlite/SQLiteDatabase;"
+ "(" +
+ "Landroid/database/sqlite/SQLiteDatabase\$OpenParams;" +
+ ")" +
+ "Landroid/database/sqlite/SQLiteDatabase;"
private const val ALL_REFERENCES_RELEASED_COMMAND_SIGNATURE = "onAllReferencesReleased()V"
@@ -116,20 +116,20 @@
assertThat(hookEntries).hasSize(wantedSignatures.size)
assertThat(hookEntries.map { it.originMethod }.containsAll(wantedSignatures)).isTrue()
hookEntries.forEachIndexed { ix, entry ->
- // expect one exit hook tracking database open events
- assertThat(entry).isInstanceOf(Hook.ExitHook::class.java)
- assertThat(entry.originClass.name).isEqualTo(SQLiteDatabase::class.java.name)
+ // expect one exit hook tracking database open events
+ assertThat(entry).isInstanceOf(Hook.ExitHook::class.java)
+ assertThat(entry.originClass.name).isEqualTo(SQLiteDatabase::class.java.name)
- // verify that executing the registered hook will result in tracking events
- testEnvironment.assertNoQueuedEvents()
- @Suppress("UNCHECKED_CAST")
- val exitHook = entry.asExitHook as ExitHook<SQLiteDatabase>
- val database = Database("db3_$ix").createInstance(temporaryFolder)
- assertThat(exitHook.onExit(database)).isSameInstanceAs(database)
- testEnvironment.receiveEvent().let { event ->
- assertThat(event.databaseOpened.path).isEqualTo(database.displayName)
- }
+ // verify that executing the registered hook will result in tracking events
+ testEnvironment.assertNoQueuedEvents()
+ @Suppress("UNCHECKED_CAST")
+ val exitHook = entry.asExitHook as ExitHook<SQLiteDatabase>
+ val database = Database("db3_$ix").createInstance(temporaryFolder)
+ assertThat(exitHook.onExit(database)).isSameInstanceAs(database)
+ testEnvironment.receiveEvent().let { event ->
+ assertThat(event.databaseOpened.path).isEqualTo(database.displayName)
}
+ }
assertThat(testEnvironment.consumeRegisteredHooks()).isEmpty()
}
diff --git a/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/EnsureInitializerMetadataDetector.kt b/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/EnsureInitializerMetadataDetector.kt
index 39a2494..4da10fc 100644
--- a/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/EnsureInitializerMetadataDetector.kt
+++ b/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/EnsureInitializerMetadataDetector.kt
@@ -53,7 +53,7 @@
companion object {
private const val DESCRIPTION = "Every Initializer needs to be accompanied by a " +
- "corresponding <meta-data> entry in the AndroidManifest.xml file."
+ "corresponding <meta-data> entry in the AndroidManifest.xml file."
val ISSUE = Issue.create(
id = "EnsureInitializerMetadata",
diff --git a/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/InitializerConstructorTest.kt b/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/InitializerConstructorTest.kt
index 82bec33..0f3488a 100644
--- a/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/InitializerConstructorTest.kt
+++ b/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/InitializerConstructorTest.kt
@@ -80,7 +80,7 @@
class TestInitializer(val int: Int): Initializer<Unit> {
^
1 errors, 0 warnings
- """.trimIndent()
+ """.trimIndent()
)
/* ktlint-enable max-line-length */
}
diff --git a/transition/transition/src/androidTest/java/androidx/transition/EpicenterTest.kt b/transition/transition/src/androidTest/java/androidx/transition/EpicenterTest.kt
index 4e2c62c..6e48dbf 100644
--- a/transition/transition/src/androidTest/java/androidx/transition/EpicenterTest.kt
+++ b/transition/transition/src/androidTest/java/androidx/transition/EpicenterTest.kt
@@ -89,11 +89,14 @@
private fun setupTestView(): View {
val view = View(rule.activity)
InstrumentationRegistry.getInstrumentation().runOnMainSync {
- rule.activity.root.addView(view, FrameLayout.LayoutParams(100, 100)
- .apply {
- leftMargin = 50
- topMargin = 50
- })
+ rule.activity.root.addView(
+ view,
+ FrameLayout.LayoutParams(100, 100)
+ .apply {
+ leftMargin = 50
+ topMargin = 50
+ }
+ )
view.left = 50
view.top = 50
view.right = 150
diff --git a/transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionTest.kt b/transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionTest.kt
index 96764c3..8380e9a 100644
--- a/transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionTest.kt
+++ b/transition/transition/src/androidTest/java/androidx/transition/FragmentTransitionTest.kt
@@ -876,8 +876,10 @@
fail("Expected IllegalArgumentException")
} catch (e: IllegalArgumentException) {
assertThat(e)
- .hasMessageThat().contains("A shared element with the target name 'blueSquare' " +
- "has already been added to the transaction.")
+ .hasMessageThat().contains(
+ "A shared element with the target name 'blueSquare' " +
+ "has already been added to the transaction."
+ )
}
try {
@@ -885,8 +887,10 @@
fail("Expected IllegalArgumentException")
} catch (e: IllegalArgumentException) {
assertThat(e)
- .hasMessageThat().contains("A shared element with the source name 'blueSquare' " +
- "has already been added to the transaction.")
+ .hasMessageThat().contains(
+ "A shared element with the source name 'blueSquare' " +
+ "has already been added to the transaction."
+ )
}
}
diff --git a/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/DesktopComposeTestRule.kt b/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/DesktopComposeTestRule.kt
index fdfb190..43e2151 100644
--- a/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/DesktopComposeTestRule.kt
+++ b/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/DesktopComposeTestRule.kt
@@ -17,8 +17,6 @@
package androidx.ui.test
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.EmbeddingContext
-import androidx.compose.runtime.EmbeddingContextFactory
import androidx.compose.runtime.ExperimentalComposeApi
import androidx.compose.runtime.Recomposer
import androidx.compose.runtime.snapshots.Snapshot
@@ -27,12 +25,10 @@
import androidx.compose.ui.platform.setContent
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import org.jetbrains.skija.Surface
import org.junit.runner.Description
import org.junit.runners.model.Statement
-import java.awt.Component
import java.util.LinkedList
import java.util.concurrent.ExecutionException
import java.util.concurrent.FutureTask
@@ -51,7 +47,7 @@
class DesktopComposeTestRule(
private val disableTransitions: Boolean = false,
private val disableBlinkingCursor: Boolean = true
-) : ComposeTestRuleJUnit, EmbeddingContext {
+) : ComposeTestRuleJUnit {
companion object {
init {
@@ -62,6 +58,7 @@
}
var owners: DesktopOwners? = null
+ private var owner: DesktopOwner? = null
override val clockTestRule: AnimationClockTestRule = DesktopAnimationClockTestRule()
@@ -76,9 +73,10 @@
current = this
return object : Statement() {
override fun evaluate() {
- EmbeddingContextFactory = fun() = this@DesktopComposeTestRule
base.evaluate()
runExecutionQueue()
+ owner?.dispose()
+ owner = null
}
}
}
@@ -129,18 +127,19 @@
}
override fun setContent(composable: @Composable () -> Unit) {
+ check(owner == null) {
+ "Cannot call setContent twice per test!"
+ }
val surface = Surface.makeRasterN32Premul(displaySize.width, displaySize.height)
val canvas = surface.canvas
- val component = object : Component() {}
- val owners = DesktopOwners(component = component, invalidate = {}).also {
+ val owners = DesktopOwners(invalidate = {}).also {
owners = it
}
val owner = DesktopOwner(owners)
owner.setContent(composable)
owner.setSize(displaySize.width, displaySize.height)
+ owner.measureAndLayout()
owner.draw(canvas)
+ this.owner = owner
}
-
- override fun isMainThread() = true
- override fun mainThreadCompositionContext() = Dispatchers.Default
}
\ No newline at end of file
diff --git a/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/SkijaTest.kt b/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/SkijaTest.kt
index cdbb9fe..8346e9b 100644
--- a/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/SkijaTest.kt
+++ b/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/SkijaTest.kt
@@ -15,16 +15,13 @@
*/
package androidx.ui.test
-import androidx.compose.runtime.EmbeddingContext
-import androidx.compose.runtime.EmbeddingContextFactory
-import kotlinx.coroutines.Dispatchers
import org.jetbrains.skija.Surface
import org.jetbrains.skiko.Library
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
import java.io.File
import java.security.MessageDigest
-import org.junit.rules.TestRule
-import org.junit.runners.model.Statement
-import org.junit.runner.Description
import java.util.LinkedList
// TODO: replace with androidx.test.screenshot.proto.ScreenshotResultProto after MPP
@@ -178,9 +175,7 @@
}
}
-class ScreenshotTestRule internal constructor(val config: GoldenConfig) :
- TestRule,
- EmbeddingContext {
+class ScreenshotTestRule internal constructor(val config: GoldenConfig) : TestRule {
private lateinit var testIdentifier: String
private lateinit var album: SkijaTestAlbum
@@ -195,13 +190,9 @@
override fun apply(base: Statement, description: Description?): Statement {
return object : Statement() {
override fun evaluate() {
- EmbeddingContextFactory = fun() = this@ScreenshotTestRule
album = SkijaTestAlbum(config)
- testIdentifier = "${description!!.className}_${description.methodName}".replace(
- "" +
- ".",
- "_"
- )
+ testIdentifier = "${description!!.className}_${description.methodName}"
+ .replace(".", "_").replace(",", "_").replace(" ", "_").replace("__", "_")
base.evaluate()
runExecutionQueue()
handleReport(album.check())
@@ -242,7 +233,4 @@
}
}
}
-
- override fun isMainThread() = true
- override fun mainThreadCompositionContext() = Dispatchers.Main
}
diff --git a/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/TestComposeWindow.kt b/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/TestComposeWindow.kt
index b0989d9..2ede091 100644
--- a/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/TestComposeWindow.kt
+++ b/ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/TestComposeWindow.kt
@@ -16,7 +16,6 @@
package androidx.ui.test
-import androidx.compose.desktop.initCompose
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Providers
import androidx.compose.ui.platform.DesktopOwner
@@ -26,7 +25,6 @@
import androidx.compose.ui.platform.setContent
import androidx.compose.ui.unit.Density
import org.jetbrains.skija.Surface
-import java.awt.Component
class TestComposeWindow(
val width: Int,
@@ -36,8 +34,7 @@
) {
val surface = Surface.makeRasterN32Premul(width, height)
val canvas = surface.canvas
- val component = object : Component() {}
- val owners = DesktopOwners(component = component, invalidate = {})
+ val owners = DesktopOwners(invalidate = {})
fun setContent(content: @Composable () -> Unit): DesktopOwners {
val owner = DesktopOwner(owners, density)
@@ -49,6 +46,7 @@
}
}
owner.setSize(width, height)
+ owner.measureAndLayout()
owner.draw(canvas)
return owners
}
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/BoundsTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/BoundsTest.kt
index 66b242f..818c550 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/BoundsTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/BoundsTest.kt
@@ -66,13 +66,14 @@
activityTestRule.runOnUiThread {
val tree = slotTableRecord.store.first().asTree()
+
val boundingBoxes = tree.firstOrNull {
- it.position?.contains("BoundsTest.kt") == true && it.box.right > 0
+ it.location?.sourceFile?.equals("BoundsTest.kt") == true && it.box.right > 0
}!!
.all()
.filter {
- val name = it.position
- name != null && name.contains("BoundsTest.kt")
+ val name = it.location?.sourceFile
+ name != null && name.equals("BoundsTest.kt")
}
.map {
it.box.left
@@ -80,7 +81,6 @@
.distinct()
.sorted()
.toTypedArray()
-
with(Density(activityTestRule.activity)) {
println(boundingBoxes.contentDeepToString())
arrayOf(
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ModifierInfoTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ModifierInfoTest.kt
index 10f3408..2ac5f9f 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ModifierInfoTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ModifierInfoTest.kt
@@ -63,7 +63,7 @@
activityTestRule.runOnUiThread {
val tree = slotTableRecord.store.first().asTree()
val firstGroup = tree.firstOrNull {
- it.position?.contains("ModifierInfoTest.kt") == true && it.box.right > 0
+ it.location?.sourceFile?.equals("ModifierInfoTest.kt") == true && it.box.right > 0
}!!
val modifierInfoItems = firstGroup.all()
.filter { it.modifierInfo.isNotEmpty() }
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt
index 01d2690..0aaf782 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt
@@ -56,8 +56,10 @@
positionedLatch = CountDownLatch(1)
activityTestRule.onUiThread {
activity.setContent {
- Box(Modifier.onGloballyPositioned { positionedLatch.countDown() }
- .fillMaxSize()) {
+ Box(
+ Modifier.onGloballyPositioned { positionedLatch.countDown() }
+ .fillMaxSize()
+ ) {
composable()
}
}
@@ -82,8 +84,10 @@
AndroidOwner.onAndroidOwnerCreatedCallback = null
}
activity.setContent {
- Box(Modifier.onGloballyPositioned { positionedLatch.countDown() }
- .fillMaxSize()) {
+ Box(
+ Modifier.onGloballyPositioned { positionedLatch.countDown() }
+ .fillMaxSize()
+ ) {
content()
}
}
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/inspector/ParameterFactoryTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/inspector/ParameterFactoryTest.kt
index 4e2299c..6000d3a 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/inspector/ParameterFactoryTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/inspector/ParameterFactoryTest.kt
@@ -18,6 +18,7 @@
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
+import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
@@ -186,10 +187,12 @@
val preAPI28 = { api <= 28 }
assertThat(lookup(SolidColor(Color.Red)))
.isEqualTo(ParameterType.Color to Color.Red.toArgb())
- validate(factory.create(
- node,
- "brush",
- LinearGradient(listOf(Color.Red, Color.Blue), 0.0f, 0.5f, 5.0f, 10.0f))!!
+ validate(
+ factory.create(
+ node,
+ "brush",
+ LinearGradient(listOf(Color.Red, Color.Blue), 0.0f, 0.5f, 5.0f, 10.0f)
+ )!!
) {
parameter("brush", ParameterType.String, "LinearGradient") {
parameter("colors", ParameterType.String, "") {
@@ -223,7 +226,7 @@
assertThat(lookup(Color.Blue)).isEqualTo(ParameterType.Color to 0xff0000ff.toInt())
assertThat(lookup(Color.Red)).isEqualTo(ParameterType.Color to 0xffff0000.toInt())
assertThat(lookup(Color.Transparent)).isEqualTo(ParameterType.Color to 0x00000000)
- assertThat(lookup(Color.Unset)).isEqualTo(ParameterType.String to "Unset")
+ assertThat(lookup(Color.Unspecified)).isEqualTo(ParameterType.String to "Unspecified")
}
@Test
@@ -382,8 +385,7 @@
node, "modifier",
Modifier
.background(Color.Blue)
- // TODO(b/163494569) uncomment this and code below when bug is fixed
- // .border(width = 5.dp, color = Color.Red)
+ .border(width = 5.dp, color = Color.Red)
.padding(2.0.dp)
.fillMaxWidth()
.wrapContentHeight(Alignment.Bottom)
@@ -397,18 +399,12 @@
parameter("color", ParameterType.Color, Color.Blue.toArgb())
parameter("shape", ParameterType.String, "RectangleShape")
}
- // TODO(b/163494569)
- /*parameter("border", ParameterType.Color, Color.Red.toArgb()) {
+ parameter("border", ParameterType.Color, Color.Red.toArgb()) {
parameter("color", ParameterType.Color, Color.Red.toArgb())
+ parameter("shape", ParameterType.String, "RectangleShape")
parameter("width", ParameterType.DimensionDp, 5.0f)
- parameter("shape", ParameterType.String, "Shape")
- }*/
- parameter("padding", ParameterType.DimensionDp, 2.0f) {
- parameter("bottom", ParameterType.DimensionDp, 2.0f)
- parameter("end", ParameterType.DimensionDp, 2.0f)
- parameter("start", ParameterType.DimensionDp, 2.0f)
- parameter("top", ParameterType.DimensionDp, 2.0f)
}
+ parameter("padding", ParameterType.DimensionDp, 2.0f)
parameter("fillMaxWidth", ParameterType.String, "")
parameter("wrapContentHeight", ParameterType.String, "") {
parameter("alignment", ParameterType.String, "Bottom")
@@ -445,10 +441,19 @@
fun testSingleModifier() {
validate(factory.create(node, "modifier", Modifier.padding(2.0.dp))!!) {
parameter("modifier", ParameterType.String, "") {
- parameter("padding", ParameterType.DimensionDp, 2.0f) {
- parameter("bottom", ParameterType.DimensionDp, 2.0f)
- parameter("end", ParameterType.DimensionDp, 2.0f)
- parameter("start", ParameterType.DimensionDp, 2.0f)
+ parameter("padding", ParameterType.DimensionDp, 2.0f)
+ }
+ }
+ }
+
+ @Test
+ fun testSingleModifierWithParameters() {
+ validate(factory.create(node, "modifier", Modifier.padding(1.dp, 2.dp, 3.dp, 4.dp))!!) {
+ parameter("modifier", ParameterType.String, "") {
+ parameter("padding", ParameterType.String, "") {
+ parameter("bottom", ParameterType.DimensionDp, 4.0f)
+ parameter("end", ParameterType.DimensionDp, 3.0f)
+ parameter("start", ParameterType.DimensionDp, 1.0f)
parameter("top", ParameterType.DimensionDp, 2.0f)
}
}
@@ -574,7 +579,7 @@
)
validate(factory.create(node, "style", style)!!) {
parameter("style", ParameterType.String, TextStyle::class.java.simpleName) {
- parameter("background", ParameterType.String, "Unset")
+ parameter("background", ParameterType.String, "Unspecified")
parameter("color", ParameterType.Color, Color.Red.toArgb())
parameter("fontSize", ParameterType.String, "Inherit")
parameter("letterSpacing", ParameterType.String, "Inherit")
diff --git a/ui/ui-tooling/src/main/java/androidx/ui/tooling/inspector/ParameterFactory.kt b/ui/ui-tooling/src/main/java/androidx/ui/tooling/inspector/ParameterFactory.kt
index f7b52ec..e4f402b 100644
--- a/ui/ui-tooling/src/main/java/androidx/ui/tooling/inspector/ParameterFactory.kt
+++ b/ui/ui-tooling/src/main/java/androidx/ui/tooling/inspector/ParameterFactory.kt
@@ -90,9 +90,10 @@
init {
val textDecorationCombination = TextDecoration.combine(
- listOf(TextDecoration.LineThrough, TextDecoration.Underline))
+ listOf(TextDecoration.LineThrough, TextDecoration.Underline)
+ )
valueLookup[textDecorationCombination] = "LineThrough+Underline"
- valueLookup[Color.Unset] = "Unset"
+ valueLookup[Color.Unspecified] = "Unspecified"
valuesLoaded.add(Enum::class.java)
valuesLoaded.add(Any::class.java)
}
@@ -172,11 +173,11 @@
javaClass.declaredMethods.asSequence()
.filter {
it.returnType != Void.TYPE &&
- JavaModifier.isStatic(it.modifiers) &&
- JavaModifier.isFinal(it.modifiers) &&
- !it.returnType.isPrimitive &&
- it.parameterTypes.isEmpty() &&
- it.name.startsWith("get")
+ JavaModifier.isStatic(it.modifiers) &&
+ JavaModifier.isFinal(it.modifiers) &&
+ !it.returnType.isPrimitive &&
+ it.parameterTypes.isEmpty() &&
+ it.name.startsWith("get")
}
.mapNotNull { javaClass.getDeclaredField(it.name.substring(3)) }
.mapNotNull { constantValueOf(it)?.let { key -> Pair(key, it.name) } }
@@ -215,8 +216,8 @@
private fun ignoredValue(value: Any?): Boolean =
value == null ||
- ignoredClasses.any { ignored -> ignored.isInstance(value) } ||
- value::class.java.isPrimitive
+ ignoredClasses.any { ignored -> ignored.isInstance(value) } ||
+ value::class.java.isPrimitive
/**
* Convenience class for building [NodeParameter]s.
diff --git a/ui/ui-tooling/src/main/java/androidx/ui/tooling/preview/ComposeViewAdapter.kt b/ui/ui-tooling/src/main/java/androidx/ui/tooling/preview/ComposeViewAdapter.kt
index 9132722..3b65bd0 100644
--- a/ui/ui-tooling/src/main/java/androidx/ui/tooling/preview/ComposeViewAdapter.kt
+++ b/ui/ui-tooling/src/main/java/androidx/ui/tooling/preview/ComposeViewAdapter.kt
@@ -485,8 +485,10 @@
-1L
}
- val forceCompositionInvalidation = attrs.getAttributeBooleanValue(TOOLS_NS_URI,
- "forceCompositionInvalidation", false)
+ val forceCompositionInvalidation = attrs.getAttributeBooleanValue(
+ TOOLS_NS_URI,
+ "forceCompositionInvalidation", false
+ )
init(
className = className,
diff --git a/versionedparcelable/versionedparcelable-compiler/build.gradle b/versionedparcelable/versionedparcelable-compiler/build.gradle
index 0c1ecd7..c493835 100644
--- a/versionedparcelable/versionedparcelable-compiler/build.gradle
+++ b/versionedparcelable/versionedparcelable-compiler/build.gradle
@@ -33,7 +33,7 @@
androidx {
name = "VersionedParcelable - Compiler"
- publish = Publish.SNAPSHOT_ONLY
+ publish = Publish.SNAPSHOT_AND_RELEASE
mavenVersion = LibraryVersions.VERSIONED_PARCELABLE
toolingProject = true
compilationTarget = CompilationTarget.HOST
diff --git a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/BaseTest.kt b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/BaseTest.kt
index 665b5b6..46ef639 100644
--- a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/BaseTest.kt
+++ b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/BaseTest.kt
@@ -66,7 +66,7 @@
lateinit var idleWatcher: ViewPagerIdleWatcher
lateinit var viewPager: ViewPager2
val isRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) ==
- ViewCompat.LAYOUT_DIRECTION_RTL
+ ViewCompat.LAYOUT_DIRECTION_RTL
@Before
open fun setUp() {
@@ -82,13 +82,15 @@
fun selectOrientation(orientation: Int) {
onView(withId(R.id.orientation_spinner)).perform(click())
- onData(equalTo(
- when (orientation) {
- ORIENTATION_HORIZONTAL -> "horizontal"
- ORIENTATION_VERTICAL -> "vertical"
- else -> throw IllegalArgumentException("Orientation $orientation doesn't exist")
- }
- )).perform(click())
+ onData(
+ equalTo(
+ when (orientation) {
+ ORIENTATION_HORIZONTAL -> "horizontal"
+ ORIENTATION_VERTICAL -> "vertical"
+ else -> throw IllegalArgumentException("Orientation $orientation doesn't exist")
+ }
+ )
+ ).perform(click())
}
fun swipeToNextPage() {
diff --git a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/MutableCollectionBaseTest.kt b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/MutableCollectionBaseTest.kt
index f06245d..19f1a68 100644
--- a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/MutableCollectionBaseTest.kt
+++ b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/MutableCollectionBaseTest.kt
@@ -105,10 +105,14 @@
}
private fun verifyPage(page: Int) {
- verifyCurrentPage(hasDescendant(allOf(
- withId(R.id.textViewItemText),
- withText("item#$page")
- )))
+ verifyCurrentPage(
+ hasDescendant(
+ allOf(
+ withId(R.id.textViewItemText),
+ withText("item#$page")
+ )
+ )
+ )
}
private fun choosePage(page: Int) {
diff --git a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/PreviewPagesTest.kt b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/PreviewPagesTest.kt
index bccb5f3..61667ad 100644
--- a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/PreviewPagesTest.kt
+++ b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/PreviewPagesTest.kt
@@ -69,9 +69,11 @@
}
private fun onPage(position: Int): ViewInteraction {
- return onView(allOf(
- withParent(withParent(isAssignableFrom(ViewPager2::class.java))),
- withTagValue(equalTo(position))
- ))
+ return onView(
+ allOf(
+ withParent(withParent(isAssignableFrom(ViewPager2::class.java))),
+ withTagValue(equalTo(position))
+ )
+ )
}
}
\ No newline at end of file
diff --git a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/util/AnimationVerifier.kt b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/util/AnimationVerifier.kt
index 968e91c..920657f 100644
--- a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/util/AnimationVerifier.kt
+++ b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/util/AnimationVerifier.kt
@@ -94,9 +94,9 @@
// Get the animation values to verify
hasRotation = !isZero(page!!.rotation) || !isZero(page.rotationX) ||
- !isZero(page.rotationY)
+ !isZero(page.rotationY)
hasTranslation = !isZero(page.translationX) || !isZero(page.translationY) ||
- !isZero(ViewCompat.getTranslationZ(page))
+ !isZero(ViewCompat.getTranslationZ(page))
hasScale = !isOne(page.scaleX) || !isOne(page.scaleY)
// Mark verification as done
diff --git a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/util/ViewInteractions.kt b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/util/ViewInteractions.kt
index 75a3912..2811f13 100644
--- a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/util/ViewInteractions.kt
+++ b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/util/ViewInteractions.kt
@@ -41,10 +41,12 @@
* both show exactly 50%, the selected page is undefined.
*/
fun onCurrentPage(): ViewInteraction {
- return onView(allOf(
- withParent(withParent(isAssignableFrom(ViewPager2::class.java))),
- isDisplayingAtLeast(50)
- ))
+ return onView(
+ allOf(
+ withParent(withParent(isAssignableFrom(ViewPager2::class.java))),
+ isDisplayingAtLeast(50)
+ )
+ )
}
/**
diff --git a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/BaseCardActivity.kt b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/BaseCardActivity.kt
index f5e47e3e..59e195f 100644
--- a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/BaseCardActivity.kt
+++ b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/BaseCardActivity.kt
@@ -43,9 +43,9 @@
private lateinit var gotoPage: Button
private val translateX get() = viewPager.orientation == ORIENTATION_VERTICAL &&
- translateCheckBox.isChecked
+ translateCheckBox.isChecked
private val translateY get() = viewPager.orientation == ORIENTATION_HORIZONTAL &&
- translateCheckBox.isChecked
+ translateCheckBox.isChecked
protected open val layoutId: Int = R.layout.activity_no_tablayout
diff --git a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/BrowseActivity.kt b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/BrowseActivity.kt
index f3f44ec..fcc6ee5 100644
--- a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/BrowseActivity.kt
+++ b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/BrowseActivity.kt
@@ -31,38 +31,76 @@
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- listAdapter = SimpleAdapter(this, getData(),
- android.R.layout.simple_list_item_1, arrayOf("title"),
- intArrayOf(android.R.id.text1))
+ listAdapter = SimpleAdapter(
+ this, getData(),
+ android.R.layout.simple_list_item_1, arrayOf("title"),
+ intArrayOf(android.R.id.text1)
+ )
}
private fun getData(): List<Map<String, Any>> {
val myData = mutableListOf<Map<String, Any>>()
- myData.add(mapOf("title" to "ViewPager2 with Views",
- "intent" to activityToIntent(CardViewActivity::class.java.name)))
- myData.add(mapOf("title" to "ViewPager2 with Fragments",
- "intent" to activityToIntent(CardFragmentActivity::class.java.name)))
- myData.add(mapOf("title" to "ViewPager2 with a Mutable Collection (Views)",
- "intent" to activityToIntent(MutableCollectionViewActivity::class.java.name)))
- myData.add(mapOf("title" to "ViewPager2 with a Mutable Collection (Fragments)",
- "intent" to activityToIntent(MutableCollectionFragmentActivity::class.java.name)))
- myData.add(mapOf("title" to "ViewPager2 with a TabLayout (Views)",
- "intent" to activityToIntent(CardViewTabLayoutActivity::class.java.name)))
- myData.add(mapOf("title" to "ViewPager2 with Fake Dragging",
- "intent" to activityToIntent(FakeDragActivity::class.java.name)))
- myData.add(mapOf("title" to "ViewPager2 with PageTransformers",
- "intent" to activityToIntent(PageTransformerActivity::class.java.name)))
- myData.add(mapOf("title" to "ViewPager2 with a Preview of Next/Prev Page",
- "intent" to activityToIntent(PreviewPagesActivity::class.java.name)))
- myData.add(mapOf("title" to "ViewPager2 with Nested RecyclerViews",
- "intent" to activityToIntent(ParallelNestedScrollingActivity::class.java.name)))
+ myData.add(
+ mapOf(
+ "title" to "ViewPager2 with Views",
+ "intent" to activityToIntent(CardViewActivity::class.java.name)
+ )
+ )
+ myData.add(
+ mapOf(
+ "title" to "ViewPager2 with Fragments",
+ "intent" to activityToIntent(CardFragmentActivity::class.java.name)
+ )
+ )
+ myData.add(
+ mapOf(
+ "title" to "ViewPager2 with a Mutable Collection (Views)",
+ "intent" to activityToIntent(MutableCollectionViewActivity::class.java.name)
+ )
+ )
+ myData.add(
+ mapOf(
+ "title" to "ViewPager2 with a Mutable Collection (Fragments)",
+ "intent" to activityToIntent(MutableCollectionFragmentActivity::class.java.name)
+ )
+ )
+ myData.add(
+ mapOf(
+ "title" to "ViewPager2 with a TabLayout (Views)",
+ "intent" to activityToIntent(CardViewTabLayoutActivity::class.java.name)
+ )
+ )
+ myData.add(
+ mapOf(
+ "title" to "ViewPager2 with Fake Dragging",
+ "intent" to activityToIntent(FakeDragActivity::class.java.name)
+ )
+ )
+ myData.add(
+ mapOf(
+ "title" to "ViewPager2 with PageTransformers",
+ "intent" to activityToIntent(PageTransformerActivity::class.java.name)
+ )
+ )
+ myData.add(
+ mapOf(
+ "title" to "ViewPager2 with a Preview of Next/Prev Page",
+ "intent" to activityToIntent(PreviewPagesActivity::class.java.name)
+ )
+ )
+ myData.add(
+ mapOf(
+ "title" to "ViewPager2 with Nested RecyclerViews",
+ "intent" to activityToIntent(ParallelNestedScrollingActivity::class.java.name)
+ )
+ )
return myData
}
private fun activityToIntent(activity: String): Intent =
- Intent(Intent.ACTION_VIEW).setClassName(this.packageName, activity)
+ Intent(Intent.ACTION_VIEW).setClassName(this.packageName, activity)
override fun onListItemClick(listView: ListView, view: View, position: Int, id: Long) {
val map = listView.getItemAtPosition(position) as Map<*, *>
diff --git a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/FakeDragActivity.kt b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/FakeDragActivity.kt
index cf53330..b86e323 100644
--- a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/FakeDragActivity.kt
+++ b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/FakeDragActivity.kt
@@ -34,7 +34,7 @@
private var lastValue: Float = 0f
private val isRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) ==
- ViewCompat.LAYOUT_DIRECTION_RTL
+ ViewCompat.LAYOUT_DIRECTION_RTL
private val ViewPager2.isHorizontal: Boolean
get() {
diff --git a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/MutableCollectionBaseActivity.kt b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/MutableCollectionBaseActivity.kt
index 2132c098..2f3ca9d 100644
--- a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/MutableCollectionBaseActivity.kt
+++ b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/MutableCollectionBaseActivity.kt
@@ -82,16 +82,22 @@
val idsOld = items.createIdSnapshot()
performChanges()
val idsNew = items.createIdSnapshot()
- DiffUtil.calculateDiff(object : DiffUtil.Callback() {
- override fun getOldListSize(): Int = idsOld.size
- override fun getNewListSize(): Int = idsNew.size
+ DiffUtil.calculateDiff(
+ object : DiffUtil.Callback() {
+ override fun getOldListSize(): Int = idsOld.size
+ override fun getNewListSize(): Int = idsNew.size
- override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
- idsOld[oldItemPosition] == idsNew[newItemPosition]
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
+ idsOld[oldItemPosition] == idsNew[newItemPosition]
- override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
- areItemsTheSame(oldItemPosition, newItemPosition)
- }, true).dispatchUpdatesTo(viewPager.adapter!!)
+ override fun areContentsTheSame(
+ oldItemPosition: Int,
+ newItemPosition: Int
+ ) =
+ areItemsTheSame(oldItemPosition, newItemPosition)
+ },
+ true
+ ).dispatchUpdatesTo(viewPager.adapter!!)
} else {
/** without [DiffUtil] */
val oldPosition = viewPager.currentItem
diff --git a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/OrientationController.kt b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/OrientationController.kt
index 571bfea..89d9a1e 100644
--- a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/OrientationController.kt
+++ b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/OrientationController.kt
@@ -29,8 +29,10 @@
class OrientationController(private val viewPager: ViewPager2, private val spinner: Spinner) {
fun setUp() {
val orientation = viewPager.orientation
- val adapter = ArrayAdapter(spinner.context, android.R.layout.simple_spinner_item,
- arrayOf(HORIZONTAL, VERTICAL))
+ val adapter = ArrayAdapter(
+ spinner.context, android.R.layout.simple_spinner_item,
+ arrayOf(HORIZONTAL, VERTICAL)
+ )
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = adapter
diff --git a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/PageTransformerController.kt b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/PageTransformerController.kt
index 3b38ad8..4b03dd3 100644
--- a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/PageTransformerController.kt
+++ b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/PageTransformerController.kt
@@ -58,10 +58,12 @@
id: Long
) {
val selected = transformers.first { it.first == parent.selectedItem }.second
- viewPager.setPageTransformer(CompositePageTransformer().also {
- it.addTransformer(cancelTranslationsTransformer)
- it.addTransformer(selected)
- })
+ viewPager.setPageTransformer(
+ CompositePageTransformer().also {
+ it.addTransformer(cancelTranslationsTransformer)
+ it.addTransformer(selected)
+ }
+ )
}
override fun onNothingSelected(adapterView: AdapterView<*>) {}
diff --git a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/PreviewPagesActivity.kt b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/PreviewPagesActivity.kt
index a930d1a..6298a86 100644
--- a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/PreviewPagesActivity.kt
+++ b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/PreviewPagesActivity.kt
@@ -33,7 +33,7 @@
val recyclerView = getChildAt(0) as RecyclerView
recyclerView.apply {
val padding = resources.getDimensionPixelOffset(R.dimen.halfPageMargin) +
- resources.getDimensionPixelOffset(R.dimen.peekOffset)
+ resources.getDimensionPixelOffset(R.dimen.peekOffset)
// setting padding on inner RecyclerView puts overscroll effect in the right place
// TODO: expose in later versions not to rely on getChildAt(0) which might break
setPadding(padding, 0, padding, 0)
diff --git a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/cards/CardView.kt b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/cards/CardView.kt
index 9565169..a079f44 100644
--- a/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/cards/CardView.kt
+++ b/viewpager2/integration-tests/testapp/src/main/java/androidx/viewpager2/integration/testapp/cards/CardView.kt
@@ -79,11 +79,16 @@
companion object {
private val COLOR_MAP = arrayOf(
- intArrayOf(R.color.red_100, R.color.red_300, R.color.red_500, R.color.red_700),
- intArrayOf(R.color.blue_100, R.color.blue_300, R.color.blue_500, R.color.blue_700),
- intArrayOf(R.color.green_100, R.color.green_300, R.color.green_500,
- R.color.green_700),
- intArrayOf(R.color.yellow_100, R.color.yellow_300, R.color.yellow_500,
- R.color.yellow_700))
+ intArrayOf(R.color.red_100, R.color.red_300, R.color.red_500, R.color.red_700),
+ intArrayOf(R.color.blue_100, R.color.blue_300, R.color.blue_500, R.color.blue_700),
+ intArrayOf(
+ R.color.green_100, R.color.green_300, R.color.green_500,
+ R.color.green_700
+ ),
+ intArrayOf(
+ R.color.yellow_100, R.color.yellow_300, R.color.yellow_500,
+ R.color.yellow_700
+ )
+ )
}
}
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AccessibilityTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AccessibilityTest.kt
index 13688fb..69d007d 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AccessibilityTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AccessibilityTest.kt
@@ -79,16 +79,20 @@
assertBasicState(initialPage)
listOf(1, 2, 3, 2, 3, 2, 3, 4, 5, 4, 5, 4, 3, 2, 1, 0, 1).forEach {
- targetPage ->
+ targetPage ->
val currentPage = viewPager.currentItem
val latch = viewPager.addWaitForScrolledLatch(targetPage)
runOnUiThreadSync {
if (targetPage - currentPage == 1) {
- ViewCompat.performAccessibilityAction(viewPager,
- getNextPageAction(config.orientation, viewPager.isRtl), null)
+ ViewCompat.performAccessibilityAction(
+ viewPager,
+ getNextPageAction(config.orientation, viewPager.isRtl), null
+ )
} else {
- ViewCompat.performAccessibilityAction(viewPager,
- getPreviousPageAction(config.orientation, viewPager.isRtl), null)
+ ViewCompat.performAccessibilityAction(
+ viewPager,
+ getPreviousPageAction(config.orientation, viewPager.isRtl), null
+ )
}
}
latch.await(2, TimeUnit.SECONDS)
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AdapterDataSetChangeWhileSmoothScrollTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AdapterDataSetChangeWhileSmoothScrollTest.kt
index 31fb236..0187be6 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AdapterDataSetChangeWhileSmoothScrollTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AdapterDataSetChangeWhileSmoothScrollTest.kt
@@ -148,8 +148,10 @@
val scrollsAfterMarker = scrollEventsAfter(removeItemMarkIx)
listOf(scrollsBeforeMarker, scrollsAfterMarker).forEach {
it.assertPositionSorted(SortOrder.ASC)
- it.assertValueCorrectness(0, targetPage + removeCountHead,
- test.viewPager.pageSize)
+ it.assertValueCorrectness(
+ 0, targetPage + removeCountHead,
+ test.viewPager.pageSize
+ )
}
// Only check assertOffsetSorted on scroll events _before_ the marker:
// after the data set change, it can overshoot and reverse direction
@@ -180,8 +182,10 @@
it.position + it.positionOffset.toDouble()
}
if (lastScrollPosition >= windowEnd) {
- throw RetryException("Data set should be modified while scrolling through " +
- "($windowStart, $windowEnd), but was modified at $lastScrollPosition")
+ throw RetryException(
+ "Data set should be modified while scrolling through " +
+ "($windowStart, $windowEnd), but was modified at $lastScrollPosition"
+ )
}
}
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AdapterTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AdapterTest.kt
index a61995a..cc0384d 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AdapterTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/AdapterTest.kt
@@ -58,11 +58,14 @@
}
test.assertBasicState(0)
- assertThat(recorder.allEvents, equalTo(
- expectedEventsForPage(0) // for setting the adapter
- .plus(expectedEventsForPage(1)) // for going to page 1
- .plus(expectedEventsForPage(0)) // for setting it again
- ))
+ assertThat(
+ recorder.allEvents,
+ equalTo(
+ expectedEventsForPage(0) // for setting the adapter
+ .plus(expectedEventsForPage(1)) // for going to page 1
+ .plus(expectedEventsForPage(0)) // for setting it again
+ )
+ )
}
private fun setUpWithoutAdapter() {
@@ -121,10 +124,15 @@
swipe(SwipeMethod.ESPRESSO)
idleLatch.await(2, SECONDS)
- assertThat(recorder.allEvents, equalTo(listOf(
- OnPageScrollStateChangedEvent(SCROLL_STATE_DRAGGING) as Event,
- OnPageScrollStateChangedEvent(SCROLL_STATE_IDLE) as Event
- )))
+ assertThat(
+ recorder.allEvents,
+ equalTo(
+ listOf(
+ OnPageScrollStateChangedEvent(SCROLL_STATE_DRAGGING) as Event,
+ OnPageScrollStateChangedEvent(SCROLL_STATE_IDLE) as Event
+ )
+ )
+ )
test.viewPager.unregisterOnPageChangeCallback(recorder)
}
}
@@ -136,10 +144,13 @@
clearDataSet()
// check events
- assertThat(recorder.allEvents, equalTo(
- expectedEventsForPage(0) // for setting the adapter
- .plus(expectedEventsForPage(0)) // for clearing it
- ))
+ assertThat(
+ recorder.allEvents,
+ equalTo(
+ expectedEventsForPage(0) // for setting the adapter
+ .plus(expectedEventsForPage(0)) // for clearing it
+ )
+ )
}
@Test
@@ -149,11 +160,14 @@
clearDataSet()
// check events
- assertThat(recorder.allEvents, equalTo(
- expectedEventsForPage(0) // for setting the adapter
- .plus(expectedEventsForPage(1)) // for going to page 1
- .plus(expectedEventsForPage(0)) // for clearing it
- ))
+ assertThat(
+ recorder.allEvents,
+ equalTo(
+ expectedEventsForPage(0) // for setting the adapter
+ .plus(expectedEventsForPage(1)) // for going to page 1
+ .plus(expectedEventsForPage(0)) // for clearing it
+ )
+ )
}
@Test
@@ -163,9 +177,12 @@
fillDataSet()
// check events
- assertThat(recorder.allEvents, equalTo(
- expectedEventsForPage(0) // for populating the adapter
- ))
+ assertThat(
+ recorder.allEvents,
+ equalTo(
+ expectedEventsForPage(0) // for populating the adapter
+ )
+ )
}
@Test
@@ -178,12 +195,15 @@
clearDataSet()
// check events
- assertThat(recorder.allEvents, equalTo(
- expectedEventsForPage(0) // for setting the adapter
- .plus(expectedEventsForPage(0)) // for clearing it
- .plus(expectedEventsForPage(0)) // for repopulating it
- .plus(expectedEventsForPage(0)) // for clearing it again
- ))
+ assertThat(
+ recorder.allEvents,
+ equalTo(
+ expectedEventsForPage(0) // for setting the adapter
+ .plus(expectedEventsForPage(0)) // for clearing it
+ .plus(expectedEventsForPage(0)) // for repopulating it
+ .plus(expectedEventsForPage(0)) // for clearing it again
+ )
+ )
}
private fun expectedEventsForPage(page: Int): List<Event> {
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt
index 63486e4..c1aae40 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt
@@ -263,7 +263,8 @@
coordinates[1] += offset
}
coordinates
- }, Press.FINGER
+ },
+ Press.FINGER
)
)
)
@@ -282,43 +283,47 @@
var isVerticalOrientation = viewPager.orientation == ViewPager2.ORIENTATION_VERTICAL
val expectPageLeftAction = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
- isUserInputEnabled && isHorizontalOrientation &&
- (if (viewPager.isRtl) currentPage < numPages - 1 else currentPage > 0)
+ isUserInputEnabled && isHorizontalOrientation &&
+ (if (viewPager.isRtl) currentPage < numPages - 1 else currentPage > 0)
val expectPageRightAction = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
- isUserInputEnabled && isHorizontalOrientation &&
- (if (viewPager.isRtl) currentPage > 0 else currentPage < numPages - 1)
+ isUserInputEnabled && isHorizontalOrientation &&
+ (if (viewPager.isRtl) currentPage > 0 else currentPage < numPages - 1)
val expectPageUpAction = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
- isUserInputEnabled && isVerticalOrientation &&
- currentPage > 0
+ isUserInputEnabled && isVerticalOrientation &&
+ currentPage > 0
val expectPageDownAction = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
- isUserInputEnabled && isVerticalOrientation &&
- currentPage < numPages - 1
+ isUserInputEnabled && isVerticalOrientation &&
+ currentPage < numPages - 1
val expectScrollBackwardAction =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && isUserInputEnabled &&
- currentPage > 0
+ currentPage > 0
val expectScrollForwardAction =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && isUserInputEnabled &&
- currentPage < numPages - 1
+ currentPage < numPages - 1
- assertThat("Left action expected: $expectPageLeftAction",
+ assertThat(
+ "Left action expected: $expectPageLeftAction",
hasPageAction(customActions, ACTION_ID_PAGE_LEFT),
equalTo(expectPageLeftAction)
)
- assertThat("Right action expected: $expectPageRightAction",
+ assertThat(
+ "Right action expected: $expectPageRightAction",
hasPageAction(customActions, ACTION_ID_PAGE_RIGHT),
equalTo(expectPageRightAction)
)
- assertThat("Up action expected: $expectPageUpAction",
+ assertThat(
+ "Up action expected: $expectPageUpAction",
hasPageAction(customActions, ACTION_ID_PAGE_UP),
equalTo(expectPageUpAction)
)
- assertThat("Down action expected: $expectPageDownAction",
+ assertThat(
+ "Down action expected: $expectPageDownAction",
hasPageAction(customActions, ACTION_ID_PAGE_DOWN),
equalTo(expectPageDownAction)
)
@@ -327,12 +332,14 @@
runOnUiThreadSync { viewPager.onInitializeAccessibilityNodeInfo(node) }
@Suppress("DEPRECATION") var standardActions = node.actions
- assertThat("scroll backward action expected: $expectScrollBackwardAction",
+ assertThat(
+ "scroll backward action expected: $expectScrollBackwardAction",
hasScrollAction(standardActions, ACTION_SCROLL_BACKWARD),
equalTo(expectScrollBackwardAction)
)
- assertThat("Scroll forward action expected: $expectScrollForwardAction",
+ assertThat(
+ "Scroll forward action expected: $expectScrollForwardAction",
hasScrollAction(standardActions, ACTION_SCROLL_FORWARD),
equalTo(expectScrollForwardAction)
)
@@ -354,10 +361,10 @@
@Suppress("UNCHECKED_CAST")
private fun getActionList(view: View):
- List<AccessibilityNodeInfoCompat.AccessibilityActionCompat> {
- return view.getTag(R.id.tag_accessibility_actions) as?
+ List<AccessibilityNodeInfoCompat.AccessibilityActionCompat> {
+ return view.getTag(R.id.tag_accessibility_actions) as?
ArrayList<AccessibilityNodeInfoCompat.AccessibilityActionCompat> ?: ArrayList()
- }
+ }
}
/**
@@ -542,10 +549,10 @@
expectEvents: Boolean = (targetPage != currentItem)
) {
val latch =
- if (expectEvents)
- addWaitForScrolledLatch(targetPage, smoothScroll)
- else
- CountDownLatch(1)
+ if (expectEvents)
+ addWaitForScrolledLatch(targetPage, smoothScroll)
+ else
+ CountDownLatch(1)
post {
setCurrentItem(targetPage, smoothScroll)
if (!expectEvents) {
@@ -706,9 +713,9 @@
fun scrollStateGlossary(): String {
return "Scroll states: " +
- "$SCROLL_STATE_IDLE=${scrollStateToString(SCROLL_STATE_IDLE)}, " +
- "$SCROLL_STATE_DRAGGING=${scrollStateToString(SCROLL_STATE_DRAGGING)}, " +
- "$SCROLL_STATE_SETTLING=${scrollStateToString(SCROLL_STATE_SETTLING)})"
+ "$SCROLL_STATE_IDLE=${scrollStateToString(SCROLL_STATE_IDLE)}, " +
+ "$SCROLL_STATE_DRAGGING=${scrollStateToString(SCROLL_STATE_DRAGGING)}, " +
+ "$SCROLL_STATE_SETTLING=${scrollStateToString(SCROLL_STATE_SETTLING)})"
}
class RetryException(msg: String) : Exception(msg)
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/DragWhileSmoothScrollTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/DragWhileSmoothScrollTest.kt
index 5b9266c..8273c04 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/DragWhileSmoothScrollTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/DragWhileSmoothScrollTest.kt
@@ -79,14 +79,19 @@
var recorder = test.viewPager.addNewRecordingCallback()
val movingForward = config.targetPage > config.startPage
- tryNTimes(3, resetBlock = {
- test.resetViewPagerTo(config.startPage)
- test.viewPager.unregisterOnPageChangeCallback(recorder)
- recorder = test.viewPager.addNewRecordingCallback()
- }) {
+ tryNTimes(
+ 3,
+ resetBlock = {
+ test.resetViewPagerTo(config.startPage)
+ test.viewPager.unregisterOnPageChangeCallback(recorder)
+ recorder = test.viewPager.addNewRecordingCallback()
+ }
+ ) {
// when we are close enough
- val waitTillCloseEnough = test.viewPager.addWaitForDistanceToTarget(config.targetPage,
- config.distanceToTargetWhenStartDrag)
+ val waitTillCloseEnough = test.viewPager.addWaitForDistanceToTarget(
+ config.targetPage,
+ config.distanceToTargetWhenStartDrag
+ )
test.runOnUiThreadSync { test.viewPager.setCurrentItem(config.targetPage, true) }
waitTillCloseEnough.await(2, SECONDS)
@@ -133,23 +138,37 @@
if (currentlyVisible == config.targetPage) {
// drag coincidentally landed us on the targetPage,
// this slightly changes the assertions
- assertThat("viewPager.getCurrentItem() should be ${config.targetPage}",
- test.viewPager.currentItem, equalTo(config.targetPage))
- assertThat("Exactly 1 onPageSelected event should be fired",
- selectEvents.size, equalTo(1))
- assertThat("onPageSelected event should have reported ${config.targetPage}",
- selectEvents.first().position, equalTo(config.targetPage))
+ assertThat(
+ "viewPager.getCurrentItem() should be ${config.targetPage}",
+ test.viewPager.currentItem, equalTo(config.targetPage)
+ )
+ assertThat(
+ "Exactly 1 onPageSelected event should be fired",
+ selectEvents.size, equalTo(1)
+ )
+ assertThat(
+ "onPageSelected event should have reported ${config.targetPage}",
+ selectEvents.first().position, equalTo(config.targetPage)
+ )
} else {
- assertThat("viewPager.getCurrentItem() should not be ${config.targetPage}",
- test.viewPager.currentItem, not(equalTo(config.targetPage)))
- assertThat("Exactly 2 onPageSelected events should be fired",
- selectEvents.size, equalTo(2))
- assertThat("First onPageSelected event should have reported ${config.targetPage}",
- selectEvents.first().position, equalTo(config.targetPage))
- assertThat("Second onPageSelected event should have reported " +
+ assertThat(
+ "viewPager.getCurrentItem() should not be ${config.targetPage}",
+ test.viewPager.currentItem, not(equalTo(config.targetPage))
+ )
+ assertThat(
+ "Exactly 2 onPageSelected events should be fired",
+ selectEvents.size, equalTo(2)
+ )
+ assertThat(
+ "First onPageSelected event should have reported ${config.targetPage}",
+ selectEvents.first().position, equalTo(config.targetPage)
+ )
+ assertThat(
+ "Second onPageSelected event should have reported " +
"$currentlyVisible, or visible page should be " +
"${selectEvents.last().position}",
- selectEvents.last().position, equalTo(currentlyVisible))
+ selectEvents.last().position, equalTo(currentlyVisible)
+ )
}
}
}
@@ -305,16 +324,18 @@
)
}
}
- }.plus(listOf(
- TestConfig(
- title = "drag back to start",
- orientation = orientation,
- startPage = 0,
- targetPage = 1,
- dragInOppositeDirection = true,
- distanceToTargetWhenStartDrag = .7f
+ }.plus(
+ listOf(
+ TestConfig(
+ title = "drag back to start",
+ orientation = orientation,
+ startPage = 0,
+ targetPage = 1,
+ dragInOppositeDirection = true,
+ distanceToTargetWhenStartDrag = .7f
+ )
)
- ))
+ )
}
}
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/EditTextFocusTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/EditTextFocusTest.kt
index 1910394..882aa67 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/EditTextFocusTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/EditTextFocusTest.kt
@@ -132,31 +132,31 @@
* @param wrapEditTextInViewGroup if false, [EditText] is the page root
*/
private fun createEditTextAdapter(pageCount: Int, wrapEditTextInViewGroup: Boolean):
- RecyclerView.Adapter<RecyclerView.ViewHolder> {
- return object : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
- override fun getItemCount(): Int = pageCount
+ RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ return object : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
+ override fun getItemCount(): Int = pageCount
- override fun onCreateViewHolder(
- parent: ViewGroup,
- viewType: Int
- ): RecyclerView.ViewHolder {
- val editText = EditText(parent.context).apply {
- layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
- gravity = Gravity.CENTER_VERTICAL or Gravity.END
- inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
- setBackgroundColor(Color.WHITE)
- setTextColor(Color.DKGRAY)
+ override fun onCreateViewHolder(
+ parent: ViewGroup,
+ viewType: Int
+ ): RecyclerView.ViewHolder {
+ val editText = EditText(parent.context).apply {
+ layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
+ gravity = Gravity.CENTER_VERTICAL or Gravity.END
+ inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
+ setBackgroundColor(Color.WHITE)
+ setTextColor(Color.DKGRAY)
+ }
+ val pageView = pageForEditText(editText, wrapEditTextInViewGroup)
+ return object : RecyclerView.ViewHolder(pageView) {}
}
- val pageView = pageForEditText(editText, wrapEditTextInViewGroup)
- return object : RecyclerView.ViewHolder(pageView) {}
- }
- override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
- editTextForPage(holder.itemView).text =
- SpannableStringBuilder("position=$position")
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ editTextForPage(holder.itemView).text =
+ SpannableStringBuilder("position=$position")
+ }
}
}
- }
private fun editTextForPage(page: View): EditText = page.let {
when (it) {
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/FakeDragTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/FakeDragTest.kt
index 0e45b8b..bd4b7fa 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/FakeDragTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/FakeDragTest.kt
@@ -91,9 +91,11 @@
// Used to overcome touch slop and gently slide forward.
// Similar to but better than DecelerateInterpolator in this case.
- private val fastDecelerateInterpolator = PathInterpolatorCompat.create(Path().also {
- it.cubicTo(0f, .7f, 0f, 1f, 1f, 1f)
- })
+ private val fastDecelerateInterpolator = PathInterpolatorCompat.create(
+ Path().also {
+ it.cubicTo(0f, .7f, 0f, 1f, 1f, 1f)
+ }
+ )
override fun setUp() {
super.setUp()
@@ -135,11 +137,17 @@
// |/
// 0 +--------------
// 0 1
- basicFakeDragTest(.2f, 300, 0, PathInterpolatorCompat.create(Path().also {
- it.moveTo(0f, 0f)
- it.cubicTo(.4f, 6f, .5f, 1f, .8f, 1f)
- it.lineTo(1f, 1f)
- }), true)
+ basicFakeDragTest(
+ .2f, 300, 0,
+ PathInterpolatorCompat.create(
+ Path().also {
+ it.moveTo(0f, 0f)
+ it.cubicTo(.4f, 6f, .5f, 1f, .8f, 1f)
+ it.lineTo(1f, 1f)
+ }
+ ),
+ true
+ )
}
@Test
@@ -152,10 +160,16 @@
// |/
// 0 +-------
// 0 1
- basicFakeDragTest(.4f, 200, 0, PathInterpolatorCompat.create(Path().also {
- it.moveTo(0f, 0f)
- it.cubicTo(.4f, 1.7f, .7f, 1.7f, 1f, 1f)
- }), false)
+ basicFakeDragTest(
+ .4f, 200, 0,
+ PathInterpolatorCompat.create(
+ Path().also {
+ it.moveTo(0f, 0f)
+ it.cubicTo(.4f, 1.7f, .7f, 1.7f, 1f, 1f)
+ }
+ ),
+ false
+ )
}
@Test
@@ -194,8 +208,10 @@
repeat(2) {
val tracker = PositionTracker().also { test.viewPager.registerOnPageChangeCallback(it) }
val targetPage = test.viewPager.currentItem + 1
- startFakeDragWhileSettling(targetPage,
- { (targetPage - tracker.lastPosition).toFloat() }, targetPage, true)
+ startFakeDragWhileSettling(
+ targetPage,
+ { (targetPage - tracker.lastPosition).toFloat() }, targetPage, true
+ )
test.viewPager.unregisterOnPageChangeCallback(tracker)
}
}
@@ -216,8 +232,10 @@
val tracker = PositionTracker().also { test.viewPager.registerOnPageChangeCallback(it) }
val targetPage = test.viewPager.currentItem + 1
val nextPage = targetPage + 1
- startFakeDragWhileSettling(targetPage,
- { (nextPage - tracker.lastPosition).toFloat() }, nextPage, true)
+ startFakeDragWhileSettling(
+ targetPage,
+ { (nextPage - tracker.lastPosition).toFloat() }, nextPage, true
+ )
test.viewPager.unregisterOnPageChangeCallback(tracker)
}
}
@@ -420,8 +438,10 @@
// Check 1: must still be in scroll state SETTLING
if (test.viewPager.scrollState != ViewPager2.SCROLL_STATE_SETTLING) {
- throw RetryException("Interruption of SETTLING too late: " +
- "state already left SETTLING")
+ throw RetryException(
+ "Interruption of SETTLING too late: " +
+ "state already left SETTLING"
+ )
}
// Check 2: setCurrentItem should not have finished
if (settleTarget - currPosition <= 0) {
@@ -429,8 +449,10 @@
}
// Check 3: fake drag should not overshoot its target
if ((expectedFinalPage - currPosition).toFloat() < dragDistance) {
- throw RetryException("Interruption of SETTLING too late: already closer than " +
- "$dragDistance from target")
+ throw RetryException(
+ "Interruption of SETTLING too late: already closer than " +
+ "$dragDistance from target"
+ )
}
idleLatch = test.viewPager.addWaitForIdleLatch()
@@ -443,17 +465,20 @@
assertThat(test.viewPager.isFakeDragging, equalTo(false))
assertThat(fakeDragger.isInterrupted, equalTo(false))
recorder.apply {
- scrollEvents.assertValueCorrectness(initialPage, expectedFinalPage,
- test.viewPager.pageSize)
+ scrollEvents.assertValueCorrectness(
+ initialPage, expectedFinalPage,
+ test.viewPager.pageSize
+ )
assertFirstEvents(SETTLING)
assertLastEvents(expectedFinalPage)
assertPageSelectedEvents(initialPage, settleTarget, expectedFinalPage)
if (fakeDragMustEndSnapped) {
assertThat(
"When a fake drag should end in a snapped position, we expect the last " +
- "scroll event after the FAKE_DRAG event to be snapped. " +
- dumpEvents(),
- expectSettlingAfterState(DRAGGING), equalTo(false))
+ "scroll event after the FAKE_DRAG event to be snapped. " +
+ dumpEvents(),
+ expectSettlingAfterState(DRAGGING), equalTo(false)
+ )
}
assertStateChanges(
listOf(SETTLING, DRAGGING, SETTLING, IDLE),
@@ -512,7 +537,8 @@
// start fake drag
val fakeDragLatch = test.viewPager.addWaitForDistanceToTarget(
- expectedFinalPage + referencePageOffset, .9f)
+ expectedFinalPage + referencePageOffset, .9f
+ )
val idleLatch = test.viewPager.addWaitForIdleLatch()
fakeDragger.postFakeDrag(fakeDragDistance, fakeDragDuration, interpolator)
assertThat(fakeDragLatch.await(5, SECONDS), equalTo(true))
@@ -530,8 +556,10 @@
// test assertions
test.assertBasicState(expectedFinalPage)
recorder.apply {
- scrollEvents.assertValueCorrectness(initialPage,
- expectedFinalPage + referencePageOffset, test.viewPager.pageSize)
+ scrollEvents.assertValueCorrectness(
+ initialPage,
+ expectedFinalPage + referencePageOffset, test.viewPager.pageSize
+ )
assertFirstEvents(DRAGGING)
assertLastEvents(expectedFinalPage)
assertPageSelectedEvents(initialPage, expectedFinalPage)
@@ -595,15 +623,15 @@
positionOffset: Float,
positionOffsetPixels: Int
) {
- addEvent(OnPageScrolledEvent(position, positionOffset, positionOffsetPixels))
+ addEvent(OnPageScrolledEvent(position, positionOffset, positionOffsetPixels))
}
override fun onPageSelected(position: Int) {
- addEvent(OnPageSelectedEvent(position))
+ addEvent(OnPageSelectedEvent(position))
}
override fun onPageScrollStateChanged(state: Int) {
- addEvent(OnPageScrollStateChangedEvent(state))
+ addEvent(OnPageScrollStateChangedEvent(state))
}
fun expectSettlingAfterState(state: Int): Boolean {
@@ -617,24 +645,32 @@
}
fun dumpEvents(): String {
- return eventsCopy.joinToString("\n- ", "\n(${scrollStateGlossary()})\n- ")
+ return eventsCopy.joinToString("\n- ", "\n(${scrollStateGlossary()})\n- ")
}
}
private fun RecordingCallback.assertFirstEvents(expectedFirstState: Int) {
assertThat("There should be events", eventCount, greaterThan(0))
- assertThat("First event should be state change to " +
+ assertThat(
+ "First event should be state change to " +
"${scrollStateToString(expectedFirstState)}: ${dumpEvents()}",
- firstEvent, equalTo(OnPageScrollStateChangedEvent(expectedFirstState) as Event))
+ firstEvent, equalTo(OnPageScrollStateChangedEvent(expectedFirstState) as Event)
+ )
}
private fun RecordingCallback.assertLastEvents(expectedFinalPage: Int) {
- assertThat("Last event should be state change to IDLE: ${dumpEvents()}",
- lastEvent, equalTo(OnPageScrollStateChangedEvent(IDLE) as Event))
- assertThat("Scroll events don't end in snapped position: ${dumpEvents()}",
- scrollEvents.last().positionOffsetPixels, equalTo(0))
- assertThat("Scroll events don't end at page $expectedFinalPage: ${dumpEvents()}",
- scrollEvents.last().position, equalTo(expectedFinalPage))
+ assertThat(
+ "Last event should be state change to IDLE: ${dumpEvents()}",
+ lastEvent, equalTo(OnPageScrollStateChangedEvent(IDLE) as Event)
+ )
+ assertThat(
+ "Scroll events don't end in snapped position: ${dumpEvents()}",
+ scrollEvents.last().positionOffsetPixels, equalTo(0)
+ )
+ assertThat(
+ "Scroll events don't end at page $expectedFinalPage: ${dumpEvents()}",
+ scrollEvents.last().position, equalTo(expectedFinalPage)
+ )
}
private fun RecordingCallback.assertPageSelectedEvents(vararg visitedPages: Int) {
@@ -642,21 +678,28 @@
// If visited page is same as previous page, no page selected event should be fired
if (pair.first == pair.second) null else pair.second
}
- assertThat("Sequence of selected pages should be $expectedPageSelects: ${dumpEvents()}",
- selectEvents.map { it.position }, equalTo(expectedPageSelects))
+ assertThat(
+ "Sequence of selected pages should be $expectedPageSelects: ${dumpEvents()}",
+ selectEvents.map { it.position }, equalTo(expectedPageSelects)
+ )
val settleEvent = OnPageScrollStateChangedEvent(SETTLING)
val idleEvent = OnPageScrollStateChangedEvent(IDLE)
val events = eventsCopy
events.forEachIndexed { i, event ->
if (event is OnPageSelectedEvent) {
- assertThat("OnPageSelectedEvents cannot be the first or last event: " +
- dumpEvents(), i, isBetweenInEx(1, eventCount - 1))
+ assertThat(
+ "OnPageSelectedEvents cannot be the first or last event: " +
+ dumpEvents(),
+ i, isBetweenInEx(1, eventCount - 1)
+ )
val isAfterSettleEvent = events[i - 1] == settleEvent
val isBeforeIdleEvent = events[i + 1] == idleEvent
- assertThat("OnPageSelectedEvent at index $i must follow a SETTLE event or precede" +
+ assertThat(
+ "OnPageSelectedEvent at index $i must follow a SETTLE event or precede" +
" an IDLE event, but not both: ${dumpEvents()}",
- isAfterSettleEvent.xor(isBeforeIdleEvent), equalTo(true))
+ isAfterSettleEvent.xor(isBeforeIdleEvent), equalTo(true)
+ )
}
}
}
@@ -683,8 +726,10 @@
otherPage: Int,
pageSize: Int
) = forEach {
- assertThat(it.position + it.positionOffset.toDouble(),
- isBetweenInInMinMax(initialPage.toDouble(), otherPage.toDouble()))
+ assertThat(
+ it.position + it.positionOffset.toDouble(),
+ isBetweenInInMinMax(initialPage.toDouble(), otherPage.toDouble())
+ )
assertThat(it.positionOffset, isBetweenInEx(0f, 1f))
assertThat((it.positionOffset * pageSize).roundToInt(), equalTo(it.positionOffsetPixels))
}
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/FragmentTransactionCallbackTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/FragmentTransactionCallbackTest.kt
index c9096c3..9246aab 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/FragmentTransactionCallbackTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/FragmentTransactionCallbackTest.kt
@@ -73,28 +73,33 @@
latch1.awaitStrict(5)
// then 1
- assertThat(log.consume(), equalTo(listOf(
- "Adapter:onFragmentPreAdded(<no-tag>)",
- "Lifecycle:onFragmentPreAttached(f0)",
- "Lifecycle:onFragmentAttached(f0)",
- "Lifecycle:onFragmentPreCreated(f0)",
- "Lifecycle:onFragmentCreated(f0)",
- "Lifecycle:onFragmentViewCreated(f0)",
- "Lifecycle:onFragmentActivityCreated(f0)",
- "Lifecycle:onFragmentStarted(f0)",
- "Adapter:onFragmentMaxLifecyclePreUpdated(f0 at RESUMED)",
- "Lifecycle:onFragmentResumed(f0)",
- "Adapter:onFragmentMaxLifecycleUpdated(f0 at RESUMED)",
- "Adapter:onFragmentAdded(f0)",
- "Adapter:onFragmentPreAdded(<no-tag>)",
- "Lifecycle:onFragmentPreAttached(f1)",
- "Lifecycle:onFragmentAttached(f1)",
- "Lifecycle:onFragmentPreCreated(f1)",
- "Lifecycle:onFragmentCreated(f1)",
- "Lifecycle:onFragmentViewCreated(f1)",
- "Lifecycle:onFragmentActivityCreated(f1)",
- "Lifecycle:onFragmentStarted(f1)",
- "Adapter:onFragmentAdded(f1)"))
+ assertThat(
+ log.consume(),
+ equalTo(
+ listOf(
+ "Adapter:onFragmentPreAdded(<no-tag>)",
+ "Lifecycle:onFragmentPreAttached(f0)",
+ "Lifecycle:onFragmentAttached(f0)",
+ "Lifecycle:onFragmentPreCreated(f0)",
+ "Lifecycle:onFragmentCreated(f0)",
+ "Lifecycle:onFragmentViewCreated(f0)",
+ "Lifecycle:onFragmentActivityCreated(f0)",
+ "Lifecycle:onFragmentStarted(f0)",
+ "Adapter:onFragmentMaxLifecyclePreUpdated(f0 at RESUMED)",
+ "Lifecycle:onFragmentResumed(f0)",
+ "Adapter:onFragmentMaxLifecycleUpdated(f0 at RESUMED)",
+ "Adapter:onFragmentAdded(f0)",
+ "Adapter:onFragmentPreAdded(<no-tag>)",
+ "Lifecycle:onFragmentPreAttached(f1)",
+ "Lifecycle:onFragmentAttached(f1)",
+ "Lifecycle:onFragmentPreCreated(f1)",
+ "Lifecycle:onFragmentCreated(f1)",
+ "Lifecycle:onFragmentViewCreated(f1)",
+ "Lifecycle:onFragmentActivityCreated(f1)",
+ "Lifecycle:onFragmentStarted(f1)",
+ "Adapter:onFragmentAdded(f1)"
+ )
+ )
)
// when 2: current item changed to next page
@@ -105,24 +110,29 @@
latch2.awaitStrict(5)
// then 2
- assertThat(log.consume(), equalTo(listOf(
- "Adapter:onFragmentPreAdded(<no-tag>)",
- "Lifecycle:onFragmentPreAttached(f2)",
- "Lifecycle:onFragmentAttached(f2)",
- "Lifecycle:onFragmentPreCreated(f2)",
- "Lifecycle:onFragmentCreated(f2)",
- "Lifecycle:onFragmentViewCreated(f2)",
- "Lifecycle:onFragmentActivityCreated(f2)",
- "Lifecycle:onFragmentStarted(f2)",
- "Adapter:onFragmentAdded(f2)",
- "Adapter:onFragmentMaxLifecyclePreUpdated(f0 at STARTED)",
- "Adapter:onFragmentMaxLifecyclePreUpdated(f2 at STARTED)",
- "Adapter:onFragmentMaxLifecyclePreUpdated(f1 at RESUMED)",
- "Lifecycle:onFragmentPaused(f0)",
- "Lifecycle:onFragmentResumed(f1)",
- "Adapter:onFragmentMaxLifecycleUpdated(f1 at RESUMED)",
- "Adapter:onFragmentMaxLifecycleUpdated(f2 at STARTED)",
- "Adapter:onFragmentMaxLifecycleUpdated(f0 at STARTED)"))
+ assertThat(
+ log.consume(),
+ equalTo(
+ listOf(
+ "Adapter:onFragmentPreAdded(<no-tag>)",
+ "Lifecycle:onFragmentPreAttached(f2)",
+ "Lifecycle:onFragmentAttached(f2)",
+ "Lifecycle:onFragmentPreCreated(f2)",
+ "Lifecycle:onFragmentCreated(f2)",
+ "Lifecycle:onFragmentViewCreated(f2)",
+ "Lifecycle:onFragmentActivityCreated(f2)",
+ "Lifecycle:onFragmentStarted(f2)",
+ "Adapter:onFragmentAdded(f2)",
+ "Adapter:onFragmentMaxLifecyclePreUpdated(f0 at STARTED)",
+ "Adapter:onFragmentMaxLifecyclePreUpdated(f2 at STARTED)",
+ "Adapter:onFragmentMaxLifecyclePreUpdated(f1 at RESUMED)",
+ "Lifecycle:onFragmentPaused(f0)",
+ "Lifecycle:onFragmentResumed(f1)",
+ "Adapter:onFragmentMaxLifecycleUpdated(f1 at RESUMED)",
+ "Adapter:onFragmentMaxLifecycleUpdated(f2 at STARTED)",
+ "Adapter:onFragmentMaxLifecycleUpdated(f0 at STARTED)"
+ )
+ )
)
// when 3: the last page is removed from the collection
@@ -135,19 +145,24 @@
latch3.awaitStrict(5)
// then 3
- assertThat(log.consume(), equalTo(listOf(
- "Adapter:onFragmentMaxLifecyclePreUpdated(f0 at STARTED)",
- "Adapter:onFragmentMaxLifecyclePreUpdated(f2 at STARTED)",
- "Adapter:onFragmentMaxLifecyclePreUpdated(f1 at RESUMED)",
- "Adapter:onFragmentMaxLifecycleUpdated(f1 at RESUMED)",
- "Adapter:onFragmentMaxLifecycleUpdated(f2 at STARTED)",
- "Adapter:onFragmentMaxLifecycleUpdated(f0 at STARTED)",
- "Adapter:onFragmentPreRemoved(f2)",
- "Lifecycle:onFragmentStopped(f2)",
- "Lifecycle:onFragmentViewDestroyed(f2)",
- "Lifecycle:onFragmentDestroyed(f2)",
- "Lifecycle:onFragmentDetached(f2)",
- "Adapter:onFragmentRemoved(<no-tag>)"))
+ assertThat(
+ log.consume(),
+ equalTo(
+ listOf(
+ "Adapter:onFragmentMaxLifecyclePreUpdated(f0 at STARTED)",
+ "Adapter:onFragmentMaxLifecyclePreUpdated(f2 at STARTED)",
+ "Adapter:onFragmentMaxLifecyclePreUpdated(f1 at RESUMED)",
+ "Adapter:onFragmentMaxLifecycleUpdated(f1 at RESUMED)",
+ "Adapter:onFragmentMaxLifecycleUpdated(f2 at STARTED)",
+ "Adapter:onFragmentMaxLifecycleUpdated(f0 at STARTED)",
+ "Adapter:onFragmentPreRemoved(f2)",
+ "Lifecycle:onFragmentStopped(f2)",
+ "Lifecycle:onFragmentViewDestroyed(f2)",
+ "Lifecycle:onFragmentDestroyed(f2)",
+ "Lifecycle:onFragmentDetached(f2)",
+ "Adapter:onFragmentRemoved(<no-tag>)"
+ )
+ )
)
// when 4: recreate activity
@@ -329,36 +344,39 @@
}
private fun createRecordingFragmentTransactionCallback(log: RecordingLogger):
- FragmentTransactionCallback {
- return object : FragmentTransactionCallback() {
- override fun onFragmentPreAdded(fragment: Fragment): OnPostEventListener {
- log.append("Adapter:onFragmentPreAdded(${fragment.name})")
- return OnPostEventListener {
- log.append("Adapter:onFragmentAdded(${fragment.name})")
+ FragmentTransactionCallback {
+ return object : FragmentTransactionCallback() {
+ override fun onFragmentPreAdded(fragment: Fragment): OnPostEventListener {
+ log.append("Adapter:onFragmentPreAdded(${fragment.name})")
+ return OnPostEventListener {
+ log.append("Adapter:onFragmentAdded(${fragment.name})")
+ }
}
- }
- override fun onFragmentPreRemoved(fragment: Fragment): OnPostEventListener {
- log.append("Adapter:onFragmentPreRemoved(${fragment.name})")
- return OnPostEventListener {
- log.append("Adapter:onFragmentRemoved(${fragment.name})")
+ override fun onFragmentPreRemoved(fragment: Fragment): OnPostEventListener {
+ log.append("Adapter:onFragmentPreRemoved(${fragment.name})")
+ return OnPostEventListener {
+ log.append("Adapter:onFragmentRemoved(${fragment.name})")
+ }
}
- }
- override fun onFragmentMaxLifecyclePreUpdated(
- fragment: Fragment,
- maxLifecycleState: Lifecycle.State
- ): OnPostEventListener {
- log.append("Adapter:onFragmentMaxLifecyclePreUpdated(${fragment.name} " +
- "at $maxLifecycleState)")
- return OnPostEventListener {
- log.append("Adapter:onFragmentMaxLifecycleUpdated(${fragment.name} " +
+ override fun onFragmentMaxLifecyclePreUpdated(
+ fragment: Fragment,
+ maxLifecycleState: Lifecycle.State
+ ): OnPostEventListener {
+ log.append(
+ "Adapter:onFragmentMaxLifecyclePreUpdated(${fragment.name} " +
"at $maxLifecycleState)"
)
+ return OnPostEventListener {
+ log.append(
+ "Adapter:onFragmentMaxLifecycleUpdated(${fragment.name} " +
+ "at $maxLifecycleState)"
+ )
+ }
}
}
}
- }
}
private class RecordingLogger {
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/OffscreenPageLimitTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/OffscreenPageLimitTest.kt
index 2920809..5d7de7b 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/OffscreenPageLimitTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/OffscreenPageLimitTest.kt
@@ -124,24 +124,32 @@
assertThat(lower.toDouble(), lessThanOrEqualTo(position))
assertThat(upper.toDouble(), greaterThanOrEqualTo(position))
// Then verify the onscreen pages:
- assertThat("There should be ${upper - lower + 1} pages laid out at event $i. " +
+ assertThat(
+ "There should be ${upper - lower + 1} pages laid out at event $i. " +
"Events: ${recorder.dumpEvents()}",
- onscreen.size, equalTo(upper - lower + 1))
+ onscreen.size, equalTo(upper - lower + 1)
+ )
(lower..upper).forEach { laidOutPage ->
- assertThat("Page $laidOutPage should be laid out at event $i. " +
+ assertThat(
+ "Page $laidOutPage should be laid out at event $i. " +
"Events: ${recorder.dumpEvents()}",
- onscreen, hasItem(laidOutPage))
+ onscreen, hasItem(laidOutPage)
+ )
}
}
}
}
// Verify that laid out pages don't change after the last scroll event
- assertThat("The last OnChildViewAdded should be before an OnPageScrolledEvent. " +
+ assertThat(
+ "The last OnChildViewAdded should be before an OnPageScrolledEvent. " +
"Events: ${recorder.dumpEvents()}",
- recorder.lastAddedIx, lessThan(recorder.lastScrolledIx))
- assertThat("The last OnChildViewRemoved should be before an OnPageScrolledEvent. " +
+ recorder.lastAddedIx, lessThan(recorder.lastScrolledIx)
+ )
+ assertThat(
+ "The last OnChildViewRemoved should be before an OnPageScrolledEvent. " +
"Events: ${recorder.dumpEvents()}",
- recorder.lastRemovedIx, lessThan(recorder.lastScrolledIx))
+ recorder.lastRemovedIx, lessThan(recorder.lastScrolledIx)
+ )
}
private fun ViewPager2.addNewRecordingCallback(): RecordingCallback {
@@ -163,7 +171,8 @@
data class OnChildViewRemoved(val position: Int) : Event()
}
- private class RecordingCallback : ViewPager2.OnPageChangeCallback(),
+ private class RecordingCallback :
+ ViewPager2.OnPageChangeCallback(),
ViewGroup.OnHierarchyChangeListener {
private val events = mutableListOf<Event>()
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/OnApplyWindowInsetsListenerTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/OnApplyWindowInsetsListenerTest.kt
index 6769a0d..9c68982 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/OnApplyWindowInsetsListenerTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/OnApplyWindowInsetsListenerTest.kt
@@ -104,14 +104,14 @@
// dispatcher didn't stop the default dispatcher
assertThat(
"WindowInsets were dispatched ${recordedInsets.size} times to page $i. " +
- "Expected only 1 dispatch",
+ "Expected only 1 dispatch",
recordedInsets.size,
equalTo(1)
)
assertThat(
"Page $i received modified insets:\n" +
- "expected: $expectedWindowInsets\n" +
- "actual: ${recordedInsets[0]}",
+ "expected: $expectedWindowInsets\n" +
+ "actual: ${recordedInsets[0]}",
insetsEquals(recordedInsets[0], expectedWindowInsets),
equalTo(true)
)
@@ -128,9 +128,9 @@
} else {
// Otherwise, check what we can access (and what was present < 28)
a.isConsumed == b.isConsumed &&
- a.isRound == b.isRound &&
- a.systemWindowInsets == b.systemWindowInsets &&
- a.stableInsets == b.stableInsets
+ a.isRound == b.isRound &&
+ a.systemWindowInsets == b.systemWindowInsets &&
+ a.stableInsets == b.stableInsets
}
}
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PaddingMarginDecorationTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PaddingMarginDecorationTest.kt
index bf41658..7b5311c 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PaddingMarginDecorationTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PaddingMarginDecorationTest.kt
@@ -133,12 +133,15 @@
}
private val adapterProvider: AdapterProviderForItems get() {
- return AdapterProviderForItems("adapterProvider", if (config.itemMarginPx > 0) {
+ return AdapterProviderForItems(
+ "adapterProvider",
+ if (config.itemMarginPx > 0) {
{ items -> { MarginViewAdapter(config.itemMarginPx, items) } }
} else {
{ items -> { ViewAdapter(items) } }
- })
- }
+ }
+ )
+ }
class MarginViewAdapter(private val margin: Int, items: List<String>) : ViewAdapter(items) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
@@ -258,8 +261,8 @@
// dive into scroll events
val sortOrder =
- if (targetPage - initialPage > 0) SortOrder.ASC
- else SortOrder.DESC
+ if (targetPage - initialPage > 0) SortOrder.ASC
+ else SortOrder.DESC
scrollEvents.assertPositionSorted(sortOrder)
scrollEvents.assertOffsetSorted(sortOrder)
scrollEvents.assertValueCorrectness(initialPage, targetPage, viewPager.pageSize)
@@ -309,22 +312,34 @@
if (targetPage == initialPage && edgePages.contains(targetPage)) {
callback.apply {
// verify all events
- assertThat("Events should start with a state change to DRAGGING",
- draggingIx, equalTo(0))
- assertThat("Last event should be a state change to IDLE",
- idleIx, equalTo(lastIx))
- assertThat("All events but the state changes to DRAGGING and IDLE" +
+ assertThat(
+ "Events should start with a state change to DRAGGING",
+ draggingIx, equalTo(0)
+ )
+ assertThat(
+ "Last event should be a state change to IDLE",
+ idleIx, equalTo(lastIx)
+ )
+ assertThat(
+ "All events but the state changes to DRAGGING and IDLE" +
" should be scroll events",
- scrollEventCount, equalTo(eventCount - 2))
+ scrollEventCount, equalTo(eventCount - 2)
+ )
// dive into scroll events
scrollEvents.forEach {
- assertThat("All scroll events should report page $targetPage",
- it.position, equalTo(targetPage))
- assertThat("All scroll events should report an offset of 0f",
- it.positionOffset, equalTo(0f))
- assertThat("All scroll events should report an offset of 0px",
- it.positionOffsetPixels, equalTo(0))
+ assertThat(
+ "All scroll events should report page $targetPage",
+ it.position, equalTo(targetPage)
+ )
+ assertThat(
+ "All scroll events should report an offset of 0f",
+ it.positionOffset, equalTo(0f)
+ )
+ assertThat(
+ "All scroll events should report an offset of 0px",
+ it.positionOffsetPixels, equalTo(0)
+ )
}
}
}
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageChangeCallbackTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageChangeCallbackTest.kt
index 3e3228b..4ecaaf5 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageChangeCallbackTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageChangeCallbackTest.kt
@@ -135,8 +135,8 @@
// dive into scroll events
val sortOrder =
- if (targetPage - initialPage > 0) SortOrder.ASC
- else SortOrder.DESC
+ if (targetPage - initialPage > 0) SortOrder.ASC
+ else SortOrder.DESC
scrollEvents.assertPositionSorted(sortOrder)
scrollEvents.assertOffsetSorted(sortOrder)
scrollEvents.assertValueCorrectness(initialPage, targetPage, viewPager.pageSize)
@@ -189,22 +189,34 @@
if (targetPage == initialPage && edgePages.contains(targetPage)) {
callback.apply {
// verify all events
- assertThat("Events should start with a state change to DRAGGING",
- draggingIx, equalTo(0))
- assertThat("Last event should be a state change to IDLE",
- idleIx, equalTo(lastIx))
- assertThat("All events but the state changes to DRAGGING and IDLE" +
+ assertThat(
+ "Events should start with a state change to DRAGGING",
+ draggingIx, equalTo(0)
+ )
+ assertThat(
+ "Last event should be a state change to IDLE",
+ idleIx, equalTo(lastIx)
+ )
+ assertThat(
+ "All events but the state changes to DRAGGING and IDLE" +
" should be scroll events",
- scrollEventCount, equalTo(eventCount - 2))
+ scrollEventCount, equalTo(eventCount - 2)
+ )
// dive into scroll events
scrollEvents.forEach {
- assertThat("All scroll events should report page $targetPage",
- it.position, equalTo(targetPage))
- assertThat("All scroll events should report an offset of 0f",
- it.positionOffset, equalTo(0f))
- assertThat("All scroll events should report an offset of 0px",
- it.positionOffsetPixels, equalTo(0))
+ assertThat(
+ "All scroll events should report page $targetPage",
+ it.position, equalTo(targetPage)
+ )
+ assertThat(
+ "All scroll events should report an offset of 0f",
+ it.positionOffset, equalTo(0f)
+ )
+ assertThat(
+ "All scroll events should report an offset of 0px",
+ it.positionOffsetPixels, equalTo(0)
+ )
}
}
}
@@ -246,27 +258,43 @@
// then
callback.apply {
// verify all events
- assertThat("There should be exactly 1 dragging event",
- stateEvents(SCROLL_STATE_DRAGGING).size, equalTo(1))
- assertThat("There should be exactly 1 settling event",
- stateEvents(SCROLL_STATE_SETTLING).size, equalTo(1))
- assertThat("There should be exactly 1 idle event",
- stateEvents(SCROLL_STATE_IDLE).size, equalTo(1))
- assertThat("Events should start with a state change to DRAGGING",
- draggingIx, equalTo(0))
- assertThat("The settling event should be fired between the first and the last" +
+ assertThat(
+ "There should be exactly 1 dragging event",
+ stateEvents(SCROLL_STATE_DRAGGING).size, equalTo(1)
+ )
+ assertThat(
+ "There should be exactly 1 settling event",
+ stateEvents(SCROLL_STATE_SETTLING).size, equalTo(1)
+ )
+ assertThat(
+ "There should be exactly 1 idle event",
+ stateEvents(SCROLL_STATE_IDLE).size, equalTo(1)
+ )
+ assertThat(
+ "Events should start with a state change to DRAGGING",
+ draggingIx, equalTo(0)
+ )
+ assertThat(
+ "The settling event should be fired between the first and the last" +
" scroll event",
- settlingIx, isBetweenInEx(firstScrolledIx + 1, lastScrolledIx))
- assertThat("The idle event should be the last global event",
- idleIx, equalTo(lastIx))
- assertThat("All events other then the state changes should be scroll events",
- scrollEventCount, equalTo(eventCount - 3))
+ settlingIx, isBetweenInEx(firstScrolledIx + 1, lastScrolledIx)
+ )
+ assertThat(
+ "The idle event should be the last global event",
+ idleIx, equalTo(lastIx)
+ )
+ assertThat(
+ "All events other then the state changes should be scroll events",
+ scrollEventCount, equalTo(eventCount - 3)
+ )
// dive into scroll events
scrollEvents.assertPositionSorted(SortOrder.DESC)
scrollEventsBeforeSettling.assertOffsetSorted(SortOrder.ASC)
- assertThat(scrollEvents, // quick check
- equalTo(scrollEventsBeforeSettling + scrollEventsAfterSettling))
+ assertThat(
+ scrollEvents, // quick check
+ equalTo(scrollEventsBeforeSettling + scrollEventsAfterSettling)
+ )
scrollEvents.assertValueCorrectness(0, 0, viewPager.pageSize)
scrollEvents.assertLastCorrect(0)
}
@@ -309,28 +337,44 @@
// then
callback.apply {
// verify all events
- assertThat("There should be exactly 1 dragging event",
- stateEvents(SCROLL_STATE_DRAGGING).size, equalTo(1))
- assertThat("There should be exactly 1 settling event",
- stateEvents(SCROLL_STATE_SETTLING).size, equalTo(1))
- assertThat("There should be exactly 1 idle event",
- stateEvents(SCROLL_STATE_IDLE).size, equalTo(1))
- assertThat("Events should start with a state change to DRAGGING",
- draggingIx, equalTo(0))
- assertThat("The settling event should be fired between the first and the last " +
+ assertThat(
+ "There should be exactly 1 dragging event",
+ stateEvents(SCROLL_STATE_DRAGGING).size, equalTo(1)
+ )
+ assertThat(
+ "There should be exactly 1 settling event",
+ stateEvents(SCROLL_STATE_SETTLING).size, equalTo(1)
+ )
+ assertThat(
+ "There should be exactly 1 idle event",
+ stateEvents(SCROLL_STATE_IDLE).size, equalTo(1)
+ )
+ assertThat(
+ "Events should start with a state change to DRAGGING",
+ draggingIx, equalTo(0)
+ )
+ assertThat(
+ "The settling event should be fired between the first and the last " +
"scroll event",
- settlingIx, isBetweenInEx(firstScrolledIx + 1, lastScrolledIx))
- assertThat("The idle event should be the last global event",
- idleIx, equalTo(lastIx))
- assertThat("All events other then the state changes should be scroll events",
- scrollEventCount, equalTo(eventCount - 3))
+ settlingIx, isBetweenInEx(firstScrolledIx + 1, lastScrolledIx)
+ )
+ assertThat(
+ "The idle event should be the last global event",
+ idleIx, equalTo(lastIx)
+ )
+ assertThat(
+ "All events other then the state changes should be scroll events",
+ scrollEventCount, equalTo(eventCount - 3)
+ )
// dive into scroll events
scrollEvents.assertPositionSorted(SortOrder.ASC)
scrollEventsBeforeSettling.assertOffsetSorted(SortOrder.DESC)
scrollEventsAfterSettling.assertOffsetSorted(SortOrder.ASC)
- assertThat(scrollEvents, // quick check
- equalTo(scrollEventsBeforeSettling + scrollEventsAfterSettling))
+ assertThat(
+ scrollEvents, // quick check
+ equalTo(scrollEventsBeforeSettling + scrollEventsAfterSettling)
+ )
scrollEvents.assertValueCorrectness(1, 2, viewPager.pageSize)
scrollEvents.dropLast(1).assertValueCorrectness(1, 1, viewPager.pageSize)
scrollEvents.assertLastCorrect(2)
@@ -396,8 +440,10 @@
val sortOrder = if (pageIxDelta > 0) SortOrder.ASC else SortOrder.DESC
scrollEvents.assertPositionSorted(sortOrder)
scrollEvents.assertOffsetSorted(sortOrder)
- scrollEvents.assertValueCorrectness(currentPage, targetPage,
- viewPager.pageSize)
+ scrollEvents.assertValueCorrectness(
+ currentPage, targetPage,
+ viewPager.pageSize
+ )
scrollEvents.assertLastCorrect(targetPage)
scrollEvents.assertMaxShownPages()
}
@@ -602,21 +648,36 @@
// then
callback.apply {
- assertThat("viewPager.getCurrentItem() does not return the target page",
- viewPager.currentItem, equalTo(targetPage))
- assertThat("Currently shown page is not the target page",
- viewPager.currentCompletelyVisibleItem, equalTo(targetPage))
- assertThat("First overall event is not a SETTLING event",
- settlingIx, equalTo(0))
- assertThat("Number of onPageSelected events is not 2",
- selectEvents.count(), equalTo(2))
- assertThat("First onPageSelected event is not the second overall event",
- pageSelectedIx(targetPage), equalTo(1))
- assertThat("Unexpected events were fired after the config change",
- eventsAfter(marker), equalTo(listOf(
- OnPageSelectedEvent(targetPage),
- OnPageScrolledEvent(targetPage, 0f, 0)
- )))
+ assertThat(
+ "viewPager.getCurrentItem() does not return the target page",
+ viewPager.currentItem, equalTo(targetPage)
+ )
+ assertThat(
+ "Currently shown page is not the target page",
+ viewPager.currentCompletelyVisibleItem, equalTo(targetPage)
+ )
+ assertThat(
+ "First overall event is not a SETTLING event",
+ settlingIx, equalTo(0)
+ )
+ assertThat(
+ "Number of onPageSelected events is not 2",
+ selectEvents.count(), equalTo(2)
+ )
+ assertThat(
+ "First onPageSelected event is not the second overall event",
+ pageSelectedIx(targetPage), equalTo(1)
+ )
+ assertThat(
+ "Unexpected events were fired after the config change",
+ eventsAfter(marker),
+ equalTo(
+ listOf(
+ OnPageSelectedEvent(targetPage),
+ OnPageScrolledEvent(targetPage, 0f, 0)
+ )
+ )
+ )
}
}
}
@@ -657,8 +718,12 @@
else -> {
assertThat(eventCount, equalTo(2))
assertThat(pageSelectedIx(targetPage), equalTo(0))
- assertThat(scrollEvents.last(), equalTo(
- OnPageScrolledEvent(targetPage, 0f, 0)))
+ assertThat(
+ scrollEvents.last(),
+ equalTo(
+ OnPageScrolledEvent(targetPage, 0f, 0)
+ )
+ )
}
}
}
@@ -682,11 +747,14 @@
val touchSlop = vc.scaledPagingTouchSlop
// when
- tryNTimes(3, resetBlock = {
- test.resetViewPagerTo(currentPage)
- test.viewPager.unregisterOnPageChangeCallback(recorder)
- recorder = test.viewPager.addNewRecordingCallback()
- }) {
+ tryNTimes(
+ 3,
+ resetBlock = {
+ test.resetViewPagerTo(currentPage)
+ test.viewPager.unregisterOnPageChangeCallback(recorder)
+ recorder = test.viewPager.addNewRecordingCallback()
+ }
+ ) {
val settleLatch = test.viewPager.addWaitForStateLatch(SCROLL_STATE_SETTLING)
val idleLatch = test.viewPager.addWaitForIdleLatch()
@@ -717,8 +785,12 @@
// 2) State sequence was DRAGGING -> SETTLING -> DRAGGING -> SETTLING -> IDLE
assertThat(
recorder.stateEvents.map { it.state },
- equalTo(listOf(SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING,
- SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING, SCROLL_STATE_IDLE))
+ equalTo(
+ listOf(
+ SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING,
+ SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING, SCROLL_STATE_IDLE
+ )
+ )
)
// 3) Page selected sequence was select(1) -> select(0)
@@ -777,12 +849,27 @@
@Test
fun test_scrollStateValuesInSync() {
- assertThat(ViewPager2.SCROLL_STATE_IDLE, allOf(equalTo(ViewPager.SCROLL_STATE_IDLE),
- equalTo(RecyclerView.SCROLL_STATE_IDLE)))
- assertThat(ViewPager2.SCROLL_STATE_DRAGGING, allOf(equalTo(ViewPager.SCROLL_STATE_DRAGGING),
- equalTo(RecyclerView.SCROLL_STATE_DRAGGING)))
- assertThat(ViewPager2.SCROLL_STATE_SETTLING, allOf(equalTo(ViewPager.SCROLL_STATE_SETTLING),
- equalTo(RecyclerView.SCROLL_STATE_SETTLING)))
+ assertThat(
+ ViewPager2.SCROLL_STATE_IDLE,
+ allOf(
+ equalTo(ViewPager.SCROLL_STATE_IDLE),
+ equalTo(RecyclerView.SCROLL_STATE_IDLE)
+ )
+ )
+ assertThat(
+ ViewPager2.SCROLL_STATE_DRAGGING,
+ allOf(
+ equalTo(ViewPager.SCROLL_STATE_DRAGGING),
+ equalTo(RecyclerView.SCROLL_STATE_DRAGGING)
+ )
+ )
+ assertThat(
+ ViewPager2.SCROLL_STATE_SETTLING,
+ allOf(
+ equalTo(ViewPager.SCROLL_STATE_SETTLING),
+ equalTo(RecyclerView.SCROLL_STATE_SETTLING)
+ )
+ )
}
@Test
@@ -880,9 +967,12 @@
newViewPager.registerOnPageChangeCallback(recorder)
}
// then
- assertThat(recorder.allEvents, equalTo(
- listOf(MarkerEvent(marker))
- .plus(expectedEvents(0)))
+ assertThat(
+ recorder.allEvents,
+ equalTo(
+ listOf(MarkerEvent(marker))
+ .plus(expectedEvents(0))
+ )
)
// given
@@ -896,10 +986,13 @@
newViewPager.registerOnPageChangeCallback(recorder)
}
// then
- assertThat(recorder.allEvents, equalTo(
- expectedEvents(targetPage)
- .plus(MarkerEvent(marker))
- .plus(expectedEvents(targetPage)))
+ assertThat(
+ recorder.allEvents,
+ equalTo(
+ expectedEvents(targetPage)
+ .plus(MarkerEvent(marker))
+ .plus(expectedEvents(targetPage))
+ )
)
}
@@ -910,8 +1003,11 @@
val adapterCount = test.viewPager.adapter!!.itemCount
listOf(-5, -1, n, n + 1, adapterCount, adapterCount + 1).forEach { targetPage ->
- assertThat("Test should only test setCurrentItem for pages out of bounds, " +
- "bounds are [0, $n)", targetPage, not(isBetweenInEx(0, n)))
+ assertThat(
+ "Test should only test setCurrentItem for pages out of bounds, " +
+ "bounds are [0, $n)",
+ targetPage, not(isBetweenInEx(0, n))
+ )
// given
val initialPage = test.viewPager.currentItem
val callback = test.viewPager.addNewRecordingCallback()
@@ -1120,8 +1216,10 @@
is OnPageScrolledEvent -> {
assertThat(selectedPage, not(equalTo(-1)))
val currScrollPosition = event.position + event.positionOffset.toDouble()
- assertThat(currScrollPosition,
- isBetweenInInMinMax(prevScrollPosition, selectedPage.toDouble()))
+ assertThat(
+ currScrollPosition,
+ isBetweenInInMinMax(prevScrollPosition, selectedPage.toDouble())
+ )
prevScrollPosition = currScrollPosition
}
}
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageFillTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageFillTest.kt
index 75c233e..6f5d0c5 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageFillTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageFillTest.kt
@@ -56,9 +56,11 @@
private fun test_pageFillEnforced(layoutParams: LayoutParams) {
val fixedViewSizeAdapter = object : RecyclerView.Adapter<ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- return object : ViewHolder(View(parent.context).apply {
- this.layoutParams = layoutParams
- }) {}
+ return object : ViewHolder(
+ View(parent.context).apply {
+ this.layoutParams = layoutParams
+ }
+ ) {}
}
override fun getItemCount(): Int = 1
@@ -72,8 +74,12 @@
viewPager.measure(0, 0)
fail("Expected exception was not thrown")
} catch (e: IllegalStateException) {
- assertThat(e.message, containsString(
- "Pages must fill the whole ViewPager2 (use match_parent)"))
+ assertThat(
+ e.message,
+ containsString(
+ "Pages must fill the whole ViewPager2 (use match_parent)"
+ )
+ )
}
}
}
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageTransformerTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageTransformerTest.kt
index 85ece6c..dee4c31 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageTransformerTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/PageTransformerTest.kt
@@ -263,7 +263,8 @@
private fun List<Event>.assertSnappedRelativeToPage(snappedPage: Int) {
map { it as TransformPageEvent }.forEach {
- assertThat("transformPage() call must be snapped at page $snappedPage",
+ assertThat(
+ "transformPage() call must be snapped at page $snappedPage",
// event.page - event.offset resolves to the currently visible page index
it.page - it.offset.toDouble(), equalTo(snappedPage.toDouble())
)
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SetItemWhileScrollInProgressTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SetItemWhileScrollInProgressTest.kt
index e45e4d9..dfa3e30 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SetItemWhileScrollInProgressTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SetItemWhileScrollInProgressTest.kt
@@ -195,7 +195,7 @@
val stateEvents get() = events.mapNotNull { it as? OnPageScrollStateChangedEvent }
val lastEvent get() = events.last()
val lastState get() = events.findLast { it is OnPageScrollStateChangedEvent }
- as? OnPageScrollStateChangedEvent
+ as? OnPageScrollStateChangedEvent
val lastScroll get() = events.findLast { it is OnPageScrolledEvent } as? OnPageScrolledEvent
val lastSelect get() = events.findLast { it is OnPageSelectedEvent } as? OnPageSelectedEvent
val draggingIx get() = events.indexOf(OnPageScrollStateChangedEvent(SCROLL_STATE_DRAGGING))
@@ -225,8 +225,8 @@
private val RecordingCallback.isTestFinished get() = synchronized(events) {
lastState?.state == 0 &&
- lastSelect?.position == lastScroll?.position &&
- lastScroll?.positionOffsetPixels == 0
+ lastSelect?.position == lastScroll?.position &&
+ lastScroll?.positionOffsetPixels == 0
}
private fun RecordingCallback.assertPageSelectedEventFired(targetPage: Int) {
@@ -354,9 +354,9 @@
instantScrolls = setOf(1)
)
)
- .plus(
- List(RANDOM_TESTS_PER_CONFIG) { createRandomTest(orientation) }
- )
+ .plus(
+ List(RANDOM_TESTS_PER_CONFIG) { createRandomTest(orientation) }
+ )
// To rerun a failed random test, lookup the seed and the orientation of the test in the test
// output, give it a name and add the following code to createTestSet():
// .plus(listOf(
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SwipeTest.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SwipeTest.kt
index 91bf776..d1d21f9 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SwipeTest.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SwipeTest.kt
@@ -52,8 +52,10 @@
if (modifiedPageValue != null) {
expectedValues[currentPage] = modifiedPageValue
runOnUiThreadSync {
- PageView.setPageText(PageView.findPageInActivity(activity)!!,
- modifiedPageValue)
+ PageView.setPageText(
+ PageView.findPageInActivity(activity)!!,
+ modifiedPageValue
+ )
}
}
@@ -111,59 +113,64 @@
orientation: Int
): List<TestConfig> {
return listOf(
- TestConfig(
- title = "basic pass",
- adapterProvider = adapterProvider,
- orientation = orientation,
- totalPages = 4,
- pageSequence = listOf(0, 1, 2, 3, 3, 2, 1, 0, 0)
- ),
- TestConfig(
- title = "full pass",
- adapterProvider = adapterProvider,
- orientation = orientation,
- totalPages = 8,
- pageSequence = listOf(1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0)
- ),
- TestConfig(
- title = "swipe beyond edge pages",
- adapterProvider = adapterProvider,
- orientation = orientation,
- totalPages = 4,
- pageSequence = listOf(0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0)
- ),
- TestConfig(
- title = "config change",
- adapterProvider = adapterProvider,
- orientation = orientation,
- totalPages = 7,
- pageSequence = listOf(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0),
- configChangeSteps = setOf(3, 5, 7)
- ),
- TestConfig(
- title = "regression1",
- adapterProvider = adapterProvider,
- orientation = orientation,
- totalPages = 10,
- pageSequence = listOf(1, 2, 3, 2, 1, 2, 3, 4)
- ),
- TestConfig(
- title = "regression2",
- adapterProvider = adapterProvider,
- orientation = orientation,
- totalPages = 10,
- pageSequence = listOf(1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5)
- ),
- TestConfig(
- title = "regression3",
- adapterProvider = adapterProvider,
- orientation = orientation,
- totalPages = 10,
- pageSequence = listOf(1, 2, 3, 2, 1, 2, 3, 2, 1, 0)
- ))
- .plus(if (adapterProvider.supportsMutations) createMutationTests(adapterProvider,
- orientation) else emptyList())
- .plus(createRandomTests(adapterProvider, orientation))
+ TestConfig(
+ title = "basic pass",
+ adapterProvider = adapterProvider,
+ orientation = orientation,
+ totalPages = 4,
+ pageSequence = listOf(0, 1, 2, 3, 3, 2, 1, 0, 0)
+ ),
+ TestConfig(
+ title = "full pass",
+ adapterProvider = adapterProvider,
+ orientation = orientation,
+ totalPages = 8,
+ pageSequence = listOf(1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0)
+ ),
+ TestConfig(
+ title = "swipe beyond edge pages",
+ adapterProvider = adapterProvider,
+ orientation = orientation,
+ totalPages = 4,
+ pageSequence = listOf(0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0)
+ ),
+ TestConfig(
+ title = "config change",
+ adapterProvider = adapterProvider,
+ orientation = orientation,
+ totalPages = 7,
+ pageSequence = listOf(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0),
+ configChangeSteps = setOf(3, 5, 7)
+ ),
+ TestConfig(
+ title = "regression1",
+ adapterProvider = adapterProvider,
+ orientation = orientation,
+ totalPages = 10,
+ pageSequence = listOf(1, 2, 3, 2, 1, 2, 3, 4)
+ ),
+ TestConfig(
+ title = "regression2",
+ adapterProvider = adapterProvider,
+ orientation = orientation,
+ totalPages = 10,
+ pageSequence = listOf(1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5)
+ ),
+ TestConfig(
+ title = "regression3",
+ adapterProvider = adapterProvider,
+ orientation = orientation,
+ totalPages = 10,
+ pageSequence = listOf(1, 2, 3, 2, 1, 2, 3, 2, 1, 0)
+ )
+ )
+ .plus(
+ if (adapterProvider.supportsMutations) createMutationTests(
+ adapterProvider,
+ orientation
+ ) else emptyList()
+ )
+ .plus(createRandomTests(adapterProvider, orientation))
}
// region mutation testing
@@ -176,15 +183,16 @@
@Orientation orientation: Int
): List<TestConfig> {
return listOf(
- TestConfig(
- title = "mutations",
- adapterProvider = adapterProvider,
- orientation = orientation,
- totalPages = 7,
- pageSequence = listOf(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0),
- configChangeSteps = setOf(8),
- stepToNewValue = mapOf(0 to "999", 1 to "100", 3 to "300", 5 to "500")
- ))
+ TestConfig(
+ title = "mutations",
+ adapterProvider = adapterProvider,
+ orientation = orientation,
+ totalPages = 7,
+ pageSequence = listOf(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0),
+ configChangeSteps = setOf(8),
+ stepToNewValue = mapOf(0 to "999", 1 to "100", 3 to "300", 5 to "500")
+ )
+ )
}
// endregion
@@ -197,44 +205,47 @@
): List<TestConfig> {
return (1..RANDOM_TESTS_PER_CONFIG).flatMap {
listOf(
- createRandomTest(
+ createRandomTest(
+ totalPages = 8,
+ sequenceLength = 50,
+ configChangeProbability = 0.0,
+ mutationProbability = 0.0,
+ advanceProbability = 0.875,
+ adapterProvider = adapterProvider,
+ orientation = orientation
+ ),
+ createRandomTest(
+ totalPages = 8,
+ sequenceLength = 10,
+ configChangeProbability = 0.5,
+ mutationProbability = 0.0,
+ advanceProbability = 0.875,
+ adapterProvider = adapterProvider,
+ orientation = orientation
+ )
+ )
+ .plus(
+ if (!adapterProvider.supportsMutations) emptyList() else listOf(
+ createRandomTest(
totalPages = 8,
sequenceLength = 50,
configChangeProbability = 0.0,
- mutationProbability = 0.0,
+ mutationProbability = 0.125,
advanceProbability = 0.875,
adapterProvider = adapterProvider,
orientation = orientation
- ),
- createRandomTest(
+ ),
+ createRandomTest(
totalPages = 8,
sequenceLength = 10,
configChangeProbability = 0.5,
- mutationProbability = 0.0,
+ mutationProbability = 0.125,
advanceProbability = 0.875,
adapterProvider = adapterProvider,
orientation = orientation
- ))
- .plus(if (!adapterProvider.supportsMutations) emptyList() else listOf(
- createRandomTest(
- totalPages = 8,
- sequenceLength = 50,
- configChangeProbability = 0.0,
- mutationProbability = 0.125,
- advanceProbability = 0.875,
- adapterProvider = adapterProvider,
- orientation = orientation
- ),
- createRandomTest(
- totalPages = 8,
- sequenceLength = 10,
- configChangeProbability = 0.5,
- mutationProbability = 0.125,
- advanceProbability = 0.875,
- adapterProvider = adapterProvider,
- orientation = orientation
- )
- ))
+ )
+ )
+ )
}
}
@@ -283,13 +294,13 @@
}
return TestConfig(
- title = "random_$seed",
- adapterProvider = adapterProvider,
- orientation = orientation,
- totalPages = totalPages,
- pageSequence = pageSequence,
- configChangeSteps = configChanges,
- stepToNewValue = stepToNewValue.mapValues { it.toString() }
+ title = "random_$seed",
+ adapterProvider = adapterProvider,
+ orientation = orientation,
+ totalPages = totalPages,
+ pageSequence = pageSequence,
+ configChangeSteps = configChanges,
+ stepToNewValue = stepToNewValue.mapValues { it.toString() }
)
}
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/FragmentAdapter.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/FragmentAdapter.kt
index 2d5c7fe..2a35e9b 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/FragmentAdapter.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/FragmentAdapter.kt
@@ -76,11 +76,13 @@
): View = PageView.inflatePage(layoutInflater, container)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- setValue(when {
- savedInstanceState != null -> savedInstanceState.getString(ARG_KEY)!!
- arguments != null -> arguments!!.getString(ARG_KEY)!!
- else -> throw IllegalStateException()
- })
+ setValue(
+ when {
+ savedInstanceState != null -> savedInstanceState.getString(ARG_KEY)!!
+ arguments != null -> arguments!!.getString(ARG_KEY)!!
+ else -> throw IllegalStateException()
+ }
+ )
}
fun setValue(value: String) {
diff --git a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageSwiperFakeDrag.kt b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageSwiperFakeDrag.kt
index a266dc5..9196a17 100644
--- a/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageSwiperFakeDrag.kt
+++ b/viewpager2/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageSwiperFakeDrag.kt
@@ -75,8 +75,10 @@
}
if (isInterrupted) {
- throw IllegalStateException("${javaClass.simpleName} was not reset after it was " +
- "interrupted")
+ throw IllegalStateException(
+ "${javaClass.simpleName} was not reset after it was " +
+ "interrupted"
+ )
}
// Send the fakeDrag events
diff --git a/wear/wear-complications-data/api/current.txt b/wear/wear-complications-data/api/current.txt
index 709e429..0e11d42 100644
--- a/wear/wear-complications-data/api/current.txt
+++ b/wear/wear-complications-data/api/current.txt
@@ -165,6 +165,24 @@
method public void onUpdateComplication(android.support.wearable.complications.ComplicationData?) throws android.os.RemoteException;
}
+ public final class DefaultComplicationProviderPolicy {
+ ctor public DefaultComplicationProviderPolicy();
+ ctor public DefaultComplicationProviderPolicy(int systemProvider);
+ ctor public DefaultComplicationProviderPolicy(android.content.ComponentName provider, int systemProviderFallback);
+ ctor public DefaultComplicationProviderPolicy(android.content.ComponentName primaryProvider, android.content.ComponentName secondaryProvider, int systemProviderFallback);
+ method public android.content.ComponentName? getPrimaryProvider();
+ method public android.content.ComponentName? getSecondaryProvider();
+ method public int getSystemProviderFallback();
+ method public boolean isEmpty();
+ property public final android.content.ComponentName? primaryProvider;
+ property public final android.content.ComponentName? secondaryProvider;
+ property public final int systemProviderFallback;
+ field public static final androidx.wear.complications.DefaultComplicationProviderPolicy.Companion Companion;
+ }
+
+ public static final class DefaultComplicationProviderPolicy.Companion {
+ }
+
public class ProviderInfoRetriever implements java.lang.AutoCloseable {
ctor public ProviderInfoRetriever(android.content.Context);
method public void close();
diff --git a/wear/wear-complications-data/api/public_plus_experimental_current.txt b/wear/wear-complications-data/api/public_plus_experimental_current.txt
index c70d6cd..b709b10 100644
--- a/wear/wear-complications-data/api/public_plus_experimental_current.txt
+++ b/wear/wear-complications-data/api/public_plus_experimental_current.txt
@@ -165,6 +165,24 @@
method public void onUpdateComplication(android.support.wearable.complications.ComplicationData?) throws android.os.RemoteException;
}
+ public final class DefaultComplicationProviderPolicy {
+ ctor public DefaultComplicationProviderPolicy();
+ ctor public DefaultComplicationProviderPolicy(int systemProvider);
+ ctor public DefaultComplicationProviderPolicy(android.content.ComponentName provider, int systemProviderFallback);
+ ctor public DefaultComplicationProviderPolicy(android.content.ComponentName primaryProvider, android.content.ComponentName secondaryProvider, int systemProviderFallback);
+ method public android.content.ComponentName? getPrimaryProvider();
+ method public android.content.ComponentName? getSecondaryProvider();
+ method public int getSystemProviderFallback();
+ method public boolean isEmpty();
+ property public final android.content.ComponentName? primaryProvider;
+ property public final android.content.ComponentName? secondaryProvider;
+ property public final int systemProviderFallback;
+ field public static final androidx.wear.complications.DefaultComplicationProviderPolicy.Companion Companion;
+ }
+
+ public static final class DefaultComplicationProviderPolicy.Companion {
+ }
+
public class ProviderInfoRetriever implements java.lang.AutoCloseable {
ctor public ProviderInfoRetriever(android.content.Context);
method public void close();
diff --git a/wear/wear-complications-data/api/restricted_current.txt b/wear/wear-complications-data/api/restricted_current.txt
index 5f98a6f..e2c72a8 100644
--- a/wear/wear-complications-data/api/restricted_current.txt
+++ b/wear/wear-complications-data/api/restricted_current.txt
@@ -182,6 +182,30 @@
method public void onUpdateComplication(android.support.wearable.complications.ComplicationData?) throws android.os.RemoteException;
}
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @VisibleForTesting public static interface ComplicationProviderService.RetailModeProvider {
+ method public boolean inRetailMode();
+ }
+
+ public final class DefaultComplicationProviderPolicy {
+ ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public DefaultComplicationProviderPolicy(java.util.List<android.content.ComponentName> providers, int systemProviderFallback);
+ ctor public DefaultComplicationProviderPolicy();
+ ctor public DefaultComplicationProviderPolicy(int systemProvider);
+ ctor public DefaultComplicationProviderPolicy(android.content.ComponentName provider, int systemProviderFallback);
+ ctor public DefaultComplicationProviderPolicy(android.content.ComponentName primaryProvider, android.content.ComponentName secondaryProvider, int systemProviderFallback);
+ method public android.content.ComponentName? getPrimaryProvider();
+ method public android.content.ComponentName? getSecondaryProvider();
+ method public int getSystemProviderFallback();
+ method public boolean isEmpty();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public java.util.ArrayList<android.content.ComponentName> providersAsList();
+ property public final android.content.ComponentName? primaryProvider;
+ property public final android.content.ComponentName? secondaryProvider;
+ property public final int systemProviderFallback;
+ field public static final androidx.wear.complications.DefaultComplicationProviderPolicy.Companion Companion;
+ }
+
+ public static final class DefaultComplicationProviderPolicy.Companion {
+ }
+
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public class ProviderChooserIntent {
method public static android.content.Intent createProviderChooserIntent(android.content.ComponentName, int, @android.support.wearable.complications.ComplicationData.ComplicationType int...);
method public static void startProviderChooserActivity(android.content.Context, android.content.ComponentName, int, @android.support.wearable.complications.ComplicationData.ComplicationType int...);
diff --git a/wear/wear-complications-data/src/main/java/android/support/wearable/complications/ComplicationText.java b/wear/wear-complications-data/src/main/java/android/support/wearable/complications/ComplicationText.java
index 05e4d85..61f4fbb 100644
--- a/wear/wear-complications-data/src/main/java/android/support/wearable/complications/ComplicationText.java
+++ b/wear/wear-complications-data/src/main/java/android/support/wearable/complications/ComplicationText.java
@@ -417,10 +417,10 @@
* time.
*
* <p>If the text contains spans, some of them may not be rendered by
- * {@link androidx.wear.complications.rendering.ComplicationDrawable}. Supported spans are
- * {@link ForegroundColorSpan}, {@link LocaleSpan}, {@link SubscriptSpan},
- * {@link SuperscriptSpan}, {@link StyleSpan}, {@link StrikethroughSpan},
- * {@link TypefaceSpan} and {@link UnderlineSpan}.
+ * {@link androidx.wear.watchface.complications.rendering.ComplicationDrawable}. Supported spans
+ * are {@link ForegroundColorSpan}, {@link LocaleSpan}, {@link SubscriptSpan}, {@link
+ * SuperscriptSpan}, {@link StyleSpan}, {@link StrikethroughSpan}, {@link TypefaceSpan} and
+ * {@link UnderlineSpan}.
*
* @param text the text to be displayed
*/
@@ -535,11 +535,11 @@
*
* <p>To use the {@code ^} character within the text, escape it as {@code ^^}.
*
- * <p>If the text contains spans, some of them may not be rendered by
- * {@link androidx.wear.complications.rendering.ComplicationDrawable}. Supported spans
- * are {@link ForegroundColorSpan}, {@link LocaleSpan}, {@link SubscriptSpan},
- * {@link SuperscriptSpan}, {@link StyleSpan}, {@link StrikethroughSpan},
- * {@link TypefaceSpan} and {@link UnderlineSpan}.
+ * <p>If the text contains spans, some of them may not be rendered by {@link
+ * androidx.wear.watchface.complications.rendering.ComplicationDrawable}. Supported spans
+ * are {@link ForegroundColorSpan}, {@link LocaleSpan}, {@link SubscriptSpan}, {@link
+ * SuperscriptSpan}, {@link StyleSpan}, {@link StrikethroughSpan}, {@link TypefaceSpan} and
+ * {@link UnderlineSpan}.
*
* @param surroundingText text within which the time difference value will be displayed,
* with {@code ^1} in place of the time difference.
@@ -657,10 +657,10 @@
* <p>To use the {@code ^} character within the text, escape it as {@code ^^}.
*
* <p>If the text contains spans, some of them may not be rendered by
- * {@link androidx.wear.complications.rendering.ComplicationDrawable}. Supported spans are
- * {@link ForegroundColorSpan}, {@link LocaleSpan}, {@link SubscriptSpan},
- * {@link SuperscriptSpan}, {@link StyleSpan}, {@link StrikethroughSpan},
- * {@link TypefaceSpan} and {@link UnderlineSpan}.
+ * {@link androidx.wear.watchface.complications.rendering.ComplicationDrawable}. Supported
+ * spans are {@link ForegroundColorSpan}, {@link LocaleSpan}, {@link SubscriptSpan}, {@link
+ * SuperscriptSpan}, {@link StyleSpan}, {@link StrikethroughSpan}, {@link TypefaceSpan} and
+ * {@link UnderlineSpan}.
*
* @param surroundingText string within which the time difference value will be displayed,
* with {@code ^1} in place of the time difference.
diff --git a/wear/wear-complications-data/src/main/java/androidx/wear/complications/ComplicationProviderService.java b/wear/wear-complications-data/src/main/java/androidx/wear/complications/ComplicationProviderService.java
index e738810..d4b9936 100644
--- a/wear/wear-complications-data/src/main/java/androidx/wear/complications/ComplicationProviderService.java
+++ b/wear/wear-complications-data/src/main/java/androidx/wear/complications/ComplicationProviderService.java
@@ -272,7 +272,8 @@
/** @hide */
@RestrictTo(LIBRARY_GROUP)
- interface RetailModeProvider {
+ @VisibleForTesting
+ public interface RetailModeProvider {
/**
* Returns true if the device is currently running in retail mode (e.g. the watch is being
* demonstrated in a store, or the watch face is being configured by the system UI).
diff --git a/wear/wear-complications-data/src/main/java/androidx/wear/complications/DefaultComplicationProviderPolicy.kt b/wear/wear-complications-data/src/main/java/androidx/wear/complications/DefaultComplicationProviderPolicy.kt
new file mode 100644
index 0000000..f240d61
--- /dev/null
+++ b/wear/wear-complications-data/src/main/java/androidx/wear/complications/DefaultComplicationProviderPolicy.kt
@@ -0,0 +1,108 @@
+/*
+ * 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.wear.complications
+
+import android.content.ComponentName
+import androidx.annotation.RestrictTo
+import java.util.ArrayList
+
+/**
+ * A watch face may wish to try and set one or more non-system providers as the default provider
+ * for a complication. If a provider can't be used for some reason (e.g. it isn't installed or it
+ * doesn't support the requested type, or the watch face lacks the necessary permission) then the
+ * next one will be tried. A system provider acts as a final fallback in case no non-system
+ * providers can be used.
+ *
+ * If the DefaultComplicationProviderPolicy is empty then no default is set.
+ */
+class DefaultComplicationProviderPolicy {
+ /** List of up to two non-system providers to be tried in turn. This may be empty. */
+ val primaryProvider: ComponentName?
+
+ val secondaryProvider: ComponentName?
+
+ /** Fallback in case none of the non-system providers could be used. */
+ @SystemProviders.ProviderId
+ val systemProviderFallback: Int
+
+ /** @hide */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ constructor(
+ providers: List<ComponentName>,
+ systemProviderFallback: Int
+ ) {
+ this.primaryProvider = if (providers.isNotEmpty()) providers[0] else null
+ this.secondaryProvider = if (providers.size >= 2) providers[1] else null
+ this.systemProviderFallback = systemProviderFallback
+ }
+
+ /** No default complication provider. */
+ constructor() {
+ primaryProvider = null
+ secondaryProvider = null
+ systemProviderFallback = NO_DEFAULT_PROVIDER
+ }
+
+ /**
+ * Uses systemProvider as the default complication provider.
+ */
+ constructor(systemProvider: Int) {
+ primaryProvider = null
+ secondaryProvider = null
+ systemProviderFallback = systemProvider
+ }
+
+ /**
+ * Attempts to use provider as the default complication provider, if not present then
+ * systemProviderFallback will be used instead.
+ */
+ constructor(provider: ComponentName, systemProviderFallback: Int) {
+ primaryProvider = provider
+ secondaryProvider = null
+ this.systemProviderFallback = systemProviderFallback
+ }
+
+ /**
+ * Attempts to use primaryProvider as the default complication provider, if not present then
+ * secondaryProvider will be tried and if that's not present then systemProviderFallback
+ * will be used instead.
+ */
+ constructor(
+ primaryProvider: ComponentName,
+ secondaryProvider: ComponentName,
+ systemProviderFallback: Int
+ ) {
+ this.primaryProvider = primaryProvider
+ this.secondaryProvider = secondaryProvider
+ this.systemProviderFallback = systemProviderFallback
+ }
+
+ /** Whether or not this DefaultComplicationProviderPolicy contains a default provider. */
+ fun isEmpty() =
+ primaryProvider == null && systemProviderFallback == NO_DEFAULT_PROVIDER
+
+ /** @hide */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ fun providersAsList() = ArrayList<ComponentName>().apply {
+ primaryProvider?.let { add(it) }
+ secondaryProvider?.let { add(it) }
+ }
+
+ companion object {
+ internal const val NO_DEFAULT_PROVIDER = SystemProviders.NO_PROVIDER
+ }
+}
\ No newline at end of file
diff --git a/wear/wear-complications-rendering/api/public_plus_experimental_current.txt b/wear/wear-complications-rendering/api/public_plus_experimental_current.txt
deleted file mode 100644
index 7b73622..0000000
--- a/wear/wear-complications-rendering/api/public_plus_experimental_current.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-// Signature format: 4.0
-package androidx.wear.complications.rendering {
-
- public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
- ctor public ComplicationDrawable();
- ctor public ComplicationDrawable(android.content.Context);
- ctor public ComplicationDrawable(androidx.wear.complications.rendering.ComplicationDrawable);
- method public void draw(android.graphics.Canvas);
- method public androidx.wear.complications.rendering.ComplicationStyle getActiveStyle();
- method public androidx.wear.complications.rendering.ComplicationStyle getAmbientStyle();
- method public android.support.wearable.complications.ComplicationData? getComplicationData();
- method public android.content.Context? getContext();
- method public long getCurrentTimeMillis();
- method public static androidx.wear.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
- method public long getHighlightDuration();
- method public boolean getHighlighted();
- method public boolean getInAmbientMode();
- method public boolean getLowBitAmbient();
- method @Deprecated public int getOpacity();
- method public boolean isBurnInProtectionOn();
- method public boolean isRangedValueProgressHidden();
- method public boolean onTap(int, int);
- method public void setAlpha(int);
- method public void setBurnInProtection(boolean);
- method public void setColorFilter(android.graphics.ColorFilter?);
- method public void setComplicationData(android.support.wearable.complications.ComplicationData?);
- method public void setContext(android.content.Context);
- method public void setCurrentTimeMillis(long);
- method public void setHighlightDuration(long);
- method public void setHighlighted(boolean);
- method public void setInAmbientMode(boolean);
- method public void setLowBitAmbient(boolean);
- method public void setNoDataText(CharSequence?);
- method public void setRangedValueProgressHidden(boolean);
- field public static final int BORDER_STYLE_DASHED = 2; // 0x2
- field public static final int BORDER_STYLE_NONE = 0; // 0x0
- field public static final int BORDER_STYLE_SOLID = 1; // 0x1
- }
-
- @IntDef({androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_SOLID, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ComplicationDrawable.BorderStyle {
- }
-
- public class ComplicationStyle {
- ctor public ComplicationStyle();
- ctor public ComplicationStyle(androidx.wear.complications.rendering.ComplicationStyle);
- method public int getBackgroundColor();
- method public android.graphics.drawable.Drawable? getBackgroundDrawable();
- method public int getBorderColor();
- method public int getBorderDashGap();
- method public int getBorderDashWidth();
- method public int getBorderRadius();
- method @androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle public int getBorderStyle();
- method public int getBorderWidth();
- method public int getHighlightColor();
- method public int getIconColor();
- method public android.graphics.ColorFilter? getImageColorFilter();
- method public int getRangedValuePrimaryColor();
- method public int getRangedValueRingWidth();
- method public int getRangedValueSecondaryColor();
- method public int getTextColor();
- method public int getTextSize();
- method public android.graphics.Typeface? getTextTypeface();
- method public int getTitleColor();
- method public int getTitleSize();
- method public android.graphics.Typeface? getTitleTypeface();
- method public void setBackgroundColor(int);
- method public void setBackgroundDrawable(android.graphics.drawable.Drawable?);
- method public void setBorderColor(int);
- method public void setBorderDashGap(int);
- method public void setBorderDashWidth(int);
- method public void setBorderRadius(int);
- method public void setBorderStyle(@androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle int);
- method public void setBorderWidth(int);
- method public void setHighlightColor(int);
- method public void setIconColor(int);
- method public void setImageColorFilter(android.graphics.ColorFilter?);
- method public void setRangedValuePrimaryColor(int);
- method public void setRangedValueRingWidth(int);
- method public void setRangedValueSecondaryColor(int);
- method public void setTextColor(int);
- method public void setTextSize(int);
- method public void setTextTypeface(android.graphics.Typeface);
- method public void setTitleColor(int);
- method public void setTitleSize(int);
- method public void setTitleTypeface(android.graphics.Typeface);
- field public static final int BORDER_RADIUS_DEFAULT = 2147483647; // 0x7fffffff
- }
-
-}
-
diff --git a/wear/wear-complications-rendering/api/restricted_current.txt b/wear/wear-complications-rendering/api/restricted_current.txt
deleted file mode 100644
index 7b73622..0000000
--- a/wear/wear-complications-rendering/api/restricted_current.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-// Signature format: 4.0
-package androidx.wear.complications.rendering {
-
- public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
- ctor public ComplicationDrawable();
- ctor public ComplicationDrawable(android.content.Context);
- ctor public ComplicationDrawable(androidx.wear.complications.rendering.ComplicationDrawable);
- method public void draw(android.graphics.Canvas);
- method public androidx.wear.complications.rendering.ComplicationStyle getActiveStyle();
- method public androidx.wear.complications.rendering.ComplicationStyle getAmbientStyle();
- method public android.support.wearable.complications.ComplicationData? getComplicationData();
- method public android.content.Context? getContext();
- method public long getCurrentTimeMillis();
- method public static androidx.wear.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
- method public long getHighlightDuration();
- method public boolean getHighlighted();
- method public boolean getInAmbientMode();
- method public boolean getLowBitAmbient();
- method @Deprecated public int getOpacity();
- method public boolean isBurnInProtectionOn();
- method public boolean isRangedValueProgressHidden();
- method public boolean onTap(int, int);
- method public void setAlpha(int);
- method public void setBurnInProtection(boolean);
- method public void setColorFilter(android.graphics.ColorFilter?);
- method public void setComplicationData(android.support.wearable.complications.ComplicationData?);
- method public void setContext(android.content.Context);
- method public void setCurrentTimeMillis(long);
- method public void setHighlightDuration(long);
- method public void setHighlighted(boolean);
- method public void setInAmbientMode(boolean);
- method public void setLowBitAmbient(boolean);
- method public void setNoDataText(CharSequence?);
- method public void setRangedValueProgressHidden(boolean);
- field public static final int BORDER_STYLE_DASHED = 2; // 0x2
- field public static final int BORDER_STYLE_NONE = 0; // 0x0
- field public static final int BORDER_STYLE_SOLID = 1; // 0x1
- }
-
- @IntDef({androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_SOLID, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ComplicationDrawable.BorderStyle {
- }
-
- public class ComplicationStyle {
- ctor public ComplicationStyle();
- ctor public ComplicationStyle(androidx.wear.complications.rendering.ComplicationStyle);
- method public int getBackgroundColor();
- method public android.graphics.drawable.Drawable? getBackgroundDrawable();
- method public int getBorderColor();
- method public int getBorderDashGap();
- method public int getBorderDashWidth();
- method public int getBorderRadius();
- method @androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle public int getBorderStyle();
- method public int getBorderWidth();
- method public int getHighlightColor();
- method public int getIconColor();
- method public android.graphics.ColorFilter? getImageColorFilter();
- method public int getRangedValuePrimaryColor();
- method public int getRangedValueRingWidth();
- method public int getRangedValueSecondaryColor();
- method public int getTextColor();
- method public int getTextSize();
- method public android.graphics.Typeface? getTextTypeface();
- method public int getTitleColor();
- method public int getTitleSize();
- method public android.graphics.Typeface? getTitleTypeface();
- method public void setBackgroundColor(int);
- method public void setBackgroundDrawable(android.graphics.drawable.Drawable?);
- method public void setBorderColor(int);
- method public void setBorderDashGap(int);
- method public void setBorderDashWidth(int);
- method public void setBorderRadius(int);
- method public void setBorderStyle(@androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle int);
- method public void setBorderWidth(int);
- method public void setHighlightColor(int);
- method public void setIconColor(int);
- method public void setImageColorFilter(android.graphics.ColorFilter?);
- method public void setRangedValuePrimaryColor(int);
- method public void setRangedValueRingWidth(int);
- method public void setRangedValueSecondaryColor(int);
- method public void setTextColor(int);
- method public void setTextSize(int);
- method public void setTextTypeface(android.graphics.Typeface);
- method public void setTitleColor(int);
- method public void setTitleSize(int);
- method public void setTitleTypeface(android.graphics.Typeface);
- field public static final int BORDER_RADIUS_DEFAULT = 2147483647; // 0x7fffffff
- }
-
-}
-
diff --git a/wear/wear-complications-rendering/src/main/AndroidManifest.xml b/wear/wear-complications-rendering/src/main/AndroidManifest.xml
deleted file mode 100644
index 6aef0f3..0000000
--- a/wear/wear-complications-rendering/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="androidx.wear.complications.rendering">
-</manifest>
diff --git a/wear/wear-input-testing/api/1.0.0-beta01.txt b/wear/wear-input-testing/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..154d309
--- /dev/null
+++ b/wear/wear-input-testing/api/1.0.0-beta01.txt
@@ -0,0 +1,18 @@
+// Signature format: 4.0
+package androidx.wear.input.testing {
+
+ public class TestWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+ ctor public TestWearableButtonsProvider(java.util.Map<java.lang.Integer!,androidx.wear.input.testing.TestWearableButtonsProvider.TestWearableButtonLocation!>);
+ method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+ method public android.os.Bundle getButtonInfo(android.content.Context, int);
+ }
+
+ public static class TestWearableButtonsProvider.TestWearableButtonLocation {
+ ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float);
+ ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float, float, float);
+ method public android.graphics.PointF getLocation();
+ method public android.graphics.PointF? getRotatedLocation();
+ }
+
+}
+
diff --git a/wear/wear-input-testing/api/public_plus_experimental_1.0.0-beta01.txt b/wear/wear-input-testing/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..154d309
--- /dev/null
+++ b/wear/wear-input-testing/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1,18 @@
+// Signature format: 4.0
+package androidx.wear.input.testing {
+
+ public class TestWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+ ctor public TestWearableButtonsProvider(java.util.Map<java.lang.Integer!,androidx.wear.input.testing.TestWearableButtonsProvider.TestWearableButtonLocation!>);
+ method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+ method public android.os.Bundle getButtonInfo(android.content.Context, int);
+ }
+
+ public static class TestWearableButtonsProvider.TestWearableButtonLocation {
+ ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float);
+ ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float, float, float);
+ method public android.graphics.PointF getLocation();
+ method public android.graphics.PointF? getRotatedLocation();
+ }
+
+}
+
diff --git a/wear/wear-complications-rendering/api/res-current.txt b/wear/wear-input-testing/api/res-1.0.0-beta01.txt
similarity index 100%
copy from wear/wear-complications-rendering/api/res-current.txt
copy to wear/wear-input-testing/api/res-1.0.0-beta01.txt
diff --git a/wear/wear-input-testing/api/restricted_1.0.0-beta01.txt b/wear/wear-input-testing/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..154d309
--- /dev/null
+++ b/wear/wear-input-testing/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1,18 @@
+// Signature format: 4.0
+package androidx.wear.input.testing {
+
+ public class TestWearableButtonsProvider implements androidx.wear.input.WearableButtonsProvider {
+ ctor public TestWearableButtonsProvider(java.util.Map<java.lang.Integer!,androidx.wear.input.testing.TestWearableButtonsProvider.TestWearableButtonLocation!>);
+ method public int[]? getAvailableButtonKeyCodes(android.content.Context);
+ method public android.os.Bundle getButtonInfo(android.content.Context, int);
+ }
+
+ public static class TestWearableButtonsProvider.TestWearableButtonLocation {
+ ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float);
+ ctor public TestWearableButtonsProvider.TestWearableButtonLocation(float, float, float, float);
+ method public android.graphics.PointF getLocation();
+ method public android.graphics.PointF? getRotatedLocation();
+ }
+
+}
+
diff --git a/wear/wear-input-testing/build.gradle b/wear/wear-input-testing/build.gradle
index 5f5e801..ffbd290 100644
--- a/wear/wear-input-testing/build.gradle
+++ b/wear/wear-input-testing/build.gradle
@@ -24,7 +24,7 @@
}
dependencies {
- api("androidx.wear:wear-input:1.0.0-alpha01")
+ api(project(":wear:wear-input"))
compileOnly fileTree(dir: '../wear_stubs', include: ['com.google.android.wearable-stubs.jar'])
}
@@ -38,7 +38,7 @@
name = "Android Wear Support Input Testing Helpers"
publish = Publish.SNAPSHOT_AND_RELEASE
mavenGroup = LibraryGroups.WEAR
- mavenVersion = LibraryVersions.WEAR_INPUT_TESTING
+ mavenVersion = LibraryVersions.WEAR_INPUT
inceptionYear = "2020"
description = "Android Wear Support Input Testing Helpers"
}
diff --git a/wear/wear-complications-rendering/api/current.txt b/wear/wear-watchface-complications-rendering/api/current.txt
similarity index 74%
rename from wear/wear-complications-rendering/api/current.txt
rename to wear/wear-watchface-complications-rendering/api/current.txt
index 7b73622..7f565a5 100644
--- a/wear/wear-complications-rendering/api/current.txt
+++ b/wear/wear-watchface-complications-rendering/api/current.txt
@@ -1,17 +1,17 @@
// Signature format: 4.0
-package androidx.wear.complications.rendering {
+package androidx.wear.watchface.complications.rendering {
public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
ctor public ComplicationDrawable();
ctor public ComplicationDrawable(android.content.Context);
- ctor public ComplicationDrawable(androidx.wear.complications.rendering.ComplicationDrawable);
+ ctor public ComplicationDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable);
method public void draw(android.graphics.Canvas);
- method public androidx.wear.complications.rendering.ComplicationStyle getActiveStyle();
- method public androidx.wear.complications.rendering.ComplicationStyle getAmbientStyle();
+ method public androidx.wear.watchface.complications.rendering.ComplicationStyle getActiveStyle();
+ method public androidx.wear.watchface.complications.rendering.ComplicationStyle getAmbientStyle();
method public android.support.wearable.complications.ComplicationData? getComplicationData();
method public android.content.Context? getContext();
method public long getCurrentTimeMillis();
- method public static androidx.wear.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
+ method public static androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
method public long getHighlightDuration();
method public boolean getHighlighted();
method public boolean getInAmbientMode();
@@ -37,19 +37,19 @@
field public static final int BORDER_STYLE_SOLID = 1; // 0x1
}
- @IntDef({androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_SOLID, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ComplicationDrawable.BorderStyle {
+ @IntDef({androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE, androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_SOLID, androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ComplicationDrawable.BorderStyle {
}
public class ComplicationStyle {
ctor public ComplicationStyle();
- ctor public ComplicationStyle(androidx.wear.complications.rendering.ComplicationStyle);
+ ctor public ComplicationStyle(androidx.wear.watchface.complications.rendering.ComplicationStyle);
method public int getBackgroundColor();
method public android.graphics.drawable.Drawable? getBackgroundDrawable();
method public int getBorderColor();
method public int getBorderDashGap();
method public int getBorderDashWidth();
method public int getBorderRadius();
- method @androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle public int getBorderStyle();
+ method @androidx.wear.watchface.complications.rendering.ComplicationDrawable.BorderStyle public int getBorderStyle();
method public int getBorderWidth();
method public int getHighlightColor();
method public int getIconColor();
@@ -69,7 +69,7 @@
method public void setBorderDashGap(int);
method public void setBorderDashWidth(int);
method public void setBorderRadius(int);
- method public void setBorderStyle(@androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle int);
+ method public void setBorderStyle(@androidx.wear.watchface.complications.rendering.ComplicationDrawable.BorderStyle int);
method public void setBorderWidth(int);
method public void setHighlightColor(int);
method public void setIconColor(int);
diff --git a/wear/wear-complications-rendering/api/current.txt b/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt
similarity index 74%
copy from wear/wear-complications-rendering/api/current.txt
copy to wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt
index 7b73622..7f565a5 100644
--- a/wear/wear-complications-rendering/api/current.txt
+++ b/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt
@@ -1,17 +1,17 @@
// Signature format: 4.0
-package androidx.wear.complications.rendering {
+package androidx.wear.watchface.complications.rendering {
public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
ctor public ComplicationDrawable();
ctor public ComplicationDrawable(android.content.Context);
- ctor public ComplicationDrawable(androidx.wear.complications.rendering.ComplicationDrawable);
+ ctor public ComplicationDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable);
method public void draw(android.graphics.Canvas);
- method public androidx.wear.complications.rendering.ComplicationStyle getActiveStyle();
- method public androidx.wear.complications.rendering.ComplicationStyle getAmbientStyle();
+ method public androidx.wear.watchface.complications.rendering.ComplicationStyle getActiveStyle();
+ method public androidx.wear.watchface.complications.rendering.ComplicationStyle getAmbientStyle();
method public android.support.wearable.complications.ComplicationData? getComplicationData();
method public android.content.Context? getContext();
method public long getCurrentTimeMillis();
- method public static androidx.wear.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
+ method public static androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
method public long getHighlightDuration();
method public boolean getHighlighted();
method public boolean getInAmbientMode();
@@ -37,19 +37,19 @@
field public static final int BORDER_STYLE_SOLID = 1; // 0x1
}
- @IntDef({androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_SOLID, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ComplicationDrawable.BorderStyle {
+ @IntDef({androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE, androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_SOLID, androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ComplicationDrawable.BorderStyle {
}
public class ComplicationStyle {
ctor public ComplicationStyle();
- ctor public ComplicationStyle(androidx.wear.complications.rendering.ComplicationStyle);
+ ctor public ComplicationStyle(androidx.wear.watchface.complications.rendering.ComplicationStyle);
method public int getBackgroundColor();
method public android.graphics.drawable.Drawable? getBackgroundDrawable();
method public int getBorderColor();
method public int getBorderDashGap();
method public int getBorderDashWidth();
method public int getBorderRadius();
- method @androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle public int getBorderStyle();
+ method @androidx.wear.watchface.complications.rendering.ComplicationDrawable.BorderStyle public int getBorderStyle();
method public int getBorderWidth();
method public int getHighlightColor();
method public int getIconColor();
@@ -69,7 +69,7 @@
method public void setBorderDashGap(int);
method public void setBorderDashWidth(int);
method public void setBorderRadius(int);
- method public void setBorderStyle(@androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle int);
+ method public void setBorderStyle(@androidx.wear.watchface.complications.rendering.ComplicationDrawable.BorderStyle int);
method public void setBorderWidth(int);
method public void setHighlightColor(int);
method public void setIconColor(int);
diff --git a/wear/wear-complications-rendering/api/res-current.txt b/wear/wear-watchface-complications-rendering/api/res-current.txt
similarity index 100%
rename from wear/wear-complications-rendering/api/res-current.txt
rename to wear/wear-watchface-complications-rendering/api/res-current.txt
diff --git a/wear/wear-complications-rendering/api/current.txt b/wear/wear-watchface-complications-rendering/api/restricted_current.txt
similarity index 74%
copy from wear/wear-complications-rendering/api/current.txt
copy to wear/wear-watchface-complications-rendering/api/restricted_current.txt
index 7b73622..7f565a5 100644
--- a/wear/wear-complications-rendering/api/current.txt
+++ b/wear/wear-watchface-complications-rendering/api/restricted_current.txt
@@ -1,17 +1,17 @@
// Signature format: 4.0
-package androidx.wear.complications.rendering {
+package androidx.wear.watchface.complications.rendering {
public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
ctor public ComplicationDrawable();
ctor public ComplicationDrawable(android.content.Context);
- ctor public ComplicationDrawable(androidx.wear.complications.rendering.ComplicationDrawable);
+ ctor public ComplicationDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable);
method public void draw(android.graphics.Canvas);
- method public androidx.wear.complications.rendering.ComplicationStyle getActiveStyle();
- method public androidx.wear.complications.rendering.ComplicationStyle getAmbientStyle();
+ method public androidx.wear.watchface.complications.rendering.ComplicationStyle getActiveStyle();
+ method public androidx.wear.watchface.complications.rendering.ComplicationStyle getAmbientStyle();
method public android.support.wearable.complications.ComplicationData? getComplicationData();
method public android.content.Context? getContext();
method public long getCurrentTimeMillis();
- method public static androidx.wear.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
+ method public static androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
method public long getHighlightDuration();
method public boolean getHighlighted();
method public boolean getInAmbientMode();
@@ -37,19 +37,19 @@
field public static final int BORDER_STYLE_SOLID = 1; // 0x1
}
- @IntDef({androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_SOLID, androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ComplicationDrawable.BorderStyle {
+ @IntDef({androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE, androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_SOLID, androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ComplicationDrawable.BorderStyle {
}
public class ComplicationStyle {
ctor public ComplicationStyle();
- ctor public ComplicationStyle(androidx.wear.complications.rendering.ComplicationStyle);
+ ctor public ComplicationStyle(androidx.wear.watchface.complications.rendering.ComplicationStyle);
method public int getBackgroundColor();
method public android.graphics.drawable.Drawable? getBackgroundDrawable();
method public int getBorderColor();
method public int getBorderDashGap();
method public int getBorderDashWidth();
method public int getBorderRadius();
- method @androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle public int getBorderStyle();
+ method @androidx.wear.watchface.complications.rendering.ComplicationDrawable.BorderStyle public int getBorderStyle();
method public int getBorderWidth();
method public int getHighlightColor();
method public int getIconColor();
@@ -69,7 +69,7 @@
method public void setBorderDashGap(int);
method public void setBorderDashWidth(int);
method public void setBorderRadius(int);
- method public void setBorderStyle(@androidx.wear.complications.rendering.ComplicationDrawable.BorderStyle int);
+ method public void setBorderStyle(@androidx.wear.watchface.complications.rendering.ComplicationDrawable.BorderStyle int);
method public void setBorderWidth(int);
method public void setHighlightColor(int);
method public void setIconColor(int);
diff --git a/wear/wear-complications-rendering/build.gradle b/wear/wear-watchface-complications-rendering/build.gradle
similarity index 91%
rename from wear/wear-complications-rendering/build.gradle
rename to wear/wear-watchface-complications-rendering/build.gradle
index bfe5088..6ec0cce 100644
--- a/wear/wear-complications-rendering/build.gradle
+++ b/wear/wear-watchface-complications-rendering/build.gradle
@@ -62,10 +62,10 @@
}
androidx {
- name = "Android Wear Complications"
+ name = "Android Wear Watchface Complication Rendering"
publish = Publish.SNAPSHOT_AND_RELEASE
mavenGroup = LibraryGroups.WEAR
- mavenVersion = LibraryVersions.WEAR_COMPLICATIONS
+ mavenVersion = LibraryVersions.WEAR_WATCHFACE
inceptionYear = "2020"
- description = "Android Wear Complications"
-}
\ No newline at end of file
+ description = "Support for rendering complications on the watch face"
+}
diff --git a/wear/wear-complications-rendering/src/androidTest/AndroidManifest.xml b/wear/wear-watchface-complications-rendering/src/androidTest/AndroidManifest.xml
similarity index 91%
copy from wear/wear-complications-rendering/src/androidTest/AndroidManifest.xml
copy to wear/wear-watchface-complications-rendering/src/androidTest/AndroidManifest.xml
index 0715f74..b1c90c1 100644
--- a/wear/wear-complications-rendering/src/androidTest/AndroidManifest.xml
+++ b/wear/wear-watchface-complications-rendering/src/androidTest/AndroidManifest.xml
@@ -15,5 +15,5 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="androidx.wear.complications">
+ package="androidx.wear.watchface.complications.rendering">
</manifest>
diff --git a/wear/wear-complications-rendering/src/androidTest/java/androidx/wear/complications/rendering/test/ComplicationDrawableAndroidTest.java b/wear/wear-watchface-complications-rendering/src/androidTest/java/androidx/wear/watchface/complications/rendering/test/ComplicationDrawableAndroidTest.java
similarity index 90%
rename from wear/wear-complications-rendering/src/androidTest/java/androidx/wear/complications/rendering/test/ComplicationDrawableAndroidTest.java
rename to wear/wear-watchface-complications-rendering/src/androidTest/java/androidx/wear/watchface/complications/rendering/test/ComplicationDrawableAndroidTest.java
index 9f7d308..8ef7443 100644
--- a/wear/wear-complications-rendering/src/androidTest/java/androidx/wear/complications/rendering/test/ComplicationDrawableAndroidTest.java
+++ b/wear/wear-watchface-complications-rendering/src/androidTest/java/androidx/wear/watchface/complications/rendering/test/ComplicationDrawableAndroidTest.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering.test;
+package androidx.wear.watchface.complications.rendering.test;
import static com.google.common.truth.Truth.assertThat;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.wear.complications.rendering.ComplicationDrawable;
+import androidx.wear.watchface.complications.rendering.ComplicationDrawable;
import org.junit.Before;
import org.junit.Test;
@@ -34,7 +34,7 @@
@Before
public void setUp() {
- int textSize = androidx.wear.complications.rendering.R.dimen.complicationDrawable_textSize;
+ int textSize = R.dimen.complicationDrawable_textSize;
mDefaultTextSize =
ApplicationProvider.getApplicationContext()
.getResources()
diff --git a/wear/wear-complications-rendering/src/androidTest/res/drawable/default_complication_drawable.xml b/wear/wear-watchface-complications-rendering/src/androidTest/res/drawable/default_complication_drawable.xml
similarity index 90%
rename from wear/wear-complications-rendering/src/androidTest/res/drawable/default_complication_drawable.xml
rename to wear/wear-watchface-complications-rendering/src/androidTest/res/drawable/default_complication_drawable.xml
index dbc3dd2..728dd45 100644
--- a/wear/wear-complications-rendering/src/androidTest/res/drawable/default_complication_drawable.xml
+++ b/wear/wear-watchface-complications-rendering/src/androidTest/res/drawable/default_complication_drawable.xml
@@ -14,4 +14,4 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<androidx.wear.complications.rendering.ComplicationDrawable/>
+<androidx.wear.watchface.complications.rendering.ComplicationDrawable/>
diff --git a/wear/wear-complications-rendering/src/androidTest/AndroidManifest.xml b/wear/wear-watchface-complications-rendering/src/main/AndroidManifest.xml
similarity index 91%
rename from wear/wear-complications-rendering/src/androidTest/AndroidManifest.xml
rename to wear/wear-watchface-complications-rendering/src/main/AndroidManifest.xml
index 0715f74..f55eb25 100644
--- a/wear/wear-complications-rendering/src/androidTest/AndroidManifest.xml
+++ b/wear/wear-watchface-complications-rendering/src/main/AndroidManifest.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="androidx.wear.complications">
+ package="androidx.wear.watchface.complications.rendering">
</manifest>
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/ComplicationDrawable.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationDrawable.java
similarity index 98%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/ComplicationDrawable.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationDrawable.java
index ae56fcd..9c9ad8d 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/ComplicationDrawable.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationDrawable.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import android.app.PendingIntent.CanceledException;
import android.content.ComponentName;
@@ -42,7 +42,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.wear.complications.ComplicationHelperActivity;
-import androidx.wear.complications.rendering.ComplicationRenderer.OnInvalidateListener;
+import androidx.wear.watchface.complications.rendering.ComplicationRenderer.OnInvalidateListener;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -229,7 +229,6 @@
private boolean mLowBitAmbient;
private boolean mBurnInProtection;
private boolean mHighlighted;
- private boolean mIsStyleUpToDate;
private boolean mRangedValueProgressHidden;
private boolean mIsInflatedFromXml;
@@ -262,7 +261,6 @@
mLowBitAmbient = drawable.mLowBitAmbient;
mBurnInProtection = drawable.mBurnInProtection;
mHighlighted = false;
- mIsStyleUpToDate = false;
mRangedValueProgressHidden = drawable.mRangedValueProgressHidden;
mIsInflatedFromXml = drawable.mIsInflatedFromXml;
mAlreadyStyled = true;
@@ -367,7 +365,6 @@
}
mComplicationRenderer.setRangedValueProgressHidden(mRangedValueProgressHidden);
mComplicationRenderer.setBounds(getBounds());
- mIsStyleUpToDate = true;
}
/**
@@ -551,7 +548,6 @@
"Unknown element: " + name + " for ComplicationDrawable " + this);
}
}
- mIsStyleUpToDate = false;
}
/**
@@ -827,10 +823,11 @@
}
/** Builds styles and syncs them with the complication renderer. */
- private void updateStyleIfRequired() {
- if (!mIsStyleUpToDate) {
+ void updateStyleIfRequired() {
+ if (mActiveStyle.isDirty() || mAmbientStyle.isDirty()) {
mComplicationRenderer.updateStyle(mActiveStyle, mAmbientStyle);
- mIsStyleUpToDate = true;
+ mActiveStyle.clearDirtyFlag();
+ mAmbientStyle.clearDirtyFlag();
}
}
@@ -870,4 +867,4 @@
public CharSequence getNoDataText() {
return mNoDataText;
}
-}
\ No newline at end of file
+}
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/ComplicationRenderer.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationRenderer.java
similarity index 97%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/ComplicationRenderer.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationRenderer.java
index fd6453c..961dc96 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/ComplicationRenderer.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationRenderer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -44,14 +44,14 @@
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
-import androidx.wear.complications.rendering.utils.IconLayoutHelper;
-import androidx.wear.complications.rendering.utils.LargeImageLayoutHelper;
-import androidx.wear.complications.rendering.utils.LayoutHelper;
-import androidx.wear.complications.rendering.utils.LayoutUtils;
-import androidx.wear.complications.rendering.utils.LongTextLayoutHelper;
-import androidx.wear.complications.rendering.utils.RangedValueLayoutHelper;
-import androidx.wear.complications.rendering.utils.ShortTextLayoutHelper;
-import androidx.wear.complications.rendering.utils.SmallImageLayoutHelper;
+import androidx.wear.watchface.complications.rendering.utils.IconLayoutHelper;
+import androidx.wear.watchface.complications.rendering.utils.LargeImageLayoutHelper;
+import androidx.wear.watchface.complications.rendering.utils.LayoutHelper;
+import androidx.wear.watchface.complications.rendering.utils.LayoutUtils;
+import androidx.wear.watchface.complications.rendering.utils.LongTextLayoutHelper;
+import androidx.wear.watchface.complications.rendering.utils.RangedValueLayoutHelper;
+import androidx.wear.watchface.complications.rendering.utils.ShortTextLayoutHelper;
+import androidx.wear.watchface.complications.rendering.utils.SmallImageLayoutHelper;
import java.util.Objects;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/ComplicationStyle.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationStyle.java
similarity index 90%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/ComplicationStyle.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationStyle.java
index baaf3a8..5a37aee 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/ComplicationStyle.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationStyle.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import android.graphics.Color;
import android.graphics.ColorFilter;
@@ -88,6 +88,7 @@
private int mRangedValuePrimaryColor = PRIMARY_COLOR_DEFAULT;
private int mRangedValueSecondaryColor = SECONDARY_COLOR_DEFAULT;
private int mHighlightColor = HIGHLIGHT_COLOR_DEFAULT;
+ private boolean mDirty = true;
public ComplicationStyle() {
}
@@ -115,6 +116,14 @@
mHighlightColor = style.getHighlightColor();
}
+ boolean isDirty() {
+ return mDirty;
+ }
+
+ void clearDirtyFlag() {
+ mDirty = false;
+ }
+
/** Returns the background color to be used. */
public int getBackgroundColor() {
return mBackgroundColor;
@@ -277,7 +286,8 @@
* @param colorFilter The {@link ColorFilter} to use
*/
public void setImageColorFilter(@Nullable ColorFilter colorFilter) {
- this.mImageColorFilter = colorFilter;
+ mImageColorFilter = colorFilter;
+ mDirty = true;
}
/**
@@ -286,7 +296,8 @@
* @param iconColor The color to render the icon with
*/
public void setIconColor(int iconColor) {
- this.mIconColor = iconColor;
+ mIconColor = iconColor;
+ mDirty = true;
}
/**
@@ -295,7 +306,8 @@
* @param textTypeface The {@link Typeface} to render the text with
*/
public void setTextTypeface(@NonNull Typeface textTypeface) {
- this.mTextTypeface = textTypeface;
+ mTextTypeface = textTypeface;
+ mDirty = true;
}
/**
@@ -304,7 +316,8 @@
* @param titleTypeface The {@link Typeface} to render the title with
*/
public void setTitleTypeface(@NonNull Typeface titleTypeface) {
- this.mTitleTypeface = titleTypeface;
+ mTitleTypeface = titleTypeface;
+ mDirty = true;
}
/**
@@ -313,7 +326,8 @@
* @param textSize The size of the text=
*/
public void setTextSize(int textSize) {
- this.mTextSize = textSize;
+ mTextSize = textSize;
+ mDirty = true;
}
/**
@@ -322,7 +336,8 @@
* @param titleSize The size of the title text=
*/
public void setTitleSize(int titleSize) {
- this.mTitleSize = titleSize;
+ mTitleSize = titleSize;
+ mDirty = true;
}
/**
@@ -331,7 +346,8 @@
* @param borderColor The color to render the complication border with
*/
public void setBorderColor(int borderColor) {
- this.mBorderColor = borderColor;
+ mBorderColor = borderColor;
+ mDirty = true;
}
/**
@@ -342,14 +358,15 @@
public void setBorderStyle(@ComplicationDrawable.BorderStyle int borderStyle) {
switch (borderStyle) {
case ComplicationDrawable.BORDER_STYLE_SOLID:
- this.mBorderStyle = ComplicationDrawable.BORDER_STYLE_SOLID;
+ mBorderStyle = ComplicationDrawable.BORDER_STYLE_SOLID;
break;
case ComplicationDrawable.BORDER_STYLE_DASHED:
- this.mBorderStyle = ComplicationDrawable.BORDER_STYLE_DASHED;
+ mBorderStyle = ComplicationDrawable.BORDER_STYLE_DASHED;
break;
default:
- this.mBorderStyle = ComplicationDrawable.BORDER_STYLE_NONE;
+ mBorderStyle = ComplicationDrawable.BORDER_STYLE_NONE;
}
+ mDirty = true;
}
/**
@@ -359,7 +376,8 @@
* @param borderDashWidth The dash widths to render the complication border with
*/
public void setBorderDashWidth(int borderDashWidth) {
- this.mBorderDashWidth = borderDashWidth;
+ mBorderDashWidth = borderDashWidth;
+ mDirty = true;
}
/**
@@ -369,7 +387,8 @@
* @param borderDashGap The dash gap render the complication border with
*/
public void setBorderDashGap(int borderDashGap) {
- this.mBorderDashGap = borderDashGap;
+ mBorderDashGap = borderDashGap;
+ mDirty = true;
}
/**
@@ -380,7 +399,8 @@
* @param borderRadius The radius to render the complication border with
*/
public void setBorderRadius(int borderRadius) {
- this.mBorderRadius = borderRadius;
+ mBorderRadius = borderRadius;
+ mDirty = true;
}
/**
@@ -389,7 +409,8 @@
* @param borderWidth The width to render the complication border with
*/
public void setBorderWidth(int borderWidth) {
- this.mBorderWidth = borderWidth;
+ mBorderWidth = borderWidth;
+ mDirty = true;
}
/**
@@ -398,7 +419,8 @@
* @param rangedValueRingWidth The width to render the ranged value ring with
*/
public void setRangedValueRingWidth(int rangedValueRingWidth) {
- this.mRangedValueRingWidth = rangedValueRingWidth;
+ mRangedValueRingWidth = rangedValueRingWidth;
+ mDirty = true;
}
/**
@@ -407,7 +429,8 @@
* @param rangedValuePrimaryColor The main color to render the ranged value text with
*/
public void setRangedValuePrimaryColor(int rangedValuePrimaryColor) {
- this.mRangedValuePrimaryColor = rangedValuePrimaryColor;
+ mRangedValuePrimaryColor = rangedValuePrimaryColor;
+ mDirty = true;
}
/**
@@ -416,7 +439,8 @@
* @param rangedValueSecondaryColor The secondary color to render the ranged value text with
*/
public void setRangedValueSecondaryColor(int rangedValueSecondaryColor) {
- this.mRangedValueSecondaryColor = rangedValueSecondaryColor;
+ mRangedValueSecondaryColor = rangedValueSecondaryColor;
+ mDirty = true;
}
/**
@@ -425,6 +449,7 @@
* @param highlightColor The background color to use when the complication is highlighted
*/
public void setHighlightColor(int highlightColor) {
- this.mHighlightColor = highlightColor;
+ mHighlightColor = highlightColor;
+ mDirty = true;
}
}
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/EmojiHelper.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/EmojiHelper.java
similarity index 97%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/EmojiHelper.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/EmojiHelper.java
index a93f49a..ab01980 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/EmojiHelper.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/EmojiHelper.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/RoundedDrawable.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/RoundedDrawable.java
similarity index 98%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/RoundedDrawable.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/RoundedDrawable.java
index 70af2ac..a187cc1 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/RoundedDrawable.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/RoundedDrawable.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/TextRenderer.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/TextRenderer.java
similarity index 99%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/TextRenderer.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/TextRenderer.java
index e9776af..3bd5ba0 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/TextRenderer.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/TextRenderer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import android.graphics.Canvas;
import android.graphics.Rect;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/IconLayoutHelper.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/IconLayoutHelper.java
similarity index 87%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/IconLayoutHelper.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/IconLayoutHelper.java
index 1d4bea3..aee6906 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/IconLayoutHelper.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/IconLayoutHelper.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering.utils;
+package androidx.wear.watchface.complications.rendering.utils;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getCentralSquare;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getCentralSquare;
import android.graphics.Rect;
import android.support.wearable.complications.ComplicationData;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LargeImageLayoutHelper.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LargeImageLayoutHelper.java
similarity index 87%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LargeImageLayoutHelper.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LargeImageLayoutHelper.java
index bc33e44..8f6fdbb 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LargeImageLayoutHelper.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LargeImageLayoutHelper.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering.utils;
+package androidx.wear.watchface.complications.rendering.utils;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getCentralSquare;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getCentralSquare;
import android.graphics.Rect;
import android.support.wearable.complications.ComplicationData;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LayoutHelper.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LayoutHelper.java
similarity index 98%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LayoutHelper.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LayoutHelper.java
index 1f14516..1f9d694 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LayoutHelper.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LayoutHelper.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering.utils;
+package androidx.wear.watchface.complications.rendering.utils;
import android.graphics.Rect;
import android.support.wearable.complications.ComplicationData;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LayoutUtils.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LayoutUtils.java
similarity index 98%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LayoutUtils.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LayoutUtils.java
index ed24d9a..1264d9f 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LayoutUtils.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LayoutUtils.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering.utils;
+package androidx.wear.watchface.complications.rendering.utils;
import android.graphics.Rect;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LongTextLayoutHelper.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LongTextLayoutHelper.java
similarity index 88%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LongTextLayoutHelper.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LongTextLayoutHelper.java
index d06ff26..423aa8b 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/LongTextLayoutHelper.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/LongTextLayoutHelper.java
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering.utils;
+package androidx.wear.watchface.complications.rendering.utils;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getBottomHalf;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getLeftPart;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getRightPart;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getTopHalf;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.isWideRectangle;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getBottomHalf;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getLeftPart;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getRightPart;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getTopHalf;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.isWideRectangle;
import android.graphics.Rect;
import android.support.wearable.complications.ComplicationData;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/RangedValueLayoutHelper.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/RangedValueLayoutHelper.java
similarity index 90%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/RangedValueLayoutHelper.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/RangedValueLayoutHelper.java
index f565891..d25f2e4 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/RangedValueLayoutHelper.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/RangedValueLayoutHelper.java
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering.utils;
+package androidx.wear.watchface.complications.rendering.utils;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getBottomHalf;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getCentralSquare;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getLeftPart;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getRightPart;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getTopHalf;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.isWideRectangle;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.scaledAroundCenter;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getBottomHalf;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getCentralSquare;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getLeftPart;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getRightPart;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getTopHalf;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.isWideRectangle;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.scaledAroundCenter;
import android.graphics.Rect;
import android.support.wearable.complications.ComplicationData;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/ShortTextLayoutHelper.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/ShortTextLayoutHelper.java
similarity index 86%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/ShortTextLayoutHelper.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/ShortTextLayoutHelper.java
index 9479541..fa275d3 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/ShortTextLayoutHelper.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/ShortTextLayoutHelper.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering.utils;
+package androidx.wear.watchface.complications.rendering.utils;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getBottomHalf;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getCentralSquare;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getLeftPart;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getRightPart;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getTopHalf;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.isWideRectangle;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getBottomHalf;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getCentralSquare;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getLeftPart;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getRightPart;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getTopHalf;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.isWideRectangle;
import android.graphics.Rect;
import android.support.wearable.complications.ComplicationData;
diff --git a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/SmallImageLayoutHelper.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/SmallImageLayoutHelper.java
similarity index 87%
rename from wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/SmallImageLayoutHelper.java
rename to wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/SmallImageLayoutHelper.java
index aa6910b..944b97d 100644
--- a/wear/wear-complications-rendering/src/main/java/androidx/wear/complications/rendering/utils/SmallImageLayoutHelper.java
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/utils/SmallImageLayoutHelper.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering.utils;
+package androidx.wear.watchface.complications.rendering.utils;
-import static androidx.wear.complications.rendering.utils.LayoutUtils.getCentralSquare;
+import static androidx.wear.watchface.complications.rendering.utils.LayoutUtils.getCentralSquare;
import android.graphics.Rect;
import android.support.wearable.complications.ComplicationData;
diff --git a/wear/wear-complications-rendering/src/main/res/values/attrs.xml b/wear/wear-watchface-complications-rendering/src/main/res/values/attrs.xml
similarity index 100%
rename from wear/wear-complications-rendering/src/main/res/values/attrs.xml
rename to wear/wear-watchface-complications-rendering/src/main/res/values/attrs.xml
diff --git a/wear/wear-complications-rendering/src/main/res/values/complication_drawable.xml b/wear/wear-watchface-complications-rendering/src/main/res/values/complication_drawable.xml
similarity index 100%
rename from wear/wear-complications-rendering/src/main/res/values/complication_drawable.xml
rename to wear/wear-watchface-complications-rendering/src/main/res/values/complication_drawable.xml
diff --git a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationDrawableTest.java b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationDrawableTest.java
similarity index 96%
rename from wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationDrawableTest.java
rename to wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationDrawableTest.java
index 5f7af52..aab40c9 100644
--- a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationDrawableTest.java
+++ b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationDrawableTest.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
-import static androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED;
-import static androidx.wear.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE;
+import static androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_DASHED;
+import static androidx.wear.watchface.complications.rendering.ComplicationDrawable.BORDER_STYLE_NONE;
import static com.google.common.truth.Truth.assertThat;
@@ -679,6 +679,20 @@
assertThat(copy.getAmbientStyle().getTitleSize()).isEqualTo(titleSizeAmbient);
}
+ @Test
+ public void testUpdateStyleIfRequired() {
+ mComplicationDrawable.setContext(ApplicationProvider.getApplicationContext());
+ mComplicationDrawable.getActiveStyle().setBackgroundColor(123);
+
+ assertThat(mComplicationDrawable.getComplicationRenderer().mActivePaintSet
+ .mBackgroundPaint.getColor()).isNotEqualTo(123);
+
+ mComplicationDrawable.updateStyleIfRequired();
+
+ assertThat(mComplicationDrawable.getComplicationRenderer().mActivePaintSet
+ .mBackgroundPaint.getColor()).isEqualTo(123);
+ }
+
/** Proxies necessary methods to Robolectric application. */
private static class FakeWatchFaceService extends WatchFaceService {
@@ -708,7 +722,7 @@
WatchFaceType.ANALOG,
100,
userStyleRepository,
- new ComplicationsManager(new ArrayList<>()),
+ new ComplicationsManager(new ArrayList<>(), userStyleRepository),
new Renderer(surfaceHolder, userStyleRepository, watchState) {
@NotNull
@Override
diff --git a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationRendererTest.java b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationRendererTest.java
similarity index 99%
rename from wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationRendererTest.java
rename to wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationRendererTest.java
index 95bda47..6cfe8ed 100644
--- a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationRendererTest.java
+++ b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationRendererTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import static android.support.wearable.complications.ComplicationData.TYPE_ICON;
import static android.support.wearable.complications.ComplicationData.TYPE_LONG_TEXT;
@@ -48,8 +48,8 @@
import android.text.style.ForegroundColorSpan;
import androidx.test.core.app.ApplicationProvider;
-import androidx.wear.complications.rendering.ComplicationRenderer.OnInvalidateListener;
-import androidx.wear.complications.rendering.ComplicationRenderer.PaintSet;
+import androidx.wear.watchface.complications.rendering.ComplicationRenderer.OnInvalidateListener;
+import androidx.wear.watchface.complications.rendering.ComplicationRenderer.PaintSet;
import org.junit.Before;
import org.junit.Test;
diff --git a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationsTestRunner.java b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationsTestRunner.java
similarity index 96%
rename from wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationsTestRunner.java
rename to wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationsTestRunner.java
index ba4e24a..5643ecf 100644
--- a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/ComplicationsTestRunner.java
+++ b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationsTestRunner.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import androidx.annotation.NonNull;
diff --git a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/EmojiHelperTest.java b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/EmojiHelperTest.java
similarity index 99%
rename from wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/EmojiHelperTest.java
rename to wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/EmojiHelperTest.java
index 3428ccd..6931e13 100644
--- a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/EmojiHelperTest.java
+++ b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/EmojiHelperTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
diff --git a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/RoundedDrawableTest.java b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/RoundedDrawableTest.java
similarity index 97%
rename from wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/RoundedDrawableTest.java
rename to wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/RoundedDrawableTest.java
index d63c3d4..c909f57 100644
--- a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/RoundedDrawableTest.java
+++ b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/RoundedDrawableTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import static com.google.common.truth.Truth.assertThat;
diff --git a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/TextRendererTest.java b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/TextRendererTest.java
similarity index 97%
rename from wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/TextRendererTest.java
rename to wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/TextRendererTest.java
index 69b6089..667d097 100644
--- a/wear/wear-complications-rendering/src/test/java/androidx/wear/complications/rendering/TextRendererTest.java
+++ b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/TextRendererTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.wear.complications.rendering;
+package androidx.wear.watchface.complications.rendering;
import static com.google.common.truth.Truth.assertThat;
diff --git a/wear/wear-complications-rendering/src/test/resources/robolectric.properties b/wear/wear-watchface-complications-rendering/src/test/resources/robolectric.properties
similarity index 100%
rename from wear/wear-complications-rendering/src/test/resources/robolectric.properties
rename to wear/wear-watchface-complications-rendering/src/test/resources/robolectric.properties
diff --git a/wear/wear-watchface-data/api/restricted_current.txt b/wear/wear-watchface-data/api/restricted_current.txt
index b1ce327..e648d5f 100644
--- a/wear/wear-watchface-data/api/restricted_current.txt
+++ b/wear/wear-watchface-data/api/restricted_current.txt
@@ -139,6 +139,15 @@
field public static final android.os.Parcelable.Creator<androidx.wear.watchface.data.ComplicationDetails!>! CREATOR;
}
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public final class IdAndComplicationData implements android.os.Parcelable androidx.versionedparcelable.VersionedParcelable {
+ ctor public IdAndComplicationData(int, android.support.wearable.complications.ComplicationData);
+ method public int describeContents();
+ method public android.support.wearable.complications.ComplicationData getComplicationData();
+ method public int getId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.wear.watchface.data.IdAndComplicationData!>! CREATOR;
+ }
+
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public final class ImmutableSystemState implements android.os.Parcelable androidx.versionedparcelable.VersionedParcelable {
ctor public ImmutableSystemState(boolean, boolean);
method public int describeContents();
@@ -203,6 +212,35 @@
field @androidx.versionedparcelable.ParcelField(2) public boolean mValue;
}
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public class ComplicationsUserStyleCategoryWireFormat extends androidx.wear.watchface.style.data.UserStyleCategoryWireFormat {
+ ctor public ComplicationsUserStyleCategoryWireFormat(String, String, String, android.graphics.drawable.Icon?, java.util.List<androidx.wear.watchface.style.data.UserStyleCategoryWireFormat.OptionWireFormat!>, int, java.util.List<java.lang.Integer!>);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public static class ComplicationsUserStyleCategoryWireFormat.ComplicationConfigWireFormat implements android.os.Parcelable androidx.versionedparcelable.VersionedParcelable {
+ ctor public ComplicationsUserStyleCategoryWireFormat.ComplicationConfigWireFormat(int, Boolean?, android.graphics.RectF?, int[]?, java.util.List<android.content.ComponentName!>?, Integer?, @android.support.wearable.complications.ComplicationData.ComplicationType Integer?);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat.ComplicationConfigWireFormat!>! CREATOR;
+ field public static final int ENABLED_NO = 0; // 0x0
+ field public static final int ENABLED_UNKNOWN = -1; // 0xffffffff
+ field public static final int ENABLED_YES = 1; // 0x1
+ field public static final int NO_DEFAULT_PROVIDER_TYPE = -1; // 0xffffffff
+ field @androidx.versionedparcelable.ParcelField(3) public android.graphics.RectF? mBounds;
+ field @androidx.versionedparcelable.ParcelField(1) public int mComplicationId;
+ field @android.support.wearable.complications.ComplicationData.ComplicationType @androidx.versionedparcelable.ParcelField(7) public int mDefaultProviderType;
+ field @androidx.versionedparcelable.ParcelField(5) public java.util.List<android.content.ComponentName!>? mDefaultProviders;
+ field @androidx.versionedparcelable.ParcelField(2) public int mEnabled;
+ field @androidx.versionedparcelable.ParcelField(4) public int[]? mSupportedTypes;
+ field @androidx.versionedparcelable.ParcelField(6) @androidx.wear.complications.SystemProviders.ProviderId public int mSystemProviderFallback;
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public static class ComplicationsUserStyleCategoryWireFormat.ComplicationsOptionWireFormat extends androidx.wear.watchface.style.data.UserStyleCategoryWireFormat.OptionWireFormat {
+ ctor public ComplicationsUserStyleCategoryWireFormat.ComplicationsOptionWireFormat(String, String, android.graphics.drawable.Icon?, androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat.ComplicationConfigWireFormat![]);
+ field @androidx.versionedparcelable.ParcelField(100) public androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat.ComplicationConfigWireFormat![] mComplications;
+ field @androidx.versionedparcelable.ParcelField(2) public String mDisplayName;
+ field @androidx.versionedparcelable.ParcelField(3) public android.graphics.drawable.Icon? mIcon;
+ }
+
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public class DoubleRangeUserStyleCategoryWireFormat extends androidx.wear.watchface.style.data.UserStyleCategoryWireFormat {
ctor public DoubleRangeUserStyleCategoryWireFormat(String, String, String, android.graphics.drawable.Icon?, java.util.List<androidx.wear.watchface.style.data.UserStyleCategoryWireFormat.OptionWireFormat!>, int, java.util.List<java.lang.Integer!>);
}
diff --git a/wear/wear-watchface-data/src/main/aidl/android/support/wearable/watchface/IWatchFaceCommand.aidl b/wear/wear-watchface-data/src/main/aidl/android/support/wearable/watchface/IWatchFaceCommand.aidl
index 2a2f7b9..1e23e6c 100644
--- a/wear/wear-watchface-data/src/main/aidl/android/support/wearable/watchface/IWatchFaceCommand.aidl
+++ b/wear/wear-watchface-data/src/main/aidl/android/support/wearable/watchface/IWatchFaceCommand.aidl
@@ -17,6 +17,7 @@
package android.support.wearable.watchface;
import android.support.wearable.complications.ComplicationData;
+import androidx.wear.watchface.data.IdAndComplicationData;
import androidx.wear.watchface.data.ImmutableSystemState;
import androidx.wear.watchface.data.IndicatorState;
import androidx.wear.watchface.data.RenderParametersWireFormat;
@@ -109,6 +110,8 @@
* @param renderParameters The {@link RenderParametersWireFormat} to render with
* @param compressionQuality The WebP compression quality, 100 = lossless
* @param calendarTimeMillis The calendar time (millis since the epoch) to render with
+ * @param complicationData The complications to render with. If null then the current
+ * complication data is used instead.
* @param style A {@link StyleMapWireFormat}. If null then the current style is used.
* @return A bundle containing a compressed shared memory backed {@link Bitmap} of the watch
* face with the requested settings
@@ -116,6 +119,7 @@
Bundle takeWatchfaceScreenshot(in RenderParametersWireFormat renderParameters,
in int compressionQuality,
in long calendarTimeMillis,
+ in List<IdAndComplicationData> complicationData,
in UserStyleWireFormat style) = 9;
/**
diff --git a/wear/wear-watchface-data/src/main/aidl/androidx/wear/watchface/data/IdAndComplicationData.aidl b/wear/wear-watchface-data/src/main/aidl/androidx/wear/watchface/data/IdAndComplicationData.aidl
new file mode 100644
index 0000000..20e6b89
--- /dev/null
+++ b/wear/wear-watchface-data/src/main/aidl/androidx/wear/watchface/data/IdAndComplicationData.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.wear.watchface.data;
+
+/** @hide */
+parcelable IdAndComplicationData;
\ No newline at end of file
diff --git a/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/IdAndComplicationData.java b/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/IdAndComplicationData.java
new file mode 100644
index 0000000..16019f3
--- /dev/null
+++ b/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/IdAndComplicationData.java
@@ -0,0 +1,90 @@
+/*
+ * 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.wear.watchface.data;
+
+import android.annotation.SuppressLint;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.wearable.complications.ComplicationData;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.versionedparcelable.ParcelField;
+import androidx.versionedparcelable.ParcelUtils;
+import androidx.versionedparcelable.VersionedParcelable;
+import androidx.versionedparcelable.VersionedParcelize;
+
+/**
+ * Wire format to encode a pair of id to {@link ComplicationData}.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+@VersionedParcelize
+@SuppressLint("BanParcelableUsage") // TODO(b/169214666): Remove Parcelable
+public final class IdAndComplicationData implements VersionedParcelable, Parcelable {
+ @ParcelField(1)
+ int mId;
+
+ @ParcelField(2)
+ @NonNull
+ ComplicationData mComplicationData;
+
+ /** Used by VersionedParcelable. */
+ IdAndComplicationData() {
+ }
+
+ public IdAndComplicationData(int id, @NonNull ComplicationData complicationData) {
+ mId = id;
+ mComplicationData = complicationData;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ @NonNull
+ public ComplicationData getComplicationData() {
+ return mComplicationData;
+ }
+
+ /** Serializes this IdAndComplicationData to the specified {@link Parcel}. */
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeParcelable(ParcelUtils.toParcelable(this), flags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<IdAndComplicationData> CREATOR =
+ new Parcelable.Creator<IdAndComplicationData>() {
+ @Override
+ public IdAndComplicationData createFromParcel(Parcel source) {
+ return IdAndComplicationDataParcelizer.read(
+ ParcelUtils.fromParcelable(source.readParcelable(
+ getClass().getClassLoader())));
+ }
+
+ @Override
+ public IdAndComplicationData[] newArray(int size) {
+ return new IdAndComplicationData[size];
+ }
+ };
+}
diff --git a/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/style/data/ComplicationsUserStyleCategoryWireFormat.java b/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/style/data/ComplicationsUserStyleCategoryWireFormat.java
new file mode 100644
index 0000000..cebca8a
--- /dev/null
+++ b/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/style/data/ComplicationsUserStyleCategoryWireFormat.java
@@ -0,0 +1,203 @@
+/*
+ * 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.wear.watchface.style.data;
+
+import android.annotation.SuppressLint;
+import android.content.ComponentName;
+import android.graphics.RectF;
+import android.graphics.drawable.Icon;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.wearable.complications.ComplicationData;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.versionedparcelable.ParcelField;
+import androidx.versionedparcelable.ParcelUtils;
+import androidx.versionedparcelable.VersionedParcelable;
+import androidx.versionedparcelable.VersionedParcelize;
+import androidx.wear.complications.SystemProviders;
+
+import java.util.List;
+
+/**
+ * Wire format for {@link androidx.wear.watchface.style.ComplicationsUserStyleCategory}.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+@VersionedParcelize
+public class ComplicationsUserStyleCategoryWireFormat extends UserStyleCategoryWireFormat {
+
+ ComplicationsUserStyleCategoryWireFormat() {
+ }
+
+ public ComplicationsUserStyleCategoryWireFormat(
+ @NonNull String id,
+ @NonNull String displayName,
+ @NonNull String description,
+ @Nullable Icon icon,
+ @NonNull List<OptionWireFormat> options,
+ int defaultOptionIndex,
+ @NonNull List<Integer> affectsLayers) {
+ super(id, displayName, description, icon, options, defaultOptionIndex, affectsLayers);
+ }
+
+ /** @hide */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ @VersionedParcelize
+ @SuppressLint("BanParcelableUsage") // TODO(b/169214666): Remove Parcelable
+ public static class ComplicationConfigWireFormat implements VersionedParcelable, Parcelable {
+ public static final int ENABLED_UNKNOWN = -1;
+ public static final int ENABLED_YES = 1;
+ public static final int ENABLED_NO = 0;
+ public static final int NO_DEFAULT_PROVIDER_TYPE = -1;
+
+ @ParcelField(1)
+ public int mComplicationId;
+
+ /**
+ * VersionedParcelable doesn't support boxed Boolean so we set this to one of
+ * ENABLED_UNKNOWN, ENABLED_YES, ENABLED_NO.
+ */
+ @ParcelField(2)
+ public int mEnabled;
+
+ @ParcelField(3)
+ @Nullable
+ public RectF mBounds;
+
+ @ParcelField(4)
+ @Nullable
+ public int[] mSupportedTypes;
+
+ @ParcelField(5)
+ @Nullable
+ public List<ComponentName> mDefaultProviders;
+
+ /**
+ * VersionedParcelable doesn't support boxed Integer, but that's OK, this is only valid when
+ * mDefaultProviders is non null.
+ */
+ @ParcelField(6)
+ @SystemProviders.ProviderId
+ public int mSystemProviderFallback;
+
+ /**
+ * VersionedParcelable doesn't support boxed Integer so NO_DEFAULT_PROVIDER_TYPE is used to
+ * represent null.
+ */
+ @ParcelField(7)
+ @ComplicationData.ComplicationType
+ public int mDefaultProviderType;
+
+ ComplicationConfigWireFormat() {}
+
+ public ComplicationConfigWireFormat(
+ int complicationId,
+ @Nullable Boolean enabled,
+ @Nullable RectF bounds,
+ @Nullable int[] supportedTypes,
+ @Nullable List<ComponentName> defaultProviders,
+ @Nullable Integer systemProviderFallback,
+ @Nullable @ComplicationData.ComplicationType Integer defaultProviderType
+ ) {
+ mComplicationId = complicationId;
+ if (enabled != null) {
+ mEnabled = enabled ? ENABLED_YES : ENABLED_NO;
+ } else {
+ mEnabled = ENABLED_UNKNOWN;
+ }
+ mBounds = bounds;
+ mSupportedTypes = supportedTypes;
+ mDefaultProviders = defaultProviders;
+ if (systemProviderFallback != null) {
+ mSystemProviderFallback = systemProviderFallback;
+ }
+ mDefaultProviderType =
+ (defaultProviderType != null) ? defaultProviderType : NO_DEFAULT_PROVIDER_TYPE;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Serializes this UserStyleWireFormat to the specified {@link Parcel}. */
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeParcelable(ParcelUtils.toParcelable(this), flags);
+ }
+
+ public static final Parcelable.Creator<ComplicationConfigWireFormat> CREATOR =
+ new Parcelable.Creator<ComplicationConfigWireFormat>() {
+ @Override
+ public ComplicationConfigWireFormat createFromParcel(Parcel source) {
+ return ComplicationConfigWireFormatParcelizer.read(
+ ParcelUtils.fromParcelable(source.readParcelable(
+ getClass().getClassLoader())));
+ }
+
+ @Override
+ public ComplicationConfigWireFormat[] newArray(int size) {
+ return new ComplicationConfigWireFormat[size];
+ }
+ };
+ }
+
+ /**
+ * Wire format for {@link
+ * androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationsOption}.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ @VersionedParcelize
+ public static class ComplicationsOptionWireFormat extends OptionWireFormat {
+ @ParcelField(2)
+ @NonNull
+ public String mDisplayName;
+
+ @ParcelField(3)
+ @Nullable
+ public Icon mIcon;
+
+ /**
+ * Great care should be taken to ensure backwards compatibility of the versioned parcelable
+ * if {@link ComplicationConfigWireFormat} is ever extended.
+ */
+ @ParcelField(100)
+ @NonNull
+ public ComplicationConfigWireFormat[] mComplications;
+
+ ComplicationsOptionWireFormat() {
+ }
+
+ public ComplicationsOptionWireFormat(
+ @NonNull String id,
+ @NonNull String displayName,
+ @Nullable Icon icon,
+ @NonNull ComplicationConfigWireFormat[] complications
+ ) {
+ super(id);
+ mDisplayName = displayName;
+ mIcon = icon;
+ mComplications = complications;
+ }
+ }
+}
diff --git a/wear/wear-watchface-style/api/current.txt b/wear/wear-watchface-style/api/current.txt
index e47bfc9..d9b7c3f 100644
--- a/wear/wear-watchface-style/api/current.txt
+++ b/wear/wear-watchface-style/api/current.txt
@@ -12,6 +12,45 @@
property public final boolean value;
}
+ public final class ComplicationsUserStyleCategory extends androidx.wear.watchface.style.UserStyleCategory {
+ ctor public ComplicationsUserStyleCategory(String id, String displayName, String description, android.graphics.drawable.Icon? icon, java.util.List<? extends androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationsOption> complicationConfig, java.util.Collection<? extends androidx.wear.watchface.style.Layer> affectsLayers);
+ }
+
+ public static final class ComplicationsUserStyleCategory.ComplicationOverride {
+ method public android.graphics.RectF? getBounds();
+ method public int getComplicationId();
+ method public androidx.wear.complications.DefaultComplicationProviderPolicy? getDefaultProviderPolicy();
+ method public Integer? getDefaultProviderType();
+ method public int[]? getSupportedTypes();
+ method public Boolean? isEnabled();
+ property public final android.graphics.RectF? bounds;
+ property public final int complicationId;
+ property public final androidx.wear.complications.DefaultComplicationProviderPolicy? defaultProviderPolicy;
+ property public final Integer? defaultProviderType;
+ property public final Boolean? enabled;
+ property public final int[]? supportedTypes;
+ }
+
+ public static final class ComplicationsUserStyleCategory.ComplicationOverride.Builder {
+ ctor public ComplicationsUserStyleCategory.ComplicationOverride.Builder(int complicationId);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride build();
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setBounds(android.graphics.RectF bounds);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setDefaultProviderPolicy(androidx.wear.complications.DefaultComplicationProviderPolicy? defaultComplicationProviderPolicy);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setDefaultProviderType(int defaultComplicationProviderType);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setEnabled(boolean enabled);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setSupportedTypes(int[] supportedTypes);
+ }
+
+ public static class ComplicationsUserStyleCategory.ComplicationsOption extends androidx.wear.watchface.style.UserStyleCategory.Option {
+ ctor public ComplicationsUserStyleCategory.ComplicationsOption(String id, String displayName, android.graphics.drawable.Icon? icon, java.util.Collection<androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride> complications);
+ method public final java.util.Collection<androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride> getComplications();
+ method public final String getDisplayName();
+ method public final android.graphics.drawable.Icon? getIcon();
+ property public final java.util.Collection<androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride> complications;
+ property public final String displayName;
+ property public final android.graphics.drawable.Icon? icon;
+ }
+
public final class DoubleRangeUserStyleCategory extends androidx.wear.watchface.style.UserStyleCategory {
ctor public DoubleRangeUserStyleCategory(String id, String displayName, String description, android.graphics.drawable.Icon? icon, double minimumValue, double maximumValue, double defaultValue, java.util.Collection<? extends androidx.wear.watchface.style.Layer> affectsLayers);
method public double getDefaultValue();
diff --git a/wear/wear-watchface-style/api/public_plus_experimental_current.txt b/wear/wear-watchface-style/api/public_plus_experimental_current.txt
index 8c52e86..ef22276 100644
--- a/wear/wear-watchface-style/api/public_plus_experimental_current.txt
+++ b/wear/wear-watchface-style/api/public_plus_experimental_current.txt
@@ -14,6 +14,47 @@
property public final boolean value;
}
+ public final class ComplicationsUserStyleCategory extends androidx.wear.watchface.style.UserStyleCategory {
+ ctor public ComplicationsUserStyleCategory(String id, String displayName, String description, android.graphics.drawable.Icon? icon, java.util.List<? extends androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationsOption> complicationConfig, java.util.Collection<? extends androidx.wear.watchface.style.Layer> affectsLayers);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat toWireFormat();
+ }
+
+ public static final class ComplicationsUserStyleCategory.ComplicationOverride {
+ method public android.graphics.RectF? getBounds();
+ method public int getComplicationId();
+ method public androidx.wear.complications.DefaultComplicationProviderPolicy? getDefaultProviderPolicy();
+ method public Integer? getDefaultProviderType();
+ method public int[]? getSupportedTypes();
+ method public Boolean? isEnabled();
+ property public final android.graphics.RectF? bounds;
+ property public final int complicationId;
+ property public final androidx.wear.complications.DefaultComplicationProviderPolicy? defaultProviderPolicy;
+ property public final Integer? defaultProviderType;
+ property public final Boolean? enabled;
+ property public final int[]? supportedTypes;
+ }
+
+ public static final class ComplicationsUserStyleCategory.ComplicationOverride.Builder {
+ ctor public ComplicationsUserStyleCategory.ComplicationOverride.Builder(int complicationId);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride build();
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setBounds(android.graphics.RectF bounds);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setDefaultProviderPolicy(androidx.wear.complications.DefaultComplicationProviderPolicy? defaultComplicationProviderPolicy);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setDefaultProviderType(@android.support.wearable.complications.ComplicationData.ComplicationType int defaultComplicationProviderType);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setEnabled(boolean enabled);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setSupportedTypes(int[] supportedTypes);
+ }
+
+ public static class ComplicationsUserStyleCategory.ComplicationsOption extends androidx.wear.watchface.style.UserStyleCategory.Option {
+ ctor public ComplicationsUserStyleCategory.ComplicationsOption(String id, String displayName, android.graphics.drawable.Icon? icon, java.util.Collection<androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride> complications);
+ method public final java.util.Collection<androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride> getComplications();
+ method public final String getDisplayName();
+ method public final android.graphics.drawable.Icon? getIcon();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat.ComplicationsOptionWireFormat toWireFormat();
+ property public final java.util.Collection<androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride> complications;
+ property public final String displayName;
+ property public final android.graphics.drawable.Icon? icon;
+ }
+
public final class DoubleRangeUserStyleCategory extends androidx.wear.watchface.style.UserStyleCategory {
ctor public DoubleRangeUserStyleCategory(String id, String displayName, String description, android.graphics.drawable.Icon? icon, double minimumValue, double maximumValue, double defaultValue, java.util.Collection<? extends androidx.wear.watchface.style.Layer> affectsLayers);
method public double getDefaultValue();
diff --git a/wear/wear-watchface-style/api/restricted_current.txt b/wear/wear-watchface-style/api/restricted_current.txt
index bdf8715..988f5466 100644
--- a/wear/wear-watchface-style/api/restricted_current.txt
+++ b/wear/wear-watchface-style/api/restricted_current.txt
@@ -14,6 +14,47 @@
property public final boolean value;
}
+ public final class ComplicationsUserStyleCategory extends androidx.wear.watchface.style.UserStyleCategory {
+ ctor public ComplicationsUserStyleCategory(String id, String displayName, String description, android.graphics.drawable.Icon? icon, java.util.List<? extends androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationsOption> complicationConfig, java.util.Collection<? extends androidx.wear.watchface.style.Layer> affectsLayers);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat toWireFormat();
+ }
+
+ public static final class ComplicationsUserStyleCategory.ComplicationOverride {
+ method public android.graphics.RectF? getBounds();
+ method public int getComplicationId();
+ method public androidx.wear.complications.DefaultComplicationProviderPolicy? getDefaultProviderPolicy();
+ method public Integer? getDefaultProviderType();
+ method public int[]? getSupportedTypes();
+ method public Boolean? isEnabled();
+ property public final android.graphics.RectF? bounds;
+ property public final int complicationId;
+ property public final androidx.wear.complications.DefaultComplicationProviderPolicy? defaultProviderPolicy;
+ property public final Integer? defaultProviderType;
+ property public final Boolean? enabled;
+ property public final int[]? supportedTypes;
+ }
+
+ public static final class ComplicationsUserStyleCategory.ComplicationOverride.Builder {
+ ctor public ComplicationsUserStyleCategory.ComplicationOverride.Builder(int complicationId);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride build();
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setBounds(android.graphics.RectF bounds);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setDefaultProviderPolicy(androidx.wear.complications.DefaultComplicationProviderPolicy? defaultComplicationProviderPolicy);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setDefaultProviderType(@android.support.wearable.complications.ComplicationData.ComplicationType int defaultComplicationProviderType);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setEnabled(boolean enabled);
+ method public androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride.Builder setSupportedTypes(int[] supportedTypes);
+ }
+
+ public static class ComplicationsUserStyleCategory.ComplicationsOption extends androidx.wear.watchface.style.UserStyleCategory.Option {
+ ctor public ComplicationsUserStyleCategory.ComplicationsOption(String id, String displayName, android.graphics.drawable.Icon? icon, java.util.Collection<androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride> complications);
+ method public final java.util.Collection<androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride> getComplications();
+ method public final String getDisplayName();
+ method public final android.graphics.drawable.Icon? getIcon();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat.ComplicationsOptionWireFormat toWireFormat();
+ property public final java.util.Collection<androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride> complications;
+ property public final String displayName;
+ property public final android.graphics.drawable.Icon? icon;
+ }
+
public final class DoubleRangeUserStyleCategory extends androidx.wear.watchface.style.UserStyleCategory {
ctor public DoubleRangeUserStyleCategory(String id, String displayName, String description, android.graphics.drawable.Icon? icon, double minimumValue, double maximumValue, double defaultValue, java.util.Collection<? extends androidx.wear.watchface.style.Layer> affectsLayers);
method public double getDefaultValue();
diff --git a/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/ComplicationsUserStyleCategory.kt b/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/ComplicationsUserStyleCategory.kt
new file mode 100644
index 0000000..efa1917
--- /dev/null
+++ b/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/ComplicationsUserStyleCategory.kt
@@ -0,0 +1,262 @@
+/*
+ * 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.wear.watchface.style
+
+import android.graphics.RectF
+import android.graphics.drawable.Icon
+import android.support.wearable.complications.ComplicationData
+import androidx.annotation.RestrictTo
+import androidx.wear.complications.DefaultComplicationProviderPolicy
+import androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat
+import androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat.ComplicationConfigWireFormat
+import androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat.ComplicationsOptionWireFormat
+import java.security.InvalidParameterException
+
+/**
+ * ComplicationsUserStyleCategory is the recommended [UserStyleCategory] for representing
+ * complication configuration options such as the number of active complications, their location,
+ * etc...
+ *
+ * The ComplicationsManager listens for style changes with this category and applies them
+ * automatically.
+ *
+ * Not to be confused with complication provider selection.
+ */
+class ComplicationsUserStyleCategory : UserStyleCategory {
+
+ /**
+ * Overrides to be applied to the corresponding complication's initial config (as specified in
+ * [androidx.wear.watchface.Complication]) when the category is selected.
+ */
+ class ComplicationOverride internal constructor(
+ /** The id of the complication to configure. */
+ val complicationId: Int,
+
+ /**
+ * If non null, whether the complication should be enabled for this configuration. If null
+ * then no changes are made.
+ */
+ @get:JvmName("isEnabled")
+ val enabled: Boolean?,
+
+ /**
+ * If non null, the new unit square screen space complication bounds for this configuration.
+ * If null then no changes are made.
+ */
+ val bounds: RectF?,
+
+ /**
+ * If non null, the new types of complication supported by this complication for this
+ * configuration. If null then no changes are made.
+ */
+ val supportedTypes: IntArray?,
+
+ /**
+ * If non null, the new default complication provider for this configuration. If null then
+ * no changes are made.
+ */
+ val defaultProviderPolicy: DefaultComplicationProviderPolicy?,
+
+ /**
+ * If non null, the new default complication provider data type. See
+ * [ComplicationData .ComplicationType]. If null then no changes are made.
+ */
+ @get:SuppressWarnings("AutoBoxing")
+ val defaultProviderType: Int?
+ ) {
+ class Builder(
+ /** The id of the complication to configure. */
+ private val complicationId: Int
+ ) {
+ private var enabled: Boolean? = null
+ private var bounds: RectF? = null
+ private var supportedTypes: IntArray? = null
+ private var defaultComplicationProviderPolicy: DefaultComplicationProviderPolicy? = null
+ private var defaultComplicationProviderType: Int? = null
+
+ /** Overrides the complication's enabled flag. */
+ fun setEnabled(enabled: Boolean) = apply {
+ this.enabled = enabled
+ }
+
+ /** Overrides the complication's unit-square screen space bounds. */
+ fun setBounds(bounds: RectF) = apply {
+ this.bounds = bounds
+ }
+
+ /** Overrides the complication's supported complication types. */
+ fun setSupportedTypes(supportedTypes: IntArray) = apply {
+ this.supportedTypes = supportedTypes
+ }
+
+ /** Overrides the complication's [DefaultComplicationProviderPolicy]. */
+ fun setDefaultProviderPolicy(
+ defaultComplicationProviderPolicy: DefaultComplicationProviderPolicy?
+ ) = apply {
+ this.defaultComplicationProviderPolicy = defaultComplicationProviderPolicy
+ }
+
+ /**
+ * Overrides the default complication provider data type. See
+ * [ComplicationData.ComplicationType]
+ */
+ fun setDefaultProviderType(
+ @ComplicationData.ComplicationType defaultComplicationProviderType: Int
+ ) = apply {
+ this.defaultComplicationProviderType = defaultComplicationProviderType
+ }
+
+ fun build() = ComplicationOverride(
+ complicationId,
+ enabled,
+ bounds,
+ supportedTypes,
+ defaultComplicationProviderPolicy,
+ defaultComplicationProviderType
+ )
+ }
+
+ internal constructor(
+ wireFormat: ComplicationConfigWireFormat
+ ) : this(
+ wireFormat.mComplicationId,
+ when (wireFormat.mEnabled) {
+ ComplicationConfigWireFormat.ENABLED_UNKNOWN -> null
+ ComplicationConfigWireFormat.ENABLED_YES -> true
+ ComplicationConfigWireFormat.ENABLED_NO -> false
+ else -> throw InvalidParameterException(
+ "Unrecognised wireFormat.mEnabled " + wireFormat.mEnabled
+ )
+ },
+ wireFormat.mBounds,
+ wireFormat.mSupportedTypes,
+ wireFormat.mDefaultProviders?.let {
+ DefaultComplicationProviderPolicy(it, wireFormat.mSystemProviderFallback)
+ },
+ if (wireFormat.mDefaultProviderType !=
+ ComplicationConfigWireFormat.NO_DEFAULT_PROVIDER_TYPE
+ ) {
+ wireFormat.mDefaultProviderType
+ } else {
+ null
+ }
+ )
+
+ internal fun toWireFormat() =
+ ComplicationConfigWireFormat(
+ complicationId,
+ enabled,
+ bounds,
+ supportedTypes,
+ defaultProviderPolicy?.providersAsList(),
+ defaultProviderPolicy?.systemProviderFallback,
+ defaultProviderType
+ )
+ }
+
+ constructor (
+ /** Identifier for the element, must be unique. */
+ id: String,
+
+ /** Localized human readable name for the element, used in the userStyle selection UI. */
+ displayName: String,
+
+ /** Localized description string displayed under the displayName. */
+ description: String,
+
+ /** Icon for use in the userStyle selection UI. */
+ icon: Icon?,
+
+ /**
+ * The configuration for affected complications. The first entry is the default value
+ */
+ complicationConfig: List<ComplicationsOption>,
+
+ /**
+ * Used by the style configuration UI. Describes which rendering layers this style affects,
+ * must include [Layer.COMPLICATIONS].
+ */
+ affectsLayers: Collection<Layer>
+ ) : super(
+ id,
+ displayName,
+ description,
+ icon,
+ complicationConfig,
+ 0,
+ affectsLayers
+ ) {
+ require(affectsLayers.contains(Layer.COMPLICATIONS))
+ }
+
+ internal constructor(wireFormat: ComplicationsUserStyleCategoryWireFormat) : super(wireFormat)
+
+ /** @hide */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ override fun toWireFormat() =
+ ComplicationsUserStyleCategoryWireFormat(
+ id,
+ displayName,
+ description,
+ icon,
+ getWireFormatOptionsList(),
+ defaultOptionIndex,
+ affectsLayers.map { it.ordinal }
+ )
+
+ /** Represents an override to the initial complication configuration. */
+ open class ComplicationsOption : Option {
+ /**
+ * Overrides to be applied when this ComplicationsOption is selected. If this is empty
+ * then the net result is the initial complication configuration.
+ */
+ val complications: Collection<ComplicationOverride>
+
+ /** Localized human readable name for the setting, used in the style selection UI. */
+ val displayName: String
+
+ /** Icon for use in the style selection UI. */
+ val icon: Icon?
+
+ constructor(
+ id: String,
+ displayName: String,
+ icon: Icon?,
+ complications: Collection<ComplicationOverride>
+ ) : super(id) {
+ this.complications = complications
+ this.displayName = displayName
+ this.icon = icon
+ }
+
+ internal constructor(wireFormat: ComplicationsOptionWireFormat) : super(wireFormat.mId) {
+ complications = wireFormat.mComplications.map { ComplicationOverride(it) }
+ displayName = wireFormat.mDisplayName
+ icon = wireFormat.mIcon
+ }
+
+ /** @hide */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ override fun toWireFormat() =
+ ComplicationsOptionWireFormat(
+ id,
+ displayName,
+ icon,
+ complications.map { it.toWireFormat() }.toTypedArray()
+ )
+ }
+}
\ No newline at end of file
diff --git a/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleCategory.kt b/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleCategory.kt
index bd77b8d..7ce6bff 100644
--- a/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleCategory.kt
+++ b/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleCategory.kt
@@ -19,6 +19,7 @@
import android.graphics.drawable.Icon
import androidx.annotation.RestrictTo
import androidx.wear.watchface.style.data.BooleanUserStyleCategoryWireFormat
+import androidx.wear.watchface.style.data.ComplicationsUserStyleCategoryWireFormat
import androidx.wear.watchface.style.data.DoubleRangeUserStyleCategoryWireFormat
import androidx.wear.watchface.style.data.ListUserStyleCategoryWireFormat
import androidx.wear.watchface.style.data.LongRangeUserStyleCategoryWireFormat
@@ -67,6 +68,9 @@
when (wireFormat) {
is BooleanUserStyleCategoryWireFormat -> BooleanUserStyleCategory(wireFormat)
+ is ComplicationsUserStyleCategoryWireFormat ->
+ ComplicationsUserStyleCategory(wireFormat)
+
is DoubleRangeUserStyleCategoryWireFormat ->
DoubleRangeUserStyleCategory(wireFormat)
@@ -132,6 +136,9 @@
is BooleanUserStyleCategoryWireFormat.BooleanOptionWireFormat ->
BooleanUserStyleCategory.BooleanOption(wireFormat)
+ is ComplicationsUserStyleCategoryWireFormat.ComplicationsOptionWireFormat ->
+ ComplicationsUserStyleCategory.ComplicationsOption(wireFormat)
+
is DoubleRangeUserStyleCategoryWireFormat.DoubleRangeOptionWireFormat ->
DoubleRangeUserStyleCategory.DoubleRangeOption(wireFormat)
diff --git a/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleRepository.kt b/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleRepository.kt
index aafa263..715db28 100644
--- a/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleRepository.kt
+++ b/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleRepository.kt
@@ -70,11 +70,13 @@
// The current style state which is initialized from the userStyleCategories.
@SuppressWarnings("SyntheticAccessor")
- private val _style = UserStyle(HashMap<UserStyleCategory, UserStyleCategory.Option>().apply {
- for (category in userStyleCategories) {
- this[category] = category.getDefaultOption()
+ private val _style = UserStyle(
+ HashMap<UserStyleCategory, UserStyleCategory.Option>().apply {
+ for (category in userStyleCategories) {
+ this[category] = category.getDefaultOption()
+ }
}
- })
+ )
/** The current user controlled style for rendering etc... */
var userStyle: UserStyle
diff --git a/wear/wear-watchface-style/src/test/java/androidx/wear/watchface/style/StyleParcelableTest.kt b/wear/wear-watchface-style/src/test/java/androidx/wear/watchface/style/StyleParcelableTest.kt
index 98f867a..e1eb89d 100644
--- a/wear/wear-watchface-style/src/test/java/androidx/wear/watchface/style/StyleParcelableTest.kt
+++ b/wear/wear-watchface-style/src/test/java/androidx/wear/watchface/style/StyleParcelableTest.kt
@@ -84,11 +84,11 @@
val wireFormat3 = option3.toWireFormat()
val unmarshalled1 = UserStyleCategory.Option.createFromWireFormat(wireFormat1)
- as ListUserStyleCategory.ListOption
+ as ListUserStyleCategory.ListOption
val unmarshalled2 = UserStyleCategory.Option.createFromWireFormat(wireFormat2)
- as ListUserStyleCategory.ListOption
+ as ListUserStyleCategory.ListOption
val unmarshalled3 = UserStyleCategory.Option.createFromWireFormat(wireFormat3)
- as ListUserStyleCategory.ListOption
+ as ListUserStyleCategory.ListOption
assertThat(unmarshalled1.id).isEqualTo("1")
assertThat(unmarshalled1.displayName).isEqualTo("one")
diff --git a/wear/wear-watchface-style/src/test/java/androidx/wear/watchface/style/UserStyleRepositoryTest.kt b/wear/wear-watchface-style/src/test/java/androidx/wear/watchface/style/UserStyleRepositoryTest.kt
index c9bff1c..dd9c959 100644
--- a/wear/wear-watchface-style/src/test/java/androidx/wear/watchface/style/UserStyleRepositoryTest.kt
+++ b/wear/wear-watchface-style/src/test/java/androidx/wear/watchface/style/UserStyleRepositoryTest.kt
@@ -100,10 +100,12 @@
Mockito.verify(mockListener2).onUserStyleChanged(userStyleRepository.userStyle)
Mockito.verify(mockListener3).onUserStyleChanged(userStyleRepository.userStyle)
- val newStyle = UserStyle(hashMapOf(
- colorStyleCategory to greenStyleOption,
- watchHandStyleCategory to gothicStyleOption
- ))
+ val newStyle = UserStyle(
+ hashMapOf(
+ colorStyleCategory to greenStyleOption,
+ watchHandStyleCategory to gothicStyleOption
+ )
+ )
Mockito.reset(mockListener1)
Mockito.reset(mockListener2)
@@ -118,10 +120,12 @@
@Test
fun assigning_userStyle() {
- val newStyle = UserStyle(hashMapOf(
- colorStyleCategory to greenStyleOption,
- watchHandStyleCategory to gothicStyleOption
- ))
+ val newStyle = UserStyle(
+ hashMapOf(
+ colorStyleCategory to greenStyleOption,
+ watchHandStyleCategory to gothicStyleOption
+ )
+ )
userStyleRepository.userStyle = newStyle
@@ -135,7 +139,7 @@
fun defaultValues() {
val watchHandLengthOption =
userStyleRepository.userStyle.options[watchHandLengthStyleCategory]!! as
- DoubleRangeUserStyleCategory.DoubleRangeOption
+ DoubleRangeUserStyleCategory.DoubleRangeOption
assertThat(watchHandLengthOption.value).isEqualTo(0.75)
}
}
diff --git a/wear/wear-watchface/api/current.txt b/wear/wear-watchface/api/current.txt
index 0c9210d..17568e4 100644
--- a/wear/wear-watchface/api/current.txt
+++ b/wear/wear-watchface/api/current.txt
@@ -2,18 +2,18 @@
package androidx.wear.watchface {
public class CanvasComplicationDrawableRenderer implements androidx.wear.watchface.CanvasComplicationRenderer {
- ctor public CanvasComplicationDrawableRenderer(androidx.wear.complications.rendering.ComplicationDrawable drawable, androidx.wear.watchface.WatchState watchState);
+ ctor public CanvasComplicationDrawableRenderer(androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable, androidx.wear.watchface.WatchState watchState);
method public void drawHighlight(android.graphics.Canvas canvas, android.graphics.Rect bounds, android.icu.util.Calendar calendar);
method public android.support.wearable.complications.ComplicationData? getData();
- method public final androidx.wear.complications.rendering.ComplicationDrawable getDrawable();
+ method public final androidx.wear.watchface.complications.rendering.ComplicationDrawable getDrawable();
method public void onAttach(androidx.wear.watchface.Complication complication);
method public void onDetach();
method public void render(android.graphics.Canvas canvas, android.graphics.Rect bounds, android.icu.util.Calendar calendar, androidx.wear.watchface.RenderParameters renderParameters);
method public void setData(android.support.wearable.complications.ComplicationData? data);
- method public final void setDrawable(androidx.wear.complications.rendering.ComplicationDrawable value);
+ method public final void setDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable value);
method public void setInvalidateCallback(androidx.wear.watchface.CanvasComplicationRenderer.InvalidateCallback callback);
method public void setIsHighlighted(boolean highlight);
- property public final androidx.wear.complications.rendering.ComplicationDrawable drawable;
+ property public final androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable;
}
public interface CanvasComplicationRenderer {
@@ -36,37 +36,35 @@
}
public final class Complication {
+ method @UiThread public androidx.wear.complications.DefaultComplicationProviderPolicy getDefaultProviderPolicy();
+ method @UiThread public int getDefaultProviderType();
method @UiThread public androidx.wear.watchface.CanvasComplicationRenderer getRenderer();
+ method @UiThread public int[] getSupportedTypes();
method @UiThread public android.graphics.RectF getUnitSquareBounds();
method @UiThread public boolean isEnabled();
method @UiThread public void render(android.graphics.Canvas canvas, android.icu.util.Calendar calendar, androidx.wear.watchface.RenderParameters renderParameters);
+ method @UiThread public void setDefaultProviderPolicy(androidx.wear.complications.DefaultComplicationProviderPolicy value);
+ method @UiThread public void setDefaultProviderType(int value);
method @UiThread public void setEnabled(boolean value);
method @UiThread public void setRenderer(androidx.wear.watchface.CanvasComplicationRenderer value);
+ method @UiThread public void setSupportedTypes(int[] value);
method @UiThread public void setUnitSquareBounds(android.graphics.RectF value);
+ property @UiThread public final androidx.wear.complications.DefaultComplicationProviderPolicy defaultProviderPolicy;
+ property @UiThread public final int defaultProviderType;
property @UiThread public final boolean enabled;
property @UiThread public final androidx.wear.watchface.CanvasComplicationRenderer renderer;
+ property @UiThread public final int[] supportedTypes;
property @UiThread public final android.graphics.RectF unitSquareBounds;
}
public static final class Complication.Builder {
- ctor public Complication.Builder(int id, androidx.wear.watchface.CanvasComplicationRenderer renderer, int[] supportedTypes, androidx.wear.watchface.Complication.DefaultComplicationProviderPolicy defaultProviderPolicy);
+ ctor public Complication.Builder(int id, androidx.wear.watchface.CanvasComplicationRenderer renderer, int[] supportedTypes, androidx.wear.complications.DefaultComplicationProviderPolicy defaultProviderPolicy);
method public androidx.wear.watchface.Complication build();
method public androidx.wear.watchface.Complication.Builder setBackgroundComplication();
method public androidx.wear.watchface.Complication.Builder setDefaultProviderType(int defaultProviderType);
method public androidx.wear.watchface.Complication.Builder setUnitSquareBounds(android.graphics.RectF unitSquareBounds);
}
- public static final class Complication.DefaultComplicationProviderPolicy {
- ctor public Complication.DefaultComplicationProviderPolicy(java.util.List<android.content.ComponentName> providers, int systemProviderFallback);
- ctor public Complication.DefaultComplicationProviderPolicy();
- ctor public Complication.DefaultComplicationProviderPolicy(int systemProviderFallback);
- method public java.util.List<android.content.ComponentName> getProviders();
- method public int getSystemProviderFallback();
- method public boolean isEmpty();
- property public final java.util.List<android.content.ComponentName> providers;
- property public final int systemProviderFallback;
- }
-
public final class ComplicationOutlineRenderer {
ctor public ComplicationOutlineRenderer();
method public static void drawComplicationSelectOutline(android.graphics.Canvas canvas, android.graphics.Rect bounds);
@@ -78,8 +76,7 @@
}
public final class ComplicationsManager {
- ctor public ComplicationsManager(java.util.Collection<androidx.wear.watchface.Complication> complicationCollection);
- ctor @VisibleForTesting public ComplicationsManager(java.util.Collection<androidx.wear.watchface.Complication> complicationCollection, androidx.wear.watchface.Renderer renderer);
+ ctor public ComplicationsManager(java.util.Collection<androidx.wear.watchface.Complication> complicationCollection, androidx.wear.watchface.style.UserStyleRepository userStyleRepository);
method @UiThread public void addTapListener(androidx.wear.watchface.ComplicationsManager.TapListener tapListener);
method @UiThread public void bringAttentionToComplication(int complicationId);
method public operator androidx.wear.watchface.Complication? get(int id);
diff --git a/wear/wear-watchface/api/public_plus_experimental_current.txt b/wear/wear-watchface/api/public_plus_experimental_current.txt
index e8e9290..c32c39b 100644
--- a/wear/wear-watchface/api/public_plus_experimental_current.txt
+++ b/wear/wear-watchface/api/public_plus_experimental_current.txt
@@ -2,18 +2,18 @@
package androidx.wear.watchface {
public class CanvasComplicationDrawableRenderer implements androidx.wear.watchface.CanvasComplicationRenderer {
- ctor public CanvasComplicationDrawableRenderer(androidx.wear.complications.rendering.ComplicationDrawable drawable, androidx.wear.watchface.WatchState watchState);
+ ctor public CanvasComplicationDrawableRenderer(androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable, androidx.wear.watchface.WatchState watchState);
method public void drawHighlight(android.graphics.Canvas canvas, android.graphics.Rect bounds, android.icu.util.Calendar calendar);
method public android.support.wearable.complications.ComplicationData? getData();
- method public final androidx.wear.complications.rendering.ComplicationDrawable getDrawable();
+ method public final androidx.wear.watchface.complications.rendering.ComplicationDrawable getDrawable();
method public void onAttach(androidx.wear.watchface.Complication complication);
method public void onDetach();
method public void render(android.graphics.Canvas canvas, android.graphics.Rect bounds, android.icu.util.Calendar calendar, androidx.wear.watchface.RenderParameters renderParameters);
method public void setData(android.support.wearable.complications.ComplicationData? data);
- method public final void setDrawable(androidx.wear.complications.rendering.ComplicationDrawable value);
+ method public final void setDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable value);
method public void setInvalidateCallback(androidx.wear.watchface.CanvasComplicationRenderer.InvalidateCallback callback);
method public void setIsHighlighted(boolean highlight);
- property public final androidx.wear.complications.rendering.ComplicationDrawable drawable;
+ property public final androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable;
}
public interface CanvasComplicationRenderer {
@@ -36,37 +36,35 @@
}
public final class Complication {
+ method @UiThread public androidx.wear.complications.DefaultComplicationProviderPolicy getDefaultProviderPolicy();
+ method @UiThread public int getDefaultProviderType();
method @UiThread public androidx.wear.watchface.CanvasComplicationRenderer getRenderer();
+ method @UiThread public int[] getSupportedTypes();
method @UiThread public android.graphics.RectF getUnitSquareBounds();
method @UiThread public boolean isEnabled();
method @UiThread public void render(android.graphics.Canvas canvas, android.icu.util.Calendar calendar, androidx.wear.watchface.RenderParameters renderParameters);
+ method @UiThread public void setDefaultProviderPolicy(androidx.wear.complications.DefaultComplicationProviderPolicy value);
+ method @UiThread public void setDefaultProviderType(int value);
method @UiThread public void setEnabled(boolean value);
method @UiThread public void setRenderer(androidx.wear.watchface.CanvasComplicationRenderer value);
+ method @UiThread public void setSupportedTypes(int[] value);
method @UiThread public void setUnitSquareBounds(android.graphics.RectF value);
+ property @UiThread public final androidx.wear.complications.DefaultComplicationProviderPolicy defaultProviderPolicy;
+ property @UiThread public final int defaultProviderType;
property @UiThread public final boolean enabled;
property @UiThread public final androidx.wear.watchface.CanvasComplicationRenderer renderer;
+ property @UiThread public final int[] supportedTypes;
property @UiThread public final android.graphics.RectF unitSquareBounds;
}
public static final class Complication.Builder {
- ctor public Complication.Builder(int id, androidx.wear.watchface.CanvasComplicationRenderer renderer, int[] supportedTypes, androidx.wear.watchface.Complication.DefaultComplicationProviderPolicy defaultProviderPolicy);
+ ctor public Complication.Builder(int id, androidx.wear.watchface.CanvasComplicationRenderer renderer, int[] supportedTypes, androidx.wear.complications.DefaultComplicationProviderPolicy defaultProviderPolicy);
method public androidx.wear.watchface.Complication build();
method public androidx.wear.watchface.Complication.Builder setBackgroundComplication();
- method public androidx.wear.watchface.Complication.Builder setDefaultProviderType(int defaultProviderType);
+ method public androidx.wear.watchface.Complication.Builder setDefaultProviderType(@android.support.wearable.complications.ComplicationData.ComplicationType int defaultProviderType);
method public androidx.wear.watchface.Complication.Builder setUnitSquareBounds(android.graphics.RectF unitSquareBounds);
}
- public static final class Complication.DefaultComplicationProviderPolicy {
- ctor public Complication.DefaultComplicationProviderPolicy(java.util.List<android.content.ComponentName> providers, @androidx.wear.complications.SystemProviders.ProviderId int systemProviderFallback);
- ctor public Complication.DefaultComplicationProviderPolicy();
- ctor public Complication.DefaultComplicationProviderPolicy(int systemProviderFallback);
- method public java.util.List<android.content.ComponentName> getProviders();
- method public int getSystemProviderFallback();
- method public boolean isEmpty();
- property public final java.util.List<android.content.ComponentName> providers;
- property public final int systemProviderFallback;
- }
-
public final class ComplicationOutlineRenderer {
ctor public ComplicationOutlineRenderer();
method public static void drawComplicationSelectOutline(android.graphics.Canvas canvas, android.graphics.Rect bounds);
@@ -78,8 +76,7 @@
}
public final class ComplicationsManager {
- ctor public ComplicationsManager(java.util.Collection<androidx.wear.watchface.Complication> complicationCollection);
- ctor @VisibleForTesting public ComplicationsManager(java.util.Collection<androidx.wear.watchface.Complication> complicationCollection, androidx.wear.watchface.Renderer renderer);
+ ctor public ComplicationsManager(java.util.Collection<androidx.wear.watchface.Complication> complicationCollection, androidx.wear.watchface.style.UserStyleRepository userStyleRepository);
method @UiThread public void addTapListener(androidx.wear.watchface.ComplicationsManager.TapListener tapListener);
method @UiThread public void bringAttentionToComplication(int complicationId);
method public operator androidx.wear.watchface.Complication? get(int id);
diff --git a/wear/wear-watchface/api/restricted_current.txt b/wear/wear-watchface/api/restricted_current.txt
index e3523ad..b6d9446 100644
--- a/wear/wear-watchface/api/restricted_current.txt
+++ b/wear/wear-watchface/api/restricted_current.txt
@@ -2,18 +2,18 @@
package androidx.wear.watchface {
public class CanvasComplicationDrawableRenderer implements androidx.wear.watchface.CanvasComplicationRenderer {
- ctor public CanvasComplicationDrawableRenderer(androidx.wear.complications.rendering.ComplicationDrawable drawable, androidx.wear.watchface.WatchState watchState);
+ ctor public CanvasComplicationDrawableRenderer(androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable, androidx.wear.watchface.WatchState watchState);
method public void drawHighlight(android.graphics.Canvas canvas, android.graphics.Rect bounds, android.icu.util.Calendar calendar);
method public android.support.wearable.complications.ComplicationData? getData();
- method public final androidx.wear.complications.rendering.ComplicationDrawable getDrawable();
+ method public final androidx.wear.watchface.complications.rendering.ComplicationDrawable getDrawable();
method public void onAttach(androidx.wear.watchface.Complication complication);
method public void onDetach();
method public void render(android.graphics.Canvas canvas, android.graphics.Rect bounds, android.icu.util.Calendar calendar, androidx.wear.watchface.RenderParameters renderParameters);
method public void setData(android.support.wearable.complications.ComplicationData? data);
- method public final void setDrawable(androidx.wear.complications.rendering.ComplicationDrawable value);
+ method public final void setDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable value);
method public void setInvalidateCallback(androidx.wear.watchface.CanvasComplicationRenderer.InvalidateCallback callback);
method public void setIsHighlighted(boolean highlight);
- property public final androidx.wear.complications.rendering.ComplicationDrawable drawable;
+ property public final androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable;
}
public interface CanvasComplicationRenderer {
@@ -36,37 +36,35 @@
}
public final class Complication {
+ method @UiThread public androidx.wear.complications.DefaultComplicationProviderPolicy getDefaultProviderPolicy();
+ method @UiThread public int getDefaultProviderType();
method @UiThread public androidx.wear.watchface.CanvasComplicationRenderer getRenderer();
+ method @UiThread public int[] getSupportedTypes();
method @UiThread public android.graphics.RectF getUnitSquareBounds();
method @UiThread public boolean isEnabled();
method @UiThread public void render(android.graphics.Canvas canvas, android.icu.util.Calendar calendar, androidx.wear.watchface.RenderParameters renderParameters);
+ method @UiThread public void setDefaultProviderPolicy(androidx.wear.complications.DefaultComplicationProviderPolicy value);
+ method @UiThread public void setDefaultProviderType(int value);
method @UiThread public void setEnabled(boolean value);
method @UiThread public void setRenderer(androidx.wear.watchface.CanvasComplicationRenderer value);
+ method @UiThread public void setSupportedTypes(int[] value);
method @UiThread public void setUnitSquareBounds(android.graphics.RectF value);
+ property @UiThread public final androidx.wear.complications.DefaultComplicationProviderPolicy defaultProviderPolicy;
+ property @UiThread public final int defaultProviderType;
property @UiThread public final boolean enabled;
property @UiThread public final androidx.wear.watchface.CanvasComplicationRenderer renderer;
+ property @UiThread public final int[] supportedTypes;
property @UiThread public final android.graphics.RectF unitSquareBounds;
}
public static final class Complication.Builder {
- ctor public Complication.Builder(int id, androidx.wear.watchface.CanvasComplicationRenderer renderer, int[] supportedTypes, androidx.wear.watchface.Complication.DefaultComplicationProviderPolicy defaultProviderPolicy);
+ ctor public Complication.Builder(int id, androidx.wear.watchface.CanvasComplicationRenderer renderer, int[] supportedTypes, androidx.wear.complications.DefaultComplicationProviderPolicy defaultProviderPolicy);
method public androidx.wear.watchface.Complication build();
method public androidx.wear.watchface.Complication.Builder setBackgroundComplication();
- method public androidx.wear.watchface.Complication.Builder setDefaultProviderType(int defaultProviderType);
+ method public androidx.wear.watchface.Complication.Builder setDefaultProviderType(@android.support.wearable.complications.ComplicationData.ComplicationType int defaultProviderType);
method public androidx.wear.watchface.Complication.Builder setUnitSquareBounds(android.graphics.RectF unitSquareBounds);
}
- public static final class Complication.DefaultComplicationProviderPolicy {
- ctor public Complication.DefaultComplicationProviderPolicy(java.util.List<android.content.ComponentName> providers, @androidx.wear.complications.SystemProviders.ProviderId int systemProviderFallback);
- ctor public Complication.DefaultComplicationProviderPolicy();
- ctor public Complication.DefaultComplicationProviderPolicy(int systemProviderFallback);
- method public java.util.List<android.content.ComponentName> getProviders();
- method public int getSystemProviderFallback();
- method public boolean isEmpty();
- property public final java.util.List<android.content.ComponentName> providers;
- property public final int systemProviderFallback;
- }
-
public final class ComplicationOutlineRenderer {
ctor public ComplicationOutlineRenderer();
method public static void drawComplicationSelectOutline(android.graphics.Canvas canvas, android.graphics.Rect bounds);
@@ -78,8 +76,7 @@
}
public final class ComplicationsManager {
- ctor public ComplicationsManager(java.util.Collection<androidx.wear.watchface.Complication> complicationCollection);
- ctor @VisibleForTesting public ComplicationsManager(java.util.Collection<androidx.wear.watchface.Complication> complicationCollection, androidx.wear.watchface.Renderer renderer);
+ ctor public ComplicationsManager(java.util.Collection<androidx.wear.watchface.Complication> complicationCollection, androidx.wear.watchface.style.UserStyleRepository userStyleRepository);
method @UiThread public void addTapListener(androidx.wear.watchface.ComplicationsManager.TapListener tapListener);
method @UiThread public void bringAttentionToComplication(int complicationId);
method public operator androidx.wear.watchface.Complication? get(int id);
diff --git a/wear/wear-watchface/build.gradle b/wear/wear-watchface/build.gradle
index 1a55813..a5950bf 100644
--- a/wear/wear-watchface/build.gradle
+++ b/wear/wear-watchface/build.gradle
@@ -30,7 +30,7 @@
dependencies {
api("androidx.annotation:annotation:1.1.0")
api(project(":wear:wear-complications-data"))
- api(project(":wear:wear-complications-rendering"))
+ api(project(":wear:wear-watchface-complications-rendering"))
api(project(":wear:wear-watchface-data"))
api(project(":wear:wear-watchface-style"))
api(KOTLIN_STDLIB)
diff --git a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasWatchFaceService.kt b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasWatchFaceService.kt
index 1c2c187..04c968d 100644
--- a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasWatchFaceService.kt
+++ b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasWatchFaceService.kt
@@ -27,6 +27,7 @@
import android.icu.util.Calendar
import android.support.wearable.complications.ComplicationData
import android.view.SurfaceHolder
+import androidx.wear.complications.DefaultComplicationProviderPolicy
import androidx.wear.complications.SystemProviders
import androidx.wear.watchface.CanvasRenderer
import androidx.wear.watchface.CanvasType
@@ -40,6 +41,8 @@
import androidx.wear.watchface.WatchFaceType
import androidx.wear.watchface.WatchState
import androidx.wear.watchface.style.BooleanUserStyleCategory
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride
import androidx.wear.watchface.style.DoubleRangeUserStyleCategory
import androidx.wear.watchface.style.Layer
import androidx.wear.watchface.style.ListUserStyleCategory
@@ -117,31 +120,55 @@
0.75,
listOf(Layer.TOP_LAYER)
)
- val complicationsStyleCategory = ListUserStyleCategory(
+ val complicationsStyleCategory = ComplicationsUserStyleCategory(
"complications_style_category",
"Complications",
"Number and position",
icon = null,
- options = listOf(
- ListUserStyleCategory.ListOption(
+ complicationConfig = listOf(
+ ComplicationsUserStyleCategory.ComplicationsOption(
LEFT_AND_RIGHT_COMPLICATIONS,
"Both",
- null
+ null,
+ listOf(
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID)
+ .setEnabled(true).build(),
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID)
+ .setEnabled(true).build()
+ )
),
- ListUserStyleCategory.ListOption(
+ ComplicationsUserStyleCategory.ComplicationsOption(
NO_COMPLICATIONS,
"None",
- null
+ null,
+ listOf(
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID)
+ .setEnabled(false).build(),
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID)
+ .setEnabled(false).build()
+ )
),
- ListUserStyleCategory.ListOption(
+ ComplicationsUserStyleCategory.ComplicationsOption(
LEFT_COMPLICATION,
"Left",
- null
+ null,
+ listOf(
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID)
+ .setEnabled(true).build(),
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID)
+ .setEnabled(true).build()
+ )
),
- ListUserStyleCategory.ListOption(
+ ComplicationsUserStyleCategory.ComplicationsOption(
RIGHT_COMPLICATION,
"Right",
- null
+ null,
+ listOf(
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID)
+ .setEnabled(true).build(),
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID)
+ .setEnabled(false).build()
+ )
)
),
listOf(Layer.COMPLICATIONS)
@@ -166,7 +193,7 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
+ DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
).setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
.setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.build(),
@@ -180,11 +207,12 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.STEP_COUNT)
+ DefaultComplicationProviderPolicy(SystemProviders.STEP_COUNT)
).setUnitSquareBounds(RectF(0.6f, 0.4f, 0.8f, 0.6f))
.setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.build()
- )
+ ),
+ userStyleRepository
)
val renderer = ExampleCanvasRenderer(
surfaceHolder,
@@ -195,7 +223,6 @@
colorStyleCategory,
drawHourPipsStyleCategory,
watchHandLengthStyleCategory,
- complicationsStyleCategory,
complicationSlots
)
@@ -224,7 +251,6 @@
private val colorStyleCategory: ListUserStyleCategory,
private val drawPipsStyleCategory: BooleanUserStyleCategory,
private val watchHandLengthStyleCategoryDouble: DoubleRangeUserStyleCategory,
- private val complicationsCategory: ListUserStyleCategory,
private val complicationsManager: ComplicationsManager
) : CanvasRenderer(surfaceHolder, userStyleRepository, watchState, CanvasType.HARDWARE) {
@@ -281,36 +307,10 @@
.BooleanOption
val watchHandLengthOption =
userStyle.options[watchHandLengthStyleCategoryDouble]!! as
- DoubleRangeUserStyleCategory.DoubleRangeOption
+ DoubleRangeUserStyleCategory.DoubleRangeOption
drawHourPips = drawPipsOption.value
watchHandScale = watchHandLengthOption.value.toFloat()
-
- val leftComplication =
- complicationsManager.complications[
- EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID]!!
- val rightComplication =
- complicationsManager.complications[
- EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID]!!
-
- when (userStyle.options[complicationsCategory]!!.id) {
- NO_COMPLICATIONS -> {
- leftComplication.enabled = false
- rightComplication.enabled = false
- }
- LEFT_COMPLICATION -> {
- leftComplication.enabled = true
- rightComplication.enabled = false
- }
- RIGHT_COMPLICATION -> {
- leftComplication.enabled = false
- rightComplication.enabled = true
- }
- LEFT_AND_RIGHT_COMPLICATIONS -> {
- leftComplication.enabled = true
- rightComplication.enabled = true
- }
- }
}
}
)
@@ -334,7 +334,8 @@
if (renderParameters.drawMode != DrawMode.AMBIENT &&
renderParameters.layerParameters[Layer.BASE_LAYER] != LayerMode.HIDE &&
- drawHourPips) {
+ drawHourPips
+ ) {
drawNumberStyleOuterElement(canvas, bounds, style)
}
}
@@ -349,7 +350,7 @@
val hours = calendar.get(Calendar.HOUR).toFloat()
val minutes = calendar.get(Calendar.MINUTE).toFloat()
val seconds = calendar.get(Calendar.SECOND).toFloat() +
- (calendar.get(Calendar.MILLISECOND).toFloat() / 1000f)
+ (calendar.get(Calendar.MILLISECOND).toFloat() / 1000f)
val hourRot = (hours + minutes / 60.0f + seconds / 3600.0f) / 12.0f * 360.0f
val minuteRot = (minutes + seconds / 60.0f) / 60.0f * 360.0f
diff --git a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
index d48bea0..af9f918 100644
--- a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
+++ b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
@@ -27,6 +27,7 @@
import android.util.Log
import android.view.Gravity
import android.view.SurfaceHolder
+import androidx.wear.complications.DefaultComplicationProviderPolicy
import androidx.wear.complications.SystemProviders
import androidx.wear.watchface.Complication
import androidx.wear.watchface.ComplicationsManager
@@ -109,11 +110,12 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
+ DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
).setUnitSquareBounds(RectF(0.2f, 0.7f, 0.4f, 0.9f))
.setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.build()
- )
+ ),
+ userStyleRepository
)
val renderer = ExampleOpenGLRenderer(
surfaceHolder,
@@ -221,7 +223,8 @@
createHand(
coloredTriangleProgram,
0.02f /* width */,
- 1.0f /* height */, floatArrayOf(
+ 1.0f /* height */,
+ floatArrayOf(
1.0f /* red */,
0.0f /* green */,
0.0f /* blue */,
@@ -232,7 +235,8 @@
createHand(
coloredTriangleProgram,
0.02f /* width */,
- 1.0f /* height */, floatArrayOf(
+ 1.0f /* height */,
+ floatArrayOf(
0.0f /* red */,
1.0f /* green */,
0.0f /* blue */,
@@ -243,7 +247,8 @@
minuteHandTriangle = createHand(
coloredTriangleProgram,
0.06f /* width */,
- 1f /* height */, floatArrayOf(
+ 1f /* height */,
+ floatArrayOf(
0.7f /* red */,
0.7f /* green */,
0.7f /* blue */,
@@ -253,7 +258,8 @@
hourHandTriangle = createHand(
coloredTriangleProgram,
0.1f /* width */,
- 0.6f /* height */, floatArrayOf(
+ 0.6f /* height */,
+ floatArrayOf(
0.9f /* red */,
0.9f /* green */,
0.9f /* blue */,
@@ -381,7 +387,8 @@
)
}
return Gles2ColoredTriangleList(
- program, trianglesCoords, floatArrayOf(
+ program, trianglesCoords,
+ floatArrayOf(
1.0f /* red */,
1.0f /* green */,
1.0f /* blue */,
@@ -417,7 +424,8 @@
index += 9
}
return Gles2ColoredTriangleList(
- program, trianglesCoords, floatArrayOf(
+ program, trianglesCoords,
+ floatArrayOf(
0.5f /* red */,
0.5f /* green */,
0.5f /* blue */,
@@ -618,7 +626,8 @@
0
)
secondHandTriangleMap[
- userStyleRepository.userStyle.options[colorStyleCategory]!!.id]
+ userStyleRepository.userStyle.options[colorStyleCategory]!!.id
+ ]
?.draw(mvpMatrix)
}
}
@@ -928,8 +937,10 @@
("must be multiple of VERTICE_PER_TRIANGLE * COORDS_PER_VERTEX coordinates")
}
require(textureCoords.size % (VERTICE_PER_TRIANGLE * TEXTURE_COORDS_PER_VERTEX) == 0) {
- ("must be multiple of VERTICE_PER_TRIANGLE * NUM_TEXTURE_COMPONENTS texture " +
- "coordinates")
+ (
+ "must be multiple of VERTICE_PER_TRIANGLE * NUM_TEXTURE_COMPONENTS texture " +
+ "coordinates"
+ )
}
}
diff --git a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt
index ff00812..61ece1f 100644
--- a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt
+++ b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt
@@ -25,8 +25,9 @@
import android.support.wearable.complications.ComplicationData
import android.view.SurfaceHolder
import androidx.annotation.Sampled
+import androidx.wear.complications.DefaultComplicationProviderPolicy
import androidx.wear.complications.SystemProviders
-import androidx.wear.complications.rendering.ComplicationDrawable
+import androidx.wear.watchface.complications.rendering.ComplicationDrawable
import androidx.wear.watchface.CanvasRenderer
import androidx.wear.watchface.CanvasType
import androidx.wear.watchface.Complication
@@ -114,7 +115,7 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
+ DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
).setUnitSquareBounds(RectF(0.15625f, 0.1875f, 0.84375f, 0.3125f))
.setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.build(),
@@ -131,11 +132,12 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.STEP_COUNT)
+ DefaultComplicationProviderPolicy(SystemProviders.STEP_COUNT)
).setUnitSquareBounds(RectF(0.1f, 0.5625f, 0.35f, 0.8125f))
.setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.build()
- )
+ ),
+ userStyleRepository
)
val renderer = object : CanvasRenderer(
@@ -176,4 +178,4 @@
}
return ExampleCanvasWatchFaceService()
-}
\ No newline at end of file
+}
diff --git a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/Style.kt b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/Style.kt
index cbe229f..47831ad 100644
--- a/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/Style.kt
+++ b/wear/wear-watchface/samples/src/main/java/androidx/wear/watchface/samples/Style.kt
@@ -18,7 +18,7 @@
import android.content.Context
import android.graphics.Color
-import androidx.wear.complications.rendering.ComplicationDrawable
+import androidx.wear.watchface.complications.rendering.ComplicationDrawable
import androidx.wear.watchface.CanvasComplicationDrawableRenderer
import androidx.wear.watchface.WatchState
diff --git a/wear/wear-watchface/samples/src/main/res/drawable/complication_green_style.xml b/wear/wear-watchface/samples/src/main/res/drawable/complication_green_style.xml
index 96e1e01..4083117 100644
--- a/wear/wear-watchface/samples/src/main/res/drawable/complication_green_style.xml
+++ b/wear/wear-watchface/samples/src/main/res/drawable/complication_green_style.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<androidx.wear.complications.rendering.ComplicationDrawable
+<androidx.wear.watchface.complications.rendering.ComplicationDrawable
xmlns:app="http://schemas.android.com/apk/res-auto"
app:borderColor="@color/light_green_50"
app:borderStyle="solid"
@@ -35,4 +35,4 @@
app:rangedValuePrimaryColor="@color/white"
app:rangedValueSecondaryColor="@color/transparent"
/>
-</androidx.wear.complications.rendering.ComplicationDrawable>
+</androidx.wear.watchface.complications.rendering.ComplicationDrawable>
diff --git a/wear/wear-watchface/samples/src/main/res/drawable/complication_red_style.xml b/wear/wear-watchface/samples/src/main/res/drawable/complication_red_style.xml
index 4794911..72c9916 100644
--- a/wear/wear-watchface/samples/src/main/res/drawable/complication_red_style.xml
+++ b/wear/wear-watchface/samples/src/main/res/drawable/complication_red_style.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<androidx.wear.complications.rendering.ComplicationDrawable
+<androidx.wear.watchface.complications.rendering.ComplicationDrawable
xmlns:app="http://schemas.android.com/apk/res-auto"
app:backgroundColor="@color/black_40"
app:borderStyle="none"
@@ -36,4 +36,4 @@
app:rangedValuePrimaryColor="@color/white"
app:rangedValueSecondaryColor="@color/transparent"
/>
-</androidx.wear.complications.rendering.ComplicationDrawable>
+</androidx.wear.watchface.complications.rendering.ComplicationDrawable>
diff --git a/wear/wear-watchface/samples/src/main/res/drawable/complication_white_style.xml b/wear/wear-watchface/samples/src/main/res/drawable/complication_white_style.xml
index 8b5e51f..d96c8d2 100644
--- a/wear/wear-watchface/samples/src/main/res/drawable/complication_white_style.xml
+++ b/wear/wear-watchface/samples/src/main/res/drawable/complication_white_style.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<androidx.wear.complications.rendering.ComplicationDrawable
+<androidx.wear.watchface.complications.rendering.ComplicationDrawable
xmlns:app="http://schemas.android.com/apk/res-auto"
app:backgroundColor="@color/black"
app:borderColor="@color/white_90"
@@ -37,4 +37,4 @@
app:rangedValuePrimaryColor="@color/white"
app:rangedValueSecondaryColor="@color/transparent"
/>
-</androidx.wear.complications.rendering.ComplicationDrawable>
+</androidx.wear.watchface.complications.rendering.ComplicationDrawable>
diff --git a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestCanvasWatchFaceService.kt b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestCanvasWatchFaceService.kt
index 17a6c2e..62796b4 100644
--- a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestCanvasWatchFaceService.kt
+++ b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestCanvasWatchFaceService.kt
@@ -22,6 +22,7 @@
import android.os.Handler
import android.support.wearable.complications.ComplicationData
import android.view.SurfaceHolder
+import androidx.wear.complications.DefaultComplicationProviderPolicy
import androidx.wear.complications.SystemProviders
import androidx.wear.watchface.Complication
import androidx.wear.watchface.ComplicationsManager
@@ -41,6 +42,9 @@
import androidx.wear.watchface.samples.RIGHT_COMPLICATION
import androidx.wear.watchface.samples.WatchFaceColorStyle
import androidx.wear.watchface.style.BooleanUserStyleCategory
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationsOption
import androidx.wear.watchface.style.DoubleRangeUserStyleCategory
import androidx.wear.watchface.style.Layer
import androidx.wear.watchface.style.ListUserStyleCategory
@@ -109,31 +113,55 @@
1.0,
listOf(Layer.TOP_LAYER)
)
- val complicationsStyleCategory = ListUserStyleCategory(
+ val complicationsStyleCategory = ComplicationsUserStyleCategory(
"complications_style_category",
"Complications",
"Number and position",
icon = null,
- options = listOf(
- ListUserStyleCategory.ListOption(
+ complicationConfig = listOf(
+ ComplicationsOption(
LEFT_AND_RIGHT_COMPLICATIONS,
"Both",
- null
+ null,
+ listOf(
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID)
+ .setEnabled(true).build(),
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID)
+ .setEnabled(true).build()
+ )
),
- ListUserStyleCategory.ListOption(
+ ComplicationsOption(
NO_COMPLICATIONS,
"None",
- null
+ null,
+ listOf(
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID)
+ .setEnabled(false).build(),
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID)
+ .setEnabled(false).build()
+ )
),
- ListUserStyleCategory.ListOption(
+ ComplicationsOption(
LEFT_COMPLICATION,
"Left",
- null
+ null,
+ listOf(
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID)
+ .setEnabled(true).build(),
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID)
+ .setEnabled(true).build()
+ )
),
- ListUserStyleCategory.ListOption(
+ ComplicationsOption(
RIGHT_COMPLICATION,
"Right",
- null
+ null,
+ listOf(
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID)
+ .setEnabled(true).build(),
+ ComplicationOverride.Builder(EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID)
+ .setEnabled(false).build()
+ )
)
),
listOf(Layer.COMPLICATIONS)
@@ -158,7 +186,7 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
+ DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
).setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
.setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.build(),
@@ -172,11 +200,12 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.STEP_COUNT)
+ DefaultComplicationProviderPolicy(SystemProviders.STEP_COUNT)
).setUnitSquareBounds(RectF(0.6f, 0.4f, 0.8f, 0.6f))
.setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.build()
- )
+ ),
+ userStyleRepository
)
val renderer = ExampleCanvasRenderer(
surfaceHolder,
@@ -187,7 +216,6 @@
colorStyleCategory,
drawHourPipsStyleCategory,
watchHandLengthStyleCategory,
- complicationsStyleCategory,
complicationSlots
)
diff --git a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestGlesWatchFaceService.kt b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestGlesWatchFaceService.kt
index e9fa057..9958765 100644
--- a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestGlesWatchFaceService.kt
+++ b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/TestGlesWatchFaceService.kt
@@ -22,6 +22,7 @@
import android.os.Handler
import android.support.wearable.complications.ComplicationData
import android.view.SurfaceHolder
+import androidx.wear.complications.DefaultComplicationProviderPolicy
import androidx.wear.complications.SystemProviders
import androidx.wear.watchface.Complication
import androidx.wear.watchface.ComplicationsManager
@@ -95,11 +96,12 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
+ DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
).setUnitSquareBounds(RectF(0.2f, 0.7f, 0.4f, 0.9f))
.setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.build()
- )
+ ),
+ userStyleRepository
)
val renderer = ExampleOpenGLRenderer(
surfaceHolder,
diff --git a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceControlServiceTest.kt b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceControlServiceTest.kt
index a023da8..9bf79c8 100644
--- a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceControlServiceTest.kt
+++ b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceControlServiceTest.kt
@@ -37,6 +37,7 @@
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import java.util.concurrent.CountDownLatch
private const val API_VERSION = 3
@@ -74,7 +75,9 @@
ExampleCanvasWatchFaceService::class.java
)
)
- val watchFaceService = WatchFaceServiceStub(API_VERSION, complicationProviders)
+ val activeComplicationsLatch = CountDownLatch(1)
+ val watchFaceService =
+ WatchFaceServiceStub(API_VERSION, complicationProviders, activeComplicationsLatch)
instance.initWithoutSurface(
watchFaceService,
ImmutableSystemState(false, false),
@@ -86,6 +89,7 @@
RenderParameters(DrawMode.INTERACTIVE, RenderParameters.DRAW_ALL_LAYERS).toWireFormat(),
100,
1234567890,
+ null,
null
).ashmemCompressedImageBundleToBitmap()
diff --git a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
index 8de39e5..a252cff 100644
--- a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
+++ b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
@@ -46,8 +46,10 @@
import androidx.wear.watchface.RenderParameters
import androidx.wear.watchface.WatchFaceService
import androidx.wear.watchface.data.ComplicationDetails
+import androidx.wear.watchface.data.IdAndComplicationData
import androidx.wear.watchface.data.SystemState
import androidx.wear.watchface.samples.EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID
+import androidx.wear.watchface.samples.EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID
import androidx.wear.watchface.style.Layer
import androidx.wear.watchface.style.data.UserStyleSchemaWireFormat
import androidx.wear.watchface.style.data.UserStyleWireFormat
@@ -68,7 +70,8 @@
internal class WatchFaceServiceStub(
private val apiVersion: Int,
- private val complicationProviders: Map<Int, ComplicationData>
+ private val complicationProviders: Map<Int, ComplicationData>,
+ private val activeComplicationsLatch: CountDownLatch
) : IWatchFaceService.Stub() {
var watchFaceCommand: IWatchFaceCommand? = null
@@ -79,6 +82,7 @@
}
override fun setActiveComplications(ids: IntArray, updateAll: Boolean) {
+ activeComplicationsLatch.countDown()
}
override fun setComplicationDetails(id: Int, complicationDetails: ComplicationDetails) {
@@ -165,6 +169,7 @@
private val bitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Bitmap.Config.ARGB_8888)
private val canvas = Canvas(bitmap)
private val renderDoneLatch = CountDownLatch(1)
+ private var activeComplicationsLatch = CountDownLatch(1)
private val surfaceTexture = SurfaceTexture(false)
@@ -219,7 +224,8 @@
private fun setBinder() {
watchFaceServiceStub = WatchFaceServiceStub(
API_VERSION,
- complicationProviders
+ complicationProviders,
+ activeComplicationsLatch
)
engineWrapper.onCommand(
@@ -273,8 +279,9 @@
@Test
fun testActiveScreenshot() {
+ handler.post(this::initCanvasWatchFace)
+ activeComplicationsLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
handler.post {
- initCanvasWatchFace()
engineWrapper.draw()
}
@@ -284,8 +291,9 @@
@Test
fun testAmbientScreenshot() {
+ handler.post(this::initCanvasWatchFace)
+ activeComplicationsLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
handler.post {
- initCanvasWatchFace()
setAmbient(true)
engineWrapper.draw()
}
@@ -299,12 +307,14 @@
val latch = CountDownLatch(1)
handler.post(this::initCanvasWatchFace)
+ activeComplicationsLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
var bitmap: Bitmap? = null
handler.post {
bitmap = watchFaceServiceStub.watchFaceCommand!!.takeWatchfaceScreenshot(
RenderParameters(DrawMode.AMBIENT, RenderParameters.DRAW_ALL_LAYERS).toWireFormat(),
100,
123456789,
+ null,
null
).ashmemCompressedImageBundleToBitmap()
latch.countDown()
@@ -322,6 +332,7 @@
val latch = CountDownLatch(1)
handler.post(this::initCanvasWatchFace)
+ activeComplicationsLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
var bitmap: Bitmap? = null
handler.post {
bitmap = watchFaceServiceStub.watchFaceCommand!!.takeComplicationScreenshot(
@@ -347,6 +358,7 @@
val latch = CountDownLatch(1)
handler.post(this::initGles2WatchFace)
+ activeComplicationsLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
var bitmap: Bitmap? = null
handler.post {
bitmap = watchFaceServiceStub.watchFaceCommand!!.takeWatchfaceScreenshot(
@@ -354,6 +366,7 @@
.toWireFormat(),
100,
123456789,
+ null,
null
).ashmemCompressedImageBundleToBitmap()!!
latch.countDown()
@@ -371,6 +384,7 @@
val latch = CountDownLatch(1)
handler.post(this::initCanvasWatchFace)
+ activeComplicationsLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
var bitmap: Bitmap? = null
handler.post {
bitmap = watchFaceServiceStub.watchFaceCommand!!.takeComplicationScreenshot(
@@ -396,8 +410,10 @@
// Rendering again with complicationData = null should result in a different image.
val latch2 = CountDownLatch(1)
+ activeComplicationsLatch = CountDownLatch(1)
handler.post(this::initCanvasWatchFace)
+ activeComplicationsLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
var bitmap2: Bitmap? = null
handler.post {
bitmap2 = watchFaceServiceStub.watchFaceCommand!!.takeComplicationScreenshot(
@@ -421,8 +437,9 @@
@Test
fun testSetGreenStyle() {
+ handler.post(this::initCanvasWatchFace)
+ activeComplicationsLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
handler.post {
- initCanvasWatchFace()
watchFaceServiceStub.watchFaceCommand!!.setUserStyle(
UserStyleWireFormat(mapOf("color_style_category" to "green_style"))
)
@@ -438,6 +455,7 @@
val latch = CountDownLatch(1)
handler.post(this::initCanvasWatchFace)
+ activeComplicationsLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
var bitmap: Bitmap? = null
handler.post {
bitmap = watchFaceServiceStub.watchFaceCommand!!.takeWatchfaceScreenshot(
@@ -451,6 +469,7 @@
).toWireFormat(),
100,
123456789,
+ null,
null
).ashmemCompressedImageBundleToBitmap()
latch.countDown()
@@ -462,4 +481,46 @@
"highlight_complications"
)
}
+
+ @Test
+ fun testScreenshotWithPreviewComplicationData() {
+ val latch = CountDownLatch(1)
+ val previewComplicationData = listOf(
+ IdAndComplicationData(
+ EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID,
+ ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
+ .setShortTitle(ComplicationText.plainText("Preview"))
+ .setShortText(ComplicationText.plainText("A"))
+ .build()
+ ),
+ IdAndComplicationData(
+ EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID,
+ ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
+ .setShortTitle(ComplicationText.plainText("Preview"))
+ .setShortText(ComplicationText.plainText("B"))
+ .build()
+ )
+ )
+
+ handler.post(this::initCanvasWatchFace)
+ var bitmap: Bitmap? = null
+ handler.post {
+ bitmap = watchFaceServiceStub.watchFaceCommand!!.takeWatchfaceScreenshot(
+ RenderParameters(
+ DrawMode.INTERACTIVE, RenderParameters.DRAW_ALL_LAYERS
+ ).toWireFormat(),
+ 100,
+ 123456789,
+ previewComplicationData,
+ null
+ ).ashmemCompressedImageBundleToBitmap()
+ latch.countDown()
+ }
+
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)
+ bitmap!!.assertAgainstGolden(
+ screenshotRule,
+ "preview_complications"
+ )
+ }
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/CanvasRenderer.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/CanvasRenderer.kt
index bc0305b..4b7f2d5 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/CanvasRenderer.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/CanvasRenderer.kt
@@ -67,11 +67,13 @@
internal override fun renderInternal(
calendar: Calendar
) {
- val canvas = (if (canvasType == CanvasType.HARDWARE) {
- surfaceHolder.lockHardwareCanvas()
- } else {
- surfaceHolder.lockCanvas()
- }) ?: return
+ val canvas = (
+ if (canvasType == CanvasType.HARDWARE) {
+ surfaceHolder.lockHardwareCanvas()
+ } else {
+ surfaceHolder.lockCanvas()
+ }
+ ) ?: return
try {
if (watchState.isVisible.value) {
render(canvas, surfaceHolder.surfaceFrame, calendar)
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt
index a906dcc..2e6a479 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt
@@ -17,7 +17,6 @@
package androidx.wear.watchface
import android.annotation.SuppressLint
-import android.content.ComponentName
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.RectF
@@ -25,8 +24,8 @@
import android.icu.util.Calendar
import android.support.wearable.complications.ComplicationData
import androidx.annotation.UiThread
-import androidx.wear.complications.SystemProviders
-import androidx.wear.complications.rendering.ComplicationDrawable
+import androidx.wear.complications.DefaultComplicationProviderPolicy
+import androidx.wear.watchface.complications.rendering.ComplicationDrawable
import androidx.wear.watchface.data.ComplicationBoundsType
import androidx.wear.watchface.style.Layer
@@ -122,7 +121,7 @@
_drawable.lowBitAmbient = watchState.hasLowBitAmbient
_drawable.setBurnInProtection(watchState.hasBurnInProtection)
- attachedComplication?.scheduleUpdateActiveComplications()
+ attachedComplication?.scheduleUpdateComplications()
}
private val isAmbientObserver = Observer<Boolean> {
@@ -215,9 +214,9 @@
@ComplicationBoundsType internal val boundsType: Int,
unitSquareBounds: RectF,
renderer: CanvasComplicationRenderer,
- internal val supportedTypes: IntArray,
- internal val defaultProviderPolicy: DefaultComplicationProviderPolicy,
- internal val defaultProviderType: Int
+ supportedTypes: IntArray,
+ defaultProviderPolicy: DefaultComplicationProviderPolicy,
+ defaultProviderType: Int
) {
/** @hide */
private companion object {
@@ -249,8 +248,12 @@
private var defaultProviderType: Int = WatchFace.DEFAULT_PROVIDER_TYPE_NONE
- /** Sets the default complication provider data type. */
- fun setDefaultProviderType(defaultProviderType: Int): Builder {
+ /**
+ * Sets the default complication provider data type. See [ComplicationData.ComplicationType]
+ */
+ fun setDefaultProviderType(
+ @ComplicationData.ComplicationType defaultProviderType: Int
+ ): Builder {
this.defaultProviderType = defaultProviderType
return this
}
@@ -297,66 +300,67 @@
renderer.onAttach(this)
}
- /**
- * A watch face may wish to try and set one or more non-system providers as the default provider
- * for a complication. If a provider can't be used for some reason (e.g. it isn't installed or
- * it doesn't support the requested type, or the watch face lacks the necessary permission)
- * then the next one will be tried. A system provider acts as a final fallback in case no
- * non-system providers can be used.
- *
- * If the DefaultComplicationProviderPolicy is empty then no default is set.
- */
- class DefaultComplicationProviderPolicy(
- /** List of up to two non-system providers to be tried in turn. This may be empty. */
- val providers: List<ComponentName> = listOf(),
-
- /** Fallback in case none of the non-system providers could be used. */
- @SystemProviders.ProviderId val systemProviderFallback: Int = WatchFace.NO_DEFAULT_PROVIDER
- ) {
- constructor(systemProviderFallback: Int) : this(listOf(), systemProviderFallback)
-
- fun isEmpty() =
- providers.isEmpty() && systemProviderFallback == WatchFace.NO_DEFAULT_PROVIDER
- }
-
private lateinit var complicationsManager: ComplicationsManager
private lateinit var invalidateCallback: CanvasComplicationRenderer.InvalidateCallback
private var _unitSquareBounds = unitSquareBounds
+ internal var unitSquareBoundsDirty = true
+ /**
+ * The screen space unit-square bounds of the complication. This is converted to pixels during
+ * rendering.
+ */
var unitSquareBounds: RectF
@UiThread
get() = _unitSquareBounds
@UiThread
set(value) {
+ if (_unitSquareBounds == value) {
+ return
+ }
_unitSquareBounds = value
+ unitSquareBoundsDirty = true
// The caller might modify a number of complications. For efficiency we need to coalesce
// these into one update task.
- complicationsManager.scheduleUpdateActiveComplications()
+ complicationsManager.scheduleUpdate()
}
private var _enabled = true
+ internal var enabledDirty = true
+ /**
+ * Whether or not the complication should be drawn and accept taps.
+ */
var enabled: Boolean
@JvmName("isEnabled")
@UiThread
get() = _enabled
@UiThread
set(value) {
+ if (_enabled == value) {
+ return
+ }
_enabled = value
+ enabledDirty = true
// The caller might enable/disable a number of complications. For efficiency we need
// to coalesce these into one update task.
if (this::complicationsManager.isInitialized) {
- complicationsManager.scheduleUpdateActiveComplications()
+ complicationsManager.scheduleUpdate()
}
}
private var _renderer = renderer
+ /**
+ * The [CanvasComplicationRenderer] used to render the complication.
+ */
var renderer: CanvasComplicationRenderer
@UiThread
get() = _renderer
@UiThread
set(value) {
+ if (_renderer == value) {
+ return
+ }
renderer.onDetach()
value.setData(renderer.getData())
_renderer = value
@@ -364,6 +368,78 @@
initRenderer()
}
+ private var _supportedTypes = supportedTypes
+ internal var supportedTypesDirty = true
+ /**
+ * The types of complications the complication supports.
+ */
+ var supportedTypes: IntArray
+ @UiThread
+ get() = _supportedTypes
+ @UiThread
+ set(value) {
+ if (_supportedTypes == value) {
+ return
+ }
+ _supportedTypes = value
+ supportedTypesDirty = true
+
+ // The caller might modify a number of complications. For efficiency we need to
+ // coalesce these into one update task.
+ if (this::complicationsManager.isInitialized) {
+ complicationsManager.scheduleUpdate()
+ }
+ }
+
+ private var _defaultProviderPolicy = defaultProviderPolicy
+ internal var defaultProviderPolicyDirty = true
+ /**
+ * The [DefaultComplicationProviderPolicy] which defines the default complications providers
+ * selected when the user hasn't yet made a choice. See also [.defaultProviderType].
+ */
+ var defaultProviderPolicy: DefaultComplicationProviderPolicy
+ @UiThread
+ get() = _defaultProviderPolicy
+ @UiThread
+ set(value) {
+ if (_defaultProviderPolicy == value) {
+ return
+ }
+ _defaultProviderPolicy = value
+ defaultProviderPolicyDirty = true
+
+ // The caller might modify a number of complications. For efficiency we need to
+ // coalesce these into one update task.
+ if (this::complicationsManager.isInitialized) {
+ complicationsManager.scheduleUpdate()
+ }
+ }
+
+ private var _defaultProviderType = defaultProviderType
+ internal var defaultProviderTypeDirty = true
+ /**
+ * The default [ComplicationData.ComplicationType] to use alongside [.defaultProviderPolicy].
+ */
+ var defaultProviderType: Int
+ @UiThread
+ get() = _defaultProviderType
+ @UiThread
+ set(value) {
+ if (_defaultProviderType == value) {
+ return
+ }
+ _defaultProviderType = value
+ defaultProviderTypeDirty = true
+
+ // The caller might modify a number of complications. For efficiency we need to
+ // coalesce these into one update task.
+ if (this::complicationsManager.isInitialized) {
+ complicationsManager.scheduleUpdate()
+ }
+ }
+
+ internal var dataDirty = true
+
/**
* Watch faces should use this method to render a complication. Note the system may call this.
*
@@ -408,11 +484,11 @@
initRenderer()
}
- internal fun scheduleUpdateActiveComplications() {
+ internal fun scheduleUpdateComplications() {
// In tests this may not be initialized.
if (this::complicationsManager.isInitialized) {
// Update active complications to ensure accessibility data is up to date.
- complicationsManager.scheduleUpdateActiveComplications()
+ complicationsManager.scheduleUpdate()
}
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ComplicationsManager.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ComplicationsManager.kt
index 5c806cc..40d8731 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ComplicationsManager.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ComplicationsManager.kt
@@ -20,6 +20,7 @@
import android.content.ComponentName
import android.content.Context
import android.content.Intent
+import android.graphics.RectF
import android.icu.util.Calendar
import android.support.wearable.complications.ComplicationData
import android.support.wearable.watchface.accessibility.AccessibilityUtils
@@ -27,7 +28,11 @@
import androidx.annotation.UiThread
import androidx.annotation.VisibleForTesting
import androidx.wear.complications.ComplicationHelperActivity
+import androidx.wear.complications.DefaultComplicationProviderPolicy
import androidx.wear.watchface.data.ComplicationBoundsType
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory
+import androidx.wear.watchface.style.UserStyle
+import androidx.wear.watchface.style.UserStyleRepository
import java.lang.ref.WeakReference
private fun getComponentName(context: Context) = ComponentName(
@@ -45,7 +50,13 @@
/**
* The complications associated with the watch face, may be empty.
*/
- complicationCollection: Collection<Complication>
+ complicationCollection: Collection<Complication>,
+
+ /**
+ * The [UserStyleRepository] used to listen for [ComplicationsUserStyleCategory] changes and
+ * apply them.
+ */
+ private val userStyleRepository: UserStyleRepository
) {
interface TapListener {
/**
@@ -67,19 +78,47 @@
private lateinit var watchFaceHostApi: WatchFaceHostApi
private lateinit var calendar: Calendar
private lateinit var renderer: Renderer
- private lateinit var pendingUpdateActiveComplications: CancellableUniqueTask
+ private lateinit var pendingUpdate: CancellableUniqueTask
// A map of IDs to complications.
val complications: Map<Int, Complication> =
complicationCollection.associateBy(Complication::id)
+ private class InitialComplicationConfig(
+ val id: Int,
+ val unitSquareBounds: RectF,
+ val enabled: Boolean,
+ val supportedTypes: IntArray,
+ val defaultProviderPolicy: DefaultComplicationProviderPolicy,
+ val defaultProviderType: Int
+ )
+
+ // Copy of the original complication configs. This is necessary because the semantics of
+ // [ComplicationsUserStyleCategory] are defined in terms of an override applied to the initial
+ // config.
+ private val initialComplicationConfigs: Map<Int, InitialComplicationConfig> =
+ complicationCollection.associateBy(
+ { it.id },
+ {
+ InitialComplicationConfig(
+ it.id,
+ it.unitSquareBounds,
+ it.enabled,
+ it.supportedTypes,
+ it.defaultProviderPolicy,
+ it.defaultProviderType
+ )
+ }
+ )
+
private val complicationListeners = HashSet<TapListener>()
@VisibleForTesting
- constructor(
+ internal constructor(
complicationCollection: Collection<Complication>,
+ userStyleRepository: UserStyleRepository,
renderer: Renderer
- ) : this(complicationCollection) {
+ ) : this(complicationCollection, userStyleRepository) {
this.renderer = renderer
}
@@ -92,37 +131,72 @@
this.watchFaceHostApi = watchFaceHostApi
this.calendar = calendar
this.renderer = renderer
- pendingUpdateActiveComplications = CancellableUniqueTask(watchFaceHostApi.getHandler())
+ pendingUpdate = CancellableUniqueTask(watchFaceHostApi.getHandler())
for ((_, complication) in complications) {
complication.init(this, complicationInvalidateCallback)
+ }
- if (!complication.defaultProviderPolicy.isEmpty() &&
- complication.defaultProviderType != WatchFace.DEFAULT_PROVIDER_TYPE_NONE
- ) {
- this.watchFaceHostApi.setDefaultComplicationProviderWithFallbacks(
- complication.id,
- complication.defaultProviderPolicy.providers,
- complication.defaultProviderPolicy.systemProviderFallback,
- complication.defaultProviderType
- )
+ val complicationsStyleCategory =
+ userStyleRepository.userStyleCategories.firstOrNull {
+ it is ComplicationsUserStyleCategory
}
+
+ // Add a listener if we have a ComplicationsUserStyleCategory so we can track changes and
+ // automatically apply them.
+ if (complicationsStyleCategory != null) {
+ var previousOption =
+ userStyleRepository.userStyle.options[complicationsStyleCategory] as
+ ComplicationsUserStyleCategory.ComplicationsOption
+ userStyleRepository.addUserStyleListener(
+ object : UserStyleRepository.UserStyleListener {
+ override fun onUserStyleChanged(userStyle: UserStyle) {
+ val newlySelectedOption =
+ userStyle.options[complicationsStyleCategory] as
+ ComplicationsUserStyleCategory.ComplicationsOption
+ if (previousOption != newlySelectedOption) {
+ previousOption = newlySelectedOption
+ applyComplicationsStyleCategoryOption(newlySelectedOption)
+ }
+ }
+ }
+ )
}
// Activate complications.
- scheduleUpdateActiveComplications()
+ scheduleUpdate()
+ }
+
+ internal fun applyComplicationsStyleCategoryOption(
+ styleOption: ComplicationsUserStyleCategory.ComplicationsOption
+ ) {
+ for ((id, complication) in complications) {
+ val override = styleOption.complications.find { it.complicationId == id }
+ val initialConfig = initialComplicationConfigs[id]!!
+ // Apply styleOption overrides.
+ complication.unitSquareBounds =
+ override?.bounds ?: initialConfig.unitSquareBounds
+ complication.enabled =
+ override?.enabled ?: initialConfig.enabled
+ complication.supportedTypes =
+ override?.supportedTypes ?: initialConfig.supportedTypes
+ complication.defaultProviderPolicy =
+ override?.defaultProviderPolicy ?: initialConfig.defaultProviderPolicy
+ complication.defaultProviderType =
+ override?.defaultProviderType ?: initialConfig.defaultProviderType
+ }
}
/** Returns the [Complication] corresponding to id or null. */
operator fun get(id: Int) = complications[id]
- internal fun scheduleUpdateActiveComplications() {
- if (!pendingUpdateActiveComplications.isPending()) {
- pendingUpdateActiveComplications.postUnique(this::updateActiveComplications)
+ internal fun scheduleUpdate() {
+ if (!pendingUpdate.isPending()) {
+ pendingUpdate.postUnique(this::updateComplications)
}
}
- private fun updateActiveComplications() {
+ private fun updateComplications() {
val activeKeys = mutableListOf<Int>()
val labels = mutableListOf<ContentDescriptionLabel>()
@@ -136,46 +210,77 @@
)
)
+ // Work out what's changed using the dirty flags and issue appropriate watchFaceHostApi
+ // calls.
+ var enabledDirty = false
+ var labelsDirty = false
for ((id, complication) in complications) {
+ enabledDirty = enabledDirty || complication.enabledDirty
+ labelsDirty = labelsDirty || complication.enabledDirty
+
if (complication.enabled) {
activeKeys.add(id)
- // Generate a ContentDescriptionLabel and send complication bounds for
- // non-background complications.
+ labelsDirty =
+ labelsDirty || complication.dataDirty || complication.unitSquareBoundsDirty
+
+ val complicationBounds = complication.computeBounds(renderer.screenBounds)
+
+ // Generate a ContentDescriptionLabel.
val data = complication.renderer.getData()
- if (complication.boundsType == ComplicationBoundsType.BACKGROUND) {
- watchFaceHostApi.setComplicationDetails(
- id,
- renderer.screenBounds,
- ComplicationBoundsType.BACKGROUND,
- complication.supportedTypes
- )
- } else {
- val complicationBounds = complication.computeBounds(renderer.screenBounds)
- if (data != null) {
- labels.add(
- ContentDescriptionLabel(
- watchFaceHostApi.getContext(),
- complicationBounds,
- data
+ val complicationBoundsType =
+ if (complication.boundsType == ComplicationBoundsType.BACKGROUND) {
+ ComplicationBoundsType.BACKGROUND
+ } else {
+ if (data != null) {
+ labels.add(
+ ContentDescriptionLabel(
+ watchFaceHostApi.getContext(),
+ complicationBounds,
+ data
+ )
)
- )
+ }
+ ComplicationBoundsType.ROUND_RECT
}
+ if (complication.unitSquareBoundsDirty || complication.supportedTypesDirty) {
watchFaceHostApi.setComplicationDetails(
id,
complicationBounds,
- ComplicationBoundsType.ROUND_RECT,
+ complicationBoundsType,
complication.supportedTypes
)
}
+
+ if (complication.defaultProviderPolicyDirty ||
+ complication.defaultProviderTypeDirty
+ ) {
+ watchFaceHostApi.setDefaultComplicationProviderWithFallbacks(
+ complication.id,
+ complication.defaultProviderPolicy.providersAsList(),
+ complication.defaultProviderPolicy.systemProviderFallback,
+ complication.defaultProviderType
+ )
+ }
+
+ complication.unitSquareBoundsDirty = false
+ complication.supportedTypesDirty = false
+ complication.defaultProviderPolicyDirty = false
+ complication.defaultProviderTypeDirty = false
}
+
+ complication.enabledDirty = false
}
- watchFaceHostApi.setActiveComplications(activeKeys.toIntArray())
+ if (enabledDirty) {
+ watchFaceHostApi.setActiveComplications(activeKeys.toIntArray())
+ }
- // Register ContentDescriptionLabels which are used to provide accessibility data.
- watchFaceHostApi.setContentDescriptionLabels(labels.toTypedArray())
+ if (labelsDirty) {
+ // Register ContentDescriptionLabels which are used to provide accessibility data.
+ watchFaceHostApi.setContentDescriptionLabels(labels.toTypedArray())
+ }
}
/**
@@ -187,7 +292,9 @@
*/
@UiThread
internal fun onComplicationDataUpdate(watchFaceComplicationId: Int, data: ComplicationData) {
- complications[watchFaceComplicationId]?.renderer?.setData(data)
+ val complication = complications[watchFaceComplicationId]!!
+ complication.dataDirty = complication.renderer.getData() != data
+ complication.renderer.setData(data)
}
/**
@@ -225,7 +332,7 @@
fun getComplicationAt(x: Int, y: Int): Complication? {
return complications.entries.firstOrNull {
it.value.enabled && it.value.boundsType != ComplicationBoundsType.BACKGROUND &&
- it.value.computeBounds(renderer.screenBounds).contains(x, y)
+ it.value.computeBounds(renderer.screenBounds).contains(x, y)
}?.value
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/RenderParameters.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/RenderParameters.kt
index 4d797a6..f6649c5 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/RenderParameters.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/RenderParameters.kt
@@ -89,7 +89,8 @@
/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
fun toWireFormat() = RenderParametersWireFormat(
- drawMode.ordinal, layerParameters.map {
+ drawMode.ordinal,
+ layerParameters.map {
RenderParametersWireFormat.LayerParameterWireFormat(
it.key.ordinal,
it.value.ordinal
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
index 3ab5a69..06f1ba8 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
@@ -482,7 +482,8 @@
// fully constructed and it will fail. It's also superfluous because we're going to render
// anyway.
var initFinished = false
- complicationsManager.init(watchFaceHostApi, calendar, renderer,
+ complicationsManager.init(
+ watchFaceHostApi, calendar, renderer,
object : CanvasComplicationRenderer.InvalidateCallback {
@SuppressWarnings("SyntheticAccessor")
override fun onInvalidate() {
@@ -491,9 +492,9 @@
// extra invalidation.
if (renderer.shouldAnimate() &&
computeDelayTillNextFrame(
- nextDrawTimeMillis,
- systemTimeProvider.getSystemTimeMillis()
- )
+ nextDrawTimeMillis,
+ systemTimeProvider.getSystemTimeMillis()
+ )
< MIN_PERCEPTABLE_DELAY_MILLIS
) {
return
@@ -505,36 +506,39 @@
}
)
- WatchFaceConfigActivity.registerWatchFace(componentName, object : WatchFaceConfigDelegate {
- override fun getUserStyleSchema() = userStyleRepository.toSchemaWireFormat()
+ WatchFaceConfigActivity.registerWatchFace(
+ componentName,
+ object : WatchFaceConfigDelegate {
+ override fun getUserStyleSchema() = userStyleRepository.toSchemaWireFormat()
- override fun getUserStyle() = userStyleRepository.userStyle.toWireFormat()
+ override fun getUserStyle() = userStyleRepository.userStyle.toWireFormat()
- override fun setUserStyle(userStyle: UserStyleWireFormat) {
- userStyleRepository.userStyle =
- UserStyle(userStyle, userStyleRepository.userStyleCategories)
+ override fun setUserStyle(userStyle: UserStyleWireFormat) {
+ userStyleRepository.userStyle =
+ UserStyle(userStyle, userStyleRepository.userStyleCategories)
+ }
+
+ override fun getBackgroundComplicationId() =
+ complicationsManager.getBackgroundComplication()?.id
+
+ override fun getComplicationsMap() = complicationsManager.complications
+
+ override fun getCalendar() = calendar
+
+ override fun getComplicationIdAt(tapX: Int, tapY: Int) =
+ complicationsManager.getComplicationAt(tapX, tapY)?.id
+
+ override fun brieflyHighlightComplicationId(complicationId: Int) {
+ complicationsManager.bringAttentionToComplication(complicationId)
+ }
+
+ override fun takeScreenshot(
+ drawRect: Rect,
+ calendar: Calendar,
+ renderParameters: RenderParametersWireFormat
+ ) = renderer.takeScreenshot(calendar, RenderParameters(renderParameters))
}
-
- override fun getBackgroundComplicationId() =
- complicationsManager.getBackgroundComplication()?.id
-
- override fun getComplicationsMap() = complicationsManager.complications
-
- override fun getCalendar() = calendar
-
- override fun getComplicationIdAt(tapX: Int, tapY: Int) =
- complicationsManager.getComplicationAt(tapX, tapY)?.id
-
- override fun brieflyHighlightComplicationId(complicationId: Int) {
- complicationsManager.bringAttentionToComplication(complicationId)
- }
-
- override fun takeScreenshot(
- drawRect: Rect,
- calendar: Calendar,
- renderParameters: RenderParametersWireFormat
- ) = renderer.takeScreenshot(calendar, RenderParameters(renderParameters))
- })
+ )
watchFaceHostApi.registerWatchFaceType(watchFaceType)
watchFaceHostApi.registerUserStyleSchema(userStyleRepository.toSchemaWireFormat())
@@ -693,27 +697,28 @@
@UiThread
internal fun computeDelayTillNextFrame(beginFrameTimeMillis: Long, currentTimeMillis: Long):
Long {
- // Limit update rate to conserve power when the battery is low and not charging.
- val updateRateMillis =
- if (watchState.isBatteryLowAndNotCharging.getValueOr(false)) {
- max(interactiveUpdateRateMillis, MAX_LOW_POWER_INTERACTIVE_UPDATE_RATE_MS)
- } else {
- interactiveUpdateRateMillis
+ // Limit update rate to conserve power when the battery is low and not charging.
+ val updateRateMillis =
+ if (watchState.isBatteryLowAndNotCharging.getValueOr(false)) {
+ max(interactiveUpdateRateMillis, MAX_LOW_POWER_INTERACTIVE_UPDATE_RATE_MS)
+ } else {
+ interactiveUpdateRateMillis
+ }
+ // Note beginFrameTimeMillis could be in the future if the user adjusted the time so we need
+ // to compute min(beginFrameTimeMillis, currentTimeMillis).
+ var nextFrameTimeMillis =
+ Math.min(beginFrameTimeMillis, currentTimeMillis) + updateRateMillis
+ // Drop frames if needed (happens when onDraw is slow).
+ if (nextFrameTimeMillis <= currentTimeMillis) {
+ // Compute the next runtime after currentTimeMillis with the same phase as
+ // beginFrameTimeMillis to keep the animation smooth.
+ val phaseAdjust =
+ updateRateMillis +
+ ((nextFrameTimeMillis - currentTimeMillis) % updateRateMillis)
+ nextFrameTimeMillis = currentTimeMillis + phaseAdjust
}
- // Note beginFrameTimeMillis could be in the future if the user adjusted the time so we need
- // to compute min(beginFrameTimeMillis, currentTimeMillis).
- var nextFrameTimeMillis =
- Math.min(beginFrameTimeMillis, currentTimeMillis) + updateRateMillis
- // Drop frames if needed (happens when onDraw is slow).
- if (nextFrameTimeMillis <= currentTimeMillis) {
- // Compute the next runtime after currentTimeMillis with the same phase as
- // beginFrameTimeMillis to keep the animation smooth.
- val phaseAdjust =
- updateRateMillis + ((nextFrameTimeMillis - currentTimeMillis) % updateRateMillis)
- nextFrameTimeMillis = currentTimeMillis + phaseAdjust
+ return nextFrameTimeMillis - currentTimeMillis
}
- return nextFrameTimeMillis - currentTimeMillis
- }
/**
* Called when new complication data is received.
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
index 9bbb10b..42f2736 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
@@ -35,6 +35,7 @@
import android.os.Trace
import android.service.wallpaper.WallpaperService
import android.support.wearable.complications.ComplicationData
+import android.support.wearable.complications.ComplicationData.TYPE_NO_DATA
import android.support.wearable.watchface.Constants
import android.support.wearable.watchface.IWatchFaceCommand
import android.support.wearable.watchface.IWatchFaceService
@@ -47,6 +48,7 @@
import androidx.wear.complications.SystemProviders.ProviderId
import androidx.wear.watchface.data.ComplicationBoundsType
import androidx.wear.watchface.data.ComplicationDetails
+import androidx.wear.watchface.data.IdAndComplicationData
import androidx.wear.watchface.data.ImmutableSystemState
import androidx.wear.watchface.data.IndicatorState
import androidx.wear.watchface.data.RenderParametersWireFormat
@@ -447,6 +449,7 @@
rendererParametersWireFormat: RenderParametersWireFormat,
compressionQuality: Int,
calendarTimeMillis: Long,
+ idAndComplicationData: List<IdAndComplicationData>?,
userStyle: UserStyleWireFormat?
): Bundle {
return uiThreadHandler.runOnHandler {
@@ -457,6 +460,19 @@
)
}
+ val oldComplicationData =
+ watchFace.complicationsManager.complications.mapValues {
+ it.value.renderer.getData() ?: ComplicationData.Builder(TYPE_NO_DATA)
+ .build()
+ }
+ if (idAndComplicationData != null) {
+ for (idAndData in idAndComplicationData) {
+ watchFace.onComplicationDataUpdate(
+ idAndData.id, idAndData.complicationData
+ )
+ }
+ }
+
val bitmap = watchFace.renderer.takeScreenshot(
Calendar.getInstance().apply {
timeInMillis = calendarTimeMillis
@@ -464,11 +480,17 @@
RenderParameters(rendererParametersWireFormat)
)
- // Restore previous style if required.
+ // Restore previous style & complications if required.
if (userStyle != null) {
watchFace.onSetStyleInternal(UserStyle(oldStyle))
}
+ if (idAndComplicationData != null) {
+ for ((id, data) in oldComplicationData) {
+ watchFace.onComplicationDataUpdate(id, data)
+ }
+ }
+
bitmap
}.toAshmemCompressedImageBundle(
compressionQuality
@@ -1004,14 +1026,15 @@
var returnVal: R? = null
var exception: Exception? = null
if (post {
- try {
- returnVal = task.invoke()
- } catch (e: Exception) {
- // Will rethrow on the calling thread.
- exception = e
- }
- latch.countDown()
- }) {
+ try {
+ returnVal = task.invoke()
+ } catch (e: Exception) {
+ // Will rethrow on the calling thread.
+ exception = e
+ }
+ latch.countDown()
+ }
+ ) {
latch.await()
if (exception != null) {
throw exception as Exception
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/control/WatchFaceControlService.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/control/WatchFaceControlService.kt
index 5816071..d499aee 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/control/WatchFaceControlService.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/control/WatchFaceControlService.kt
@@ -271,16 +271,18 @@
private fun sendImmutableProperties(immutableSystemState: ImmutableSystemState) {
uiThreadHandler.runOnHandler {
- engine!!.onPropertiesChanged(Bundle().apply {
- putBoolean(
- Constants.PROPERTY_LOW_BIT_AMBIENT,
- immutableSystemState.hasLowBitAmbient
- )
- putBoolean(
- Constants.PROPERTY_BURN_IN_PROTECTION,
- immutableSystemState.hasBurnInProtection
- )
- })
+ engine!!.onPropertiesChanged(
+ Bundle().apply {
+ putBoolean(
+ Constants.PROPERTY_LOW_BIT_AMBIENT,
+ immutableSystemState.hasLowBitAmbient
+ )
+ putBoolean(
+ Constants.PROPERTY_BURN_IN_PROTECTION,
+ immutableSystemState.hasBurnInProtection
+ )
+ }
+ )
}
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/ConfigFragment.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/ConfigFragment.kt
index 62a018c..26aacc1 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/ConfigFragment.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/ConfigFragment.kt
@@ -74,7 +74,7 @@
savedState: Bundle?
): View {
view = inflater.inflate(R.layout.config_layout, container, false) as
- SwipeDismissFrameLayout
+ SwipeDismissFrameLayout
view.addCallback(object : SwipeDismissFrameLayout.Callback() {
override fun onDismissed(layout: SwipeDismissFrameLayout) {
@@ -99,10 +99,10 @@
ConfigOption(
id = Constants.KEY_COMPLICATIONS_SETTINGS,
icon =
- Icon.createWithResource(
- context,
- R.drawable.ic_elements_settings_complications
- ),
+ Icon.createWithResource(
+ context,
+ R.drawable.ic_elements_settings_complications
+ ),
title = resources.getString(R.string.settings_complications),
summary = ""
)
@@ -153,13 +153,16 @@
watchFaceConfigActivity.watchFaceComponentName,
intArrayOf(watchFaceConfigActivity.backgroundComplicationId!!)
)
- future.addListener({
- val provideInfo = future.get()
- provideInfo.info?.apply {
- backgroundConfigOption.summary = providerName!!
- configViewAdapter.notifyDataSetChanged()
- }
- }, { runnable -> runnable.run() })
+ future.addListener(
+ {
+ val provideInfo = future.get()
+ provideInfo.info?.apply {
+ backgroundConfigOption.summary = providerName!!
+ configViewAdapter.notifyDataSetChanged()
+ }
+ },
+ { runnable -> runnable.run() }
+ )
return backgroundConfigOption
}
@@ -185,7 +188,8 @@
Constants.KEY_BACKGROUND_IMAGE_SETTINGS -> {
val backgroundComplication =
watchFaceConfigActivity.watchFaceConfigDelegate.getComplicationsMap()[
- watchFaceConfigActivity.backgroundComplicationId!!]!!
+ watchFaceConfigActivity.backgroundComplicationId!!
+ ]!!
watchFaceConfigActivity.fragmentController.showComplicationConfig(
backgroundComplication.id,
*backgroundComplication.supportedTypes
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/StyleConfigFragment.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/StyleConfigFragment.kt
index ed042f0..1605791 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/StyleConfigFragment.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/StyleConfigFragment.kt
@@ -34,6 +34,7 @@
import androidx.versionedparcelable.ParcelUtils
import androidx.wear.watchface.R
import androidx.wear.watchface.style.BooleanUserStyleCategory
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory
import androidx.wear.watchface.style.DoubleRangeUserStyleCategory
import androidx.wear.watchface.style.ListUserStyleCategory
import androidx.wear.watchface.style.UserStyle
@@ -49,8 +50,7 @@
* @hide
*/
@RestrictTo(LIBRARY)
-internal class StyleConfigFragment : Fragment(),
- StyleSettingViewAdapter.ClickListener {
+internal class StyleConfigFragment : Fragment(), ClickListener {
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
internal lateinit var watchFaceConfigActivity: WatchFaceConfigActivity
@@ -97,13 +97,15 @@
val view =
inflater.inflate(R.layout.style_options_layout, container, false)
- as SwipeDismissFrameLayout
+ as SwipeDismissFrameLayout
val styleOptions = styleCategory.options
val booleanUserStyleCategory =
styleOptions.filterIsInstance<BooleanUserStyleCategory.BooleanOption>()
- val ListUserStyleCategory =
+ val listUserStyleCategory =
styleOptions.filterIsInstance<ListUserStyleCategory.ListOption>()
+ val complicationsUserStyleCategory =
+ styleOptions.filterIsInstance<ComplicationsUserStyleCategory.ComplicationsOption>()
val rangeUserStyleCategory =
styleOptions.filterIsInstance<DoubleRangeUserStyleCategory.DoubleRangeOption>()
@@ -123,13 +125,27 @@
rangedStyle.isEnabled = false
}
- ListUserStyleCategory.isNotEmpty() -> {
+ listUserStyleCategory.isNotEmpty() -> {
booleanStyle.isEnabled = false
booleanStyle.visibility = View.GONE
styleOptionsList.adapter =
- StyleSettingViewAdapter(
+ ListStyleSettingViewAdapter(
requireContext(),
- ListUserStyleCategory,
+ listUserStyleCategory,
+ this@StyleConfigFragment
+ )
+ styleOptionsList.layoutManager = WearableLinearLayoutManager(context)
+ rangedStyle.isEnabled = false
+ rangedStyle.visibility = View.GONE
+ }
+
+ complicationsUserStyleCategory.isNotEmpty() -> {
+ booleanStyle.isEnabled = false
+ booleanStyle.visibility = View.GONE
+ styleOptionsList.adapter =
+ ComplicationsStyleSettingViewAdapter(
+ requireContext(),
+ complicationsUserStyleCategory,
this@StyleConfigFragment
)
styleOptionsList.layoutManager = WearableLinearLayoutManager(context)
@@ -140,11 +156,15 @@
rangeUserStyleCategory.isNotEmpty() -> {
val rangedStyleCategory = styleCategory as DoubleRangeUserStyleCategory
val minValue =
- (rangedStyleCategory.options.first() as
- DoubleRangeUserStyleCategory.DoubleRangeOption).value
+ (
+ rangedStyleCategory.options.first() as
+ DoubleRangeUserStyleCategory.DoubleRangeOption
+ ).value
val maxValue =
- (rangedStyleCategory.options.last() as
- DoubleRangeUserStyleCategory.DoubleRangeOption).value
+ (
+ rangedStyleCategory.options.last() as
+ DoubleRangeUserStyleCategory.DoubleRangeOption
+ ).value
val delta = (maxValue - minValue) / 100.0f
val value = userStyle.options[styleCategory]!!.id.toFloat()
rangedStyle.progress = ((value - minValue) / delta).toInt()
@@ -214,24 +234,63 @@
var userStyleOption: UserStyleCategory.Option? = null
}
+internal interface ClickListener {
+ /** Called when a userStyle option is selected. */
+ fun onItemClick(userStyleOption: UserStyleCategory.Option)
+}
+
/**
- * An adapter for lists of selectable userStyle options.
- *
- * @hide
+ * An adapter for [ListUserStyleCategory].
*/
-@RestrictTo(LIBRARY)
-internal class StyleSettingViewAdapter(
+internal class ListStyleSettingViewAdapter(
private val context: Context,
private val styleOptions: List<ListUserStyleCategory.ListOption>,
private val clickListener: ClickListener
) :
RecyclerView.Adapter<StyleSettingViewHolder>() {
- interface ClickListener {
- /** Called when a userStyle option is selected. */
- fun onItemClick(userStyleOption: UserStyleCategory.Option)
+ private val handler = Handler(Looper.getMainLooper())
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = StyleSettingViewHolder(
+ LayoutInflater.from(parent.context).inflate(
+ R.layout.stylelist_item_layout, parent, false
+ )
+ ).apply {
+ itemView.setOnClickListener { clickListener.onItemClick(userStyleOption!!) }
}
+ override fun onBindViewHolder(holder: StyleSettingViewHolder, position: Int) {
+ val styleOption = styleOptions[position]
+ holder.userStyleOption = styleOption
+ val textView = holder.itemView as TextView
+ textView.text = styleOption.displayName
+ styleOption.icon?.loadDrawableAsync(
+ context,
+ { drawable ->
+ textView.setCompoundDrawablesRelativeWithIntrinsicBounds(
+ Helper.wrapIcon(context, drawable),
+ /* top = */ null,
+ /* end = */ null,
+ /* bottom = */ null
+ )
+ },
+ handler
+ )
+ }
+
+ override fun getItemCount() = styleOptions.size
+}
+
+/**
+ * An adapter for [ComplicationsUserStyleCategory]. This is a very minimal placeholder UI.
+ */
+internal class ComplicationsStyleSettingViewAdapter(
+ private val context: Context,
+ private val styleOptions: List<ComplicationsUserStyleCategory.ComplicationsOption>,
+ private val clickListener: ClickListener
+) :
+ RecyclerView.Adapter<StyleSettingViewHolder>() {
+
private val handler = Handler(Looper.getMainLooper())
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = StyleSettingViewHolder(
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/WatchFaceConfigActivity.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/WatchFaceConfigActivity.kt
index 61dc687..fbeea63 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/WatchFaceConfigActivity.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/ui/WatchFaceConfigActivity.kt
@@ -120,46 +120,51 @@
val componentName: ComponentName =
intent.getParcelableExtra(Constants.EXTRA_WATCH_FACE_COMPONENT) ?: return
- init(componentName, object : FragmentController {
- @SuppressLint("SyntheticAccessor")
- override fun showConfigFragment() {
- showFragment(ConfigFragment())
- }
+ init(
+ componentName,
+ object : FragmentController {
+ @SuppressLint("SyntheticAccessor")
+ override fun showConfigFragment() {
+ showFragment(ConfigFragment())
+ }
- @SuppressLint("SyntheticAccessor")
- override fun showComplicationConfigSelectionFragment() {
- showFragment(ComplicationConfigFragment())
- }
+ @SuppressLint("SyntheticAccessor")
+ override fun showComplicationConfigSelectionFragment() {
+ showFragment(ComplicationConfigFragment())
+ }
- @SuppressLint("SyntheticAccessor")
- override fun showStyleConfigFragment(
- categoryId: String,
- styleSchema: List<UserStyleCategory>,
- userStyle: UserStyle
- ) {
- showFragment(StyleConfigFragment.newInstance(categoryId, styleSchema, userStyle))
- }
+ @SuppressLint("SyntheticAccessor")
+ override fun showStyleConfigFragment(
+ categoryId: String,
+ styleSchema: List<UserStyleCategory>,
+ userStyle: UserStyle
+ ) {
+ showFragment(
+ StyleConfigFragment.newInstance(categoryId, styleSchema, userStyle)
+ )
+ }
- /**
- * Displays a config screen which allows the user to select the data source for the
- * complication.
- */
- @SuppressWarnings("deprecation")
- override fun showComplicationConfig(
- complicationId: Int,
- vararg supportedComplicationDataTypes: Int
- ) {
- startActivityForResult(
- ComplicationHelperActivity.createProviderChooserHelperIntent(
- context,
- watchFaceComponentName,
- complicationId,
- supportedComplicationDataTypes
- ),
- Constants.PROVIDER_CHOOSER_REQUEST_CODE
- )
+ /**
+ * Displays a config screen which allows the user to select the data source for the
+ * complication.
+ */
+ @SuppressWarnings("deprecation")
+ override fun showComplicationConfig(
+ complicationId: Int,
+ vararg supportedComplicationDataTypes: Int
+ ) {
+ startActivityForResult(
+ ComplicationHelperActivity.createProviderChooserHelperIntent(
+ context,
+ watchFaceComponentName,
+ complicationId,
+ supportedComplicationDataTypes
+ ),
+ Constants.PROVIDER_CHOOSER_REQUEST_CODE
+ )
+ }
}
- })
+ )
}
private fun focusCurrentFragment() {
diff --git a/wear/wear-watchface/src/test/java/androidx/wear/watchface/ObservableWatchDataTest.kt b/wear/wear-watchface/src/test/java/androidx/wear/watchface/ObservableWatchDataTest.kt
index 4cf3908..b29815d 100644
--- a/wear/wear-watchface/src/test/java/androidx/wear/watchface/ObservableWatchDataTest.kt
+++ b/wear/wear-watchface/src/test/java/androidx/wear/watchface/ObservableWatchDataTest.kt
@@ -131,13 +131,15 @@
// Inhibit initial onChanged callback for clarity.
var addObserver = false
- data.addObserver(Observer<Int> {
- if (addObserver) {
- val observer = Observer<Int> { addedObserverObservations++ }
- data.addObserver(observer)
- observersAdded++
+ data.addObserver(
+ Observer<Int> {
+ if (addObserver) {
+ val observer = Observer<Int> { addedObserverObservations++ }
+ data.addObserver(observer)
+ observersAdded++
+ }
}
- })
+ )
addObserver = true
data.value = 20
diff --git a/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt b/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
index a8177cd..6079cb01 100644
--- a/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
+++ b/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
@@ -33,10 +33,14 @@
import android.view.SurfaceHolder
import android.view.ViewConfiguration
import androidx.test.core.app.ApplicationProvider
+import androidx.wear.complications.DefaultComplicationProviderPolicy
import androidx.wear.complications.SystemProviders
-import androidx.wear.complications.rendering.ComplicationDrawable
+import androidx.wear.watchface.complications.rendering.ComplicationDrawable
import androidx.wear.watchface.data.ComplicationBoundsType
import androidx.wear.watchface.data.ComplicationDetails
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationOverride
+import androidx.wear.watchface.style.ComplicationsUserStyleCategory.ComplicationsOption
import androidx.wear.watchface.style.Layer
import androidx.wear.watchface.style.ListUserStyleCategory
import androidx.wear.watchface.style.UserStyle
@@ -69,6 +73,10 @@
private const val LEFT_COMPLICATION_ID = 1000
private const val RIGHT_COMPLICATION_ID = 1001
private const val BACKGROUND_COMPLICATION_ID = 1111
+private const val NO_COMPLICATIONS = "NO_COMPLICATIONS"
+private const val LEFT_COMPLICATION = "LEFT_COMPLICATION"
+private const val RIGHT_COMPLICATION = "RIGHT_COMPLICATION"
+private const val LEFT_AND_RIGHT_COMPLICATIONS = "LEFT_AND_RIGHT_COMPLICATIONS"
@Config(manifest = Config.NONE)
@RunWith(WatchFaceTestRunner::class)
@@ -151,7 +159,7 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.SUNRISE_SUNSET)
+ DefaultComplicationProviderPolicy(SystemProviders.SUNRISE_SUNSET)
).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
.build()
@@ -172,7 +180,7 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
+ DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.setUnitSquareBounds(RectF(0.6f, 0.4f, 0.8f, 0.6f))
.build()
@@ -189,11 +197,69 @@
intArrayOf(
ComplicationData.TYPE_LARGE_IMAGE
),
- Complication.DefaultComplicationProviderPolicy()
+ DefaultComplicationProviderPolicy()
).setDefaultProviderType(ComplicationData.TYPE_LARGE_IMAGE)
.setBackgroundComplication()
.build()
+ private val leftAndRightComplicationsOption = ComplicationsOption(
+ LEFT_AND_RIGHT_COMPLICATIONS,
+ "Both",
+ null,
+ listOf(
+ ComplicationOverride.Builder(LEFT_COMPLICATION_ID)
+ .setEnabled(true).build(),
+ ComplicationOverride.Builder(RIGHT_COMPLICATION_ID)
+ .setEnabled(true).build()
+ )
+ )
+ private val noComplicationsOption = ComplicationsOption(
+ NO_COMPLICATIONS,
+ "Both",
+ null,
+ listOf(
+ ComplicationOverride.Builder(LEFT_COMPLICATION_ID)
+ .setEnabled(false).build(),
+ ComplicationOverride.Builder(RIGHT_COMPLICATION_ID)
+ .setEnabled(false).build()
+ )
+ )
+ private val leftComplicationsOption = ComplicationsOption(
+ LEFT_COMPLICATION,
+ "Left",
+ null,
+ listOf(
+ ComplicationOverride.Builder(LEFT_COMPLICATION_ID)
+ .setEnabled(true).build(),
+ ComplicationOverride.Builder(RIGHT_COMPLICATION_ID)
+ .setEnabled(false).build()
+ )
+ )
+ private val rightComplicationsOption = ComplicationsOption(
+ RIGHT_COMPLICATION,
+ "Right",
+ null,
+ listOf(
+ ComplicationOverride.Builder(LEFT_COMPLICATION_ID)
+ .setEnabled(false).build(),
+ ComplicationOverride.Builder(RIGHT_COMPLICATION_ID)
+ .setEnabled(true).build()
+ )
+ )
+ private val complicationsStyleCategory = ComplicationsUserStyleCategory(
+ "complications_style_category",
+ "Complications",
+ "Number and position",
+ icon = null,
+ complicationConfig = listOf(
+ leftAndRightComplicationsOption,
+ noComplicationsOption,
+ leftComplicationsOption,
+ rightComplicationsOption
+ ),
+ affectsLayers = listOf(Layer.COMPLICATIONS)
+ )
+
private lateinit var renderer: TestRenderer
private lateinit var complicationsManager: ComplicationsManager
private lateinit var userStyleRepository: UserStyleRepository
@@ -225,9 +291,8 @@
hasLowBitAmbient: Boolean = false,
hasBurnInProtection: Boolean = false
) {
- this.complicationsManager = ComplicationsManager(complications)
- userStyleRepository =
- UserStyleRepository(userStyleCategories)
+ userStyleRepository = UserStyleRepository(userStyleCategories)
+ this.complicationsManager = ComplicationsManager(complications, userStyleRepository)
renderer = TestRenderer(surfaceHolder, userStyleRepository, watchState.asWatchState())
testWatchFaceService = TestWatchFaceService(
watchFaceType,
@@ -272,10 +337,12 @@
hasLowBitAmbient: Boolean,
hasBurnInProtection: Boolean
) {
- engine.onPropertiesChanged(Bundle().apply {
- putBoolean(Constants.PROPERTY_LOW_BIT_AMBIENT, hasLowBitAmbient)
- putBoolean(Constants.PROPERTY_BURN_IN_PROTECTION, hasBurnInProtection)
- })
+ engine.onPropertiesChanged(
+ Bundle().apply {
+ putBoolean(Constants.PROPERTY_LOW_BIT_AMBIENT, hasLowBitAmbient)
+ putBoolean(Constants.PROPERTY_BURN_IN_PROTECTION, hasBurnInProtection)
+ }
+ )
}
private fun sendRequestStyle() {
@@ -778,7 +845,7 @@
TestRenderer(surfaceHolder, userStyleRepository2, watchState.asWatchState())
val service2 = TestWatchFaceService(
WatchFaceType.ANALOG,
- ComplicationsManager(emptyList()),
+ ComplicationsManager(emptyList(), userStyleRepository2),
testRenderer2,
userStyleRepository2,
watchState,
@@ -837,7 +904,7 @@
TestRenderer(surfaceHolder, userStyleRepository2, watchState.asWatchState())
val service2 = TestWatchFaceService(
WatchFaceType.ANALOG,
- ComplicationsManager(emptyList()),
+ ComplicationsManager(emptyList(), userStyleRepository2),
testRenderer2,
userStyleRepository2,
watchState,
@@ -903,9 +970,11 @@
watchState.isKeyguardLocked.addObserver(isKeyguardLockedObserver)
// Every indicator onXyz method should be called upon the initial update.
- engineWrapper.onBackgroundAction(Bundle().apply {
- putBundle(Constants.EXTRA_INDICATOR_STATUS, bundle)
- })
+ engineWrapper.onBackgroundAction(
+ Bundle().apply {
+ putBundle(Constants.EXTRA_INDICATOR_STATUS, bundle)
+ }
+ )
verify(isChargingObserver).onChanged(true)
verify(inAirplaneModeObserver).onChanged(false)
@@ -923,9 +992,11 @@
// Check only the modified setIsCharging state leads to a call.
bundle.putBoolean(Constants.STATUS_CHARGING, false)
- engineWrapper.onBackgroundAction(Bundle().apply {
- putBundle(Constants.EXTRA_INDICATOR_STATUS, bundle)
- })
+ engineWrapper.onBackgroundAction(
+ Bundle().apply {
+ putBundle(Constants.EXTRA_INDICATOR_STATUS, bundle)
+ }
+ )
verify(isChargingObserver).onChanged(false)
verify(inAirplaneModeObserver, times(0)).onChanged(anyBoolean())
verify(isConnectedToCompanionObserver, times(0)).onChanged(anyBoolean())
@@ -1119,7 +1190,8 @@
val service = TestWatchFaceService(
WatchFaceType.ANALOG,
ComplicationsManager(
- listOf(leftComplication, rightComplication, backgroundComplication)
+ listOf(leftComplication, rightComplication, backgroundComplication),
+ userStyleRepository
),
testRenderer,
UserStyleRepository(emptyList()),
@@ -1144,6 +1216,7 @@
assertThat(argument.value.acceptsTapEvents).isEqualTo(true)
}
+ @Test
fun defaultProvidersWithFallbacks_newApi() {
val provider1 = ComponentName("com.app1", "com.app1.App1")
val provider2 = ComponentName("com.app2", "com.app2.App2")
@@ -1151,8 +1224,9 @@
LEFT_COMPLICATION_ID,
CanvasComplicationDrawableRenderer(complicationDrawableLeft, watchState.asWatchState()),
intArrayOf(),
- Complication.DefaultComplicationProviderPolicy(
- listOf(provider1, provider2),
+ DefaultComplicationProviderPolicy(
+ provider1,
+ provider2,
SystemProviders.SUNRISE_SUNSET
)
).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
@@ -1160,6 +1234,8 @@
.build()
initEngine(WatchFaceType.ANALOG, listOf(complication), emptyList())
+ runPostedTasksFor(0)
+
verify(iWatchFaceService).setDefaultComplicationProviderWithFallbacks(
LEFT_COMPLICATION_ID,
listOf(provider1, provider2),
@@ -1176,8 +1252,9 @@
LEFT_COMPLICATION_ID,
CanvasComplicationDrawableRenderer(complicationDrawableLeft, watchState.asWatchState()),
intArrayOf(),
- Complication.DefaultComplicationProviderPolicy(
- listOf(provider1, provider2),
+ DefaultComplicationProviderPolicy(
+ provider1,
+ provider2,
SystemProviders.SUNRISE_SUNSET
)
).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
@@ -1185,6 +1262,8 @@
.build()
initEngine(WatchFaceType.ANALOG, listOf(complication), emptyList(), apiVersion = 0)
+ runPostedTasksFor(0)
+
verify(iWatchFaceService).setDefaultComplicationProvider(
LEFT_COMPLICATION_ID, provider2, ComplicationData.TYPE_SHORT_TEXT
)
@@ -1281,7 +1360,7 @@
}
val service = TestWatchFaceService(
WatchFaceType.ANALOG,
- ComplicationsManager(emptyList()),
+ ComplicationsManager(emptyList(), userStyleRepository),
testRenderer,
UserStyleRepository(emptyList()),
watchState,
@@ -1309,4 +1388,123 @@
watchFace.maybeUpdateDrawMode()
assertThat(testRenderer.renderParameters.drawMode).isEqualTo(DrawMode.AMBIENT)
}
+
+ @Test
+ fun complicationsUserStyleCategorySelectionAppliesChanges() {
+ initEngine(
+ WatchFaceType.DIGITAL,
+ listOf(leftComplication, rightComplication),
+ listOf(complicationsStyleCategory),
+ apiVersion = 4
+ )
+
+ // Select a new style which turns off both complications.
+ val newStyleA = HashMap(userStyleRepository.userStyle.options)
+ newStyleA[complicationsStyleCategory] = noComplicationsOption
+ userStyleRepository.userStyle = UserStyle(newStyleA)
+
+ runPostedTasksFor(0)
+
+ assertFalse(leftComplication.enabled)
+ assertFalse(rightComplication.enabled)
+ verify(iWatchFaceService).setActiveComplications(intArrayOf(), true)
+
+ val argumentA = ArgumentCaptor.forClass(Array<ContentDescriptionLabel>::class.java)
+ verify(iWatchFaceService).setContentDescriptionLabels(argumentA.capture())
+ assertThat(argumentA.value.size).isEqualTo(1)
+ assertThat(argumentA.value[0].bounds).isEqualTo(Rect(25, 25, 75, 75)) // Clock element.
+
+ reset(iWatchFaceService)
+
+ // Select a new style which turns on only the left complication.
+ val newStyleB = HashMap(userStyleRepository.userStyle.options)
+ newStyleB[complicationsStyleCategory] = leftComplicationsOption
+ userStyleRepository.userStyle = UserStyle(newStyleB)
+
+ runPostedTasksFor(0)
+
+ assertTrue(leftComplication.enabled)
+ assertFalse(rightComplication.enabled)
+ verify(iWatchFaceService).setActiveComplications(intArrayOf(LEFT_COMPLICATION_ID), false)
+
+ val argumentB = ArgumentCaptor.forClass(Array<ContentDescriptionLabel>::class.java)
+ verify(iWatchFaceService).setContentDescriptionLabels(argumentB.capture())
+ assertThat(argumentB.value.size).isEqualTo(2)
+ assertThat(argumentB.value[0].bounds).isEqualTo(Rect(25, 25, 75, 75)) // Clock element.
+ assertThat(argumentB.value[1].bounds).isEqualTo(Rect(20, 40, 40, 60)) // Left complication.
+ }
+
+ @Test
+ fun partialComplicationOverrides() {
+ val bothComplicationsOption = ComplicationsOption(
+ LEFT_AND_RIGHT_COMPLICATIONS,
+ "Left And Right",
+ null,
+ emptyList()
+ )
+ val leftOnlyComplicationsOption = ComplicationsOption(
+ LEFT_COMPLICATION,
+ "Left",
+ null,
+ listOf(ComplicationOverride.Builder(RIGHT_COMPLICATION_ID).setEnabled(false).build())
+ )
+ val rightOnlyComplicationsOption = ComplicationsOption(
+ RIGHT_COMPLICATION,
+ "Right",
+ null,
+ listOf(ComplicationOverride.Builder(LEFT_COMPLICATION_ID).setEnabled(false).build())
+ )
+ val complicationsStyleCategory = ComplicationsUserStyleCategory(
+ "complications_style_category",
+ "Complications",
+ "Number and position",
+ icon = null,
+ complicationConfig = listOf(
+ bothComplicationsOption,
+ leftOnlyComplicationsOption,
+ rightOnlyComplicationsOption
+ ),
+ affectsLayers = listOf(Layer.COMPLICATIONS)
+ )
+
+ initEngine(
+ WatchFaceType.DIGITAL,
+ listOf(leftComplication, rightComplication),
+ listOf(complicationsStyleCategory),
+ apiVersion = 4
+ )
+
+ assertTrue(leftComplication.enabled)
+ assertTrue(rightComplication.enabled)
+
+ // Select left complication only.
+ val newStyleA = HashMap(userStyleRepository.userStyle.options)
+ newStyleA[complicationsStyleCategory] = leftOnlyComplicationsOption
+ userStyleRepository.userStyle = UserStyle(newStyleA)
+
+ runPostedTasksFor(0)
+
+ assertTrue(leftComplication.enabled)
+ assertFalse(rightComplication.enabled)
+
+ // Select right complication only.
+ val newStyleB = HashMap(userStyleRepository.userStyle.options)
+ newStyleB[complicationsStyleCategory] = rightOnlyComplicationsOption
+ userStyleRepository.userStyle = UserStyle(newStyleB)
+
+ runPostedTasksFor(0)
+
+ assertFalse(leftComplication.enabled)
+ assertTrue(rightComplication.enabled)
+
+ // Select both complications.
+ val newStyleC = HashMap(userStyleRepository.userStyle.options)
+ newStyleC[complicationsStyleCategory] = bothComplicationsOption
+ userStyleRepository.userStyle = UserStyle(newStyleC)
+
+ runPostedTasksFor(0)
+
+ assertTrue(leftComplication.enabled)
+ assertTrue(rightComplication.enabled)
+ }
}
diff --git a/wear/wear-watchface/src/test/java/androidx/wear/watchface/ui/WatchFaceConfigUiTest.kt b/wear/wear-watchface/src/test/java/androidx/wear/watchface/ui/WatchFaceConfigUiTest.kt
index aefe0bc..beec667 100644
--- a/wear/wear-watchface/src/test/java/androidx/wear/watchface/ui/WatchFaceConfigUiTest.kt
+++ b/wear/wear-watchface/src/test/java/androidx/wear/watchface/ui/WatchFaceConfigUiTest.kt
@@ -25,8 +25,9 @@
import android.support.wearable.complications.ComplicationData
import android.view.SurfaceHolder
import androidx.test.core.app.ApplicationProvider
+import androidx.wear.complications.DefaultComplicationProviderPolicy
import androidx.wear.complications.SystemProviders
-import androidx.wear.complications.rendering.ComplicationDrawable
+import androidx.wear.watchface.complications.rendering.ComplicationDrawable
import androidx.wear.watchface.Complication
import androidx.wear.watchface.CanvasComplicationDrawableRenderer
import androidx.wear.watchface.ComplicationsManager
@@ -133,7 +134,7 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.SUNRISE_SUNSET)
+ DefaultComplicationProviderPolicy(SystemProviders.SUNRISE_SUNSET)
).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.setUnitSquareBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
.build()
@@ -154,7 +155,7 @@
ComplicationData.TYPE_ICON,
ComplicationData.TYPE_SMALL_IMAGE
),
- Complication.DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
+ DefaultComplicationProviderPolicy(SystemProviders.DAY_OF_WEEK)
).setDefaultProviderType(ComplicationData.TYPE_SHORT_TEXT)
.setUnitSquareBounds(RectF(0.6f, 0.4f, 0.8f, 0.6f))
.build()
@@ -171,7 +172,7 @@
intArrayOf(
ComplicationData.TYPE_LARGE_IMAGE
),
- Complication.DefaultComplicationProviderPolicy()
+ DefaultComplicationProviderPolicy()
).setDefaultProviderType(ComplicationData.TYPE_LARGE_IMAGE)
.setBackgroundComplication()
.build()
@@ -196,6 +197,7 @@
val complicationSet = ComplicationsManager(
complications,
+ userStyleRepository,
object : Renderer(surfaceHolder, userStyleRepository, watchState.asWatchState()) {
override fun renderInternal(calendar: Calendar) {}
@@ -205,7 +207,8 @@
): Bitmap {
throw RuntimeException("Not Implemented!")
}
- })
+ }
+ )
val watchFaceComponentName = ComponentName(
context.packageName,
@@ -242,7 +245,8 @@
calendar: Calendar,
renderParameters: RenderParametersWireFormat
) = watchFaceConfigDelegate.takeScreenshot(drawRect, calendar, renderParameters)
- })
+ }
+ )
configActivity.init(watchFaceComponentName, fragmentController)
}
@@ -361,10 +365,12 @@
val styleConfigFragment = StyleConfigFragment.newInstance(
configActivity.styleSchema[categoryIndex].id,
configActivity.styleSchema,
- UserStyle(hashMapOf(
- colorStyleCategory to colorStyleCategory.options.first(),
- watchHandStyleCategory to watchHandStyleCategory.options.first()
- ))
+ UserStyle(
+ hashMapOf(
+ colorStyleCategory to colorStyleCategory.options.first(),
+ watchHandStyleCategory to watchHandStyleCategory.options.first()
+ )
+ )
)
styleConfigFragment.readOptionsFromArguments()
styleConfigFragment.watchFaceConfigActivity = configActivity
diff --git a/window/window-samples/build.gradle b/window/window-samples/build.gradle
index 5d49fbc..190be72 100644
--- a/window/window-samples/build.gradle
+++ b/window/window-samples/build.gradle
@@ -37,7 +37,7 @@
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
- implementation 'androidx.core:core-ktx:1.3.1'
+ implementation 'androidx.core:core-ktx:1.3.2'
api(CONSTRAINT_LAYOUT, {transitive = true})
// TODO(b/152245564) Conflicting dependencies cause IDE errors.
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0'
diff --git a/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt b/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt
index 54d1f49..cf9d864 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt
@@ -48,8 +48,10 @@
windowManager = getTestBackend()?.let { backend -> WindowManager(this, backend) }
?: WindowManager(this)
- windowManager.registerDeviceStateChangeCallback(mainThreadExecutor,
- deviceStateChangeCallback)
+ windowManager.registerDeviceStateChangeCallback(
+ mainThreadExecutor,
+ deviceStateChangeCallback
+ )
updateCurrentState(windowManager.deviceState)
}
@@ -97,7 +99,8 @@
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
presentation!!.window?.attributes?.flags =
presentation!!.window?.attributes?.flags?.or(
- android.R.attr.showWhenLocked or android.R.attr.turnScreenOn)
+ android.R.attr.showWhenLocked or android.R.attr.turnScreenOn
+ )
}
presentation!!.show()
break
diff --git a/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt b/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt
index 2907a9e..a7e91ca 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt
@@ -35,8 +35,10 @@
view.getLocationInWindow(viewLocationInWindow)
// Intersect the feature rectangle in window with view rectangle to clip the bounds.
- val viewRect = Rect(viewLocationInWindow[0], viewLocationInWindow[1],
- viewLocationInWindow[0] + view.width, viewLocationInWindow[1] + view.height)
+ val viewRect = Rect(
+ viewLocationInWindow[0], viewLocationInWindow[1],
+ viewLocationInWindow[0] + view.width, viewLocationInWindow[1] + view.height
+ )
// Include padding if needed
if (includePadding) {
@@ -49,7 +51,8 @@
val featureRectInView = Rect(displayFeature.bounds)
val intersects = featureRectInView.intersect(viewRect)
if ((featureRectInView.width() == 0 && featureRectInView.height() == 0) ||
- !intersects) {
+ !intersects
+ ) {
return null
}
@@ -64,12 +67,12 @@
* [FrameLayout].
*/
fun getLayoutParamsForFeatureInFrameLayout(displayFeature: DisplayFeature, view: FrameLayout):
- FrameLayout.LayoutParams? {
- val featureRectInView = getFeaturePositionInViewRect(displayFeature, view) ?: return null
+ FrameLayout.LayoutParams? {
+ val featureRectInView = getFeaturePositionInViewRect(displayFeature, view) ?: return null
- val lp = FrameLayout.LayoutParams(featureRectInView.width(), featureRectInView.height())
- lp.leftMargin = featureRectInView.left
- lp.topMargin = featureRectInView.top
+ val lp = FrameLayout.LayoutParams(featureRectInView.width(), featureRectInView.height())
+ lp.leftMargin = featureRectInView.left
+ lp.topMargin = featureRectInView.top
- return lp
-}
\ No newline at end of file
+ return lp
+ }
\ No newline at end of file
diff --git a/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt b/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt
index 25b7105..954c798 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt
@@ -78,15 +78,19 @@
val startWidthSpec = MeasureSpec.makeMeasureSpec(startPosition.width(), EXACTLY)
val startHeightSpec = MeasureSpec.makeMeasureSpec(startPosition.height(), EXACTLY)
startView.measure(startWidthSpec, startHeightSpec)
- startView.layout(startPosition.left, startPosition.top, startPosition.right,
- startPosition.bottom)
+ startView.layout(
+ startPosition.left, startPosition.top, startPosition.right,
+ startPosition.bottom
+ )
val endPosition = splitPositions[1]
val endWidthSpec = MeasureSpec.makeMeasureSpec(endPosition.width(), EXACTLY)
val endHeightSpec = MeasureSpec.makeMeasureSpec(endPosition.height(), EXACTLY)
endView.measure(endWidthSpec, endHeightSpec)
- endView.layout(endPosition.left, endPosition.top, endPosition.right,
- endPosition.bottom)
+ endView.layout(
+ endPosition.left, endPosition.top, endPosition.right,
+ endPosition.bottom
+ )
} else {
super.onLayout(changed, left, top, right, bottom)
}
@@ -130,23 +134,33 @@
val splitRect = getFeaturePositionInViewRect(feature, this) ?: continue
if (feature.bounds.left == 0) { // Horizontal layout
- val topRect = Rect(paddingLeft, paddingTop,
- paddingLeft + paddedWidth, splitRect.top)
- val bottomRect = Rect(paddingLeft, splitRect.bottom,
- paddingLeft + paddedWidth, paddingTop + paddedHeight)
+ val topRect = Rect(
+ paddingLeft, paddingTop,
+ paddingLeft + paddedWidth, splitRect.top
+ )
+ val bottomRect = Rect(
+ paddingLeft, splitRect.bottom,
+ paddingLeft + paddedWidth, paddingTop + paddedHeight
+ )
if (measureAndCheckMinSize(topRect, startView) &&
- measureAndCheckMinSize(bottomRect, endView)) {
+ measureAndCheckMinSize(bottomRect, endView)
+ ) {
return arrayOf(topRect, bottomRect)
}
} else if (feature.bounds.top == 0) { // Vertical layout
- val leftRect = Rect(paddingLeft, paddingTop,
- splitRect.left, paddingTop + paddedHeight)
- val rightRect = Rect(splitRect.right, paddingTop,
- paddingLeft + paddedWidth, paddingTop + paddedHeight)
+ val leftRect = Rect(
+ paddingLeft, paddingTop,
+ splitRect.left, paddingTop + paddedHeight
+ )
+ val rightRect = Rect(
+ splitRect.right, paddingTop,
+ paddingLeft + paddedWidth, paddingTop + paddedHeight
+ )
if (measureAndCheckMinSize(leftRect, startView) &&
- measureAndCheckMinSize(rightRect, endView)) {
+ measureAndCheckMinSize(rightRect, endView)
+ ) {
return arrayOf(leftRect, rightRect)
}
}
diff --git a/window/window-samples/src/main/java/androidx/window/sample/WindowDemosActivity.kt b/window/window-samples/src/main/java/androidx/window/sample/WindowDemosActivity.kt
index e2aa14a..ad02757 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/WindowDemosActivity.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/WindowDemosActivity.kt
@@ -49,8 +49,10 @@
}
if (savedInstanceState != null) {
- selectedBackend = savedInstanceState.getInt(BACKEND_TYPE_EXTRA,
- BACKEND_TYPE_DEVICE_DEFAULT)
+ selectedBackend = savedInstanceState.getInt(
+ BACKEND_TYPE_EXTRA,
+ BACKEND_TYPE_DEVICE_DEFAULT
+ )
}
when (selectedBackend) {
BACKEND_TYPE_DEVICE_DEFAULT ->
diff --git a/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt b/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt
index 358982b..aacfe08 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt
@@ -60,7 +60,8 @@
override fun getWindowLayoutInfo(context: Context): WindowLayoutInfo {
val activity = context.getActivityExt() ?: throw IllegalArgumentException(
"Used non-visual Context used with WindowManager. Please use an Activity or a " +
- "ContextWrapper around an Activity instead.")
+ "ContextWrapper around an Activity instead."
+ )
val windowSize = activity.calculateWindowSizeExt()
val featureRect = foldRect(windowSize)
diff --git a/window/window/build.gradle b/window/window/build.gradle
index 6b2d419..30a2fa6 100644
--- a/window/window/build.gradle
+++ b/window/window/build.gradle
@@ -41,8 +41,8 @@
dependencies {
implementation("androidx.annotation:annotation:1.1.0")
- implementation("androidx.collection:collection:1.0.0")
- implementation "androidx.core:core:1.2.0"
+ implementation("androidx.collection:collection:1.1.0")
+ implementation "androidx.core:core:1.3.2"
compileOnly(project(":window:window-extensions"))
compileOnly(project(":window:window-sidecar"))
diff --git a/work/workmanager-inspection/src/androidTest/java/androidx/work/inspection/WorkInfoTest.kt b/work/workmanager-inspection/src/androidTest/java/androidx/work/inspection/WorkInfoTest.kt
index 412d88b..74b343f 100644
--- a/work/workmanager-inspection/src/androidTest/java/androidx/work/inspection/WorkInfoTest.kt
+++ b/work/workmanager-inspection/src/androidTest/java/androidx/work/inspection/WorkInfoTest.kt
@@ -117,8 +117,8 @@
testEnvironment.workManager.enqueue(request)
testEnvironment.receiveFilteredEvent { event ->
event.hasWorkUpdated() &&
- event.workUpdated.hasData() &&
- event.workUpdated.data.entriesCount == 1
+ event.workUpdated.hasData() &&
+ event.workUpdated.data.entriesCount == 1
}.let { event ->
assertThat(event.workUpdated.id).isEqualTo(request.stringId)
val expectedEntry = DataEntry.newBuilder()
@@ -136,7 +136,7 @@
testEnvironment.workManager.enqueue(request)
testEnvironment.receiveFilteredEvent { event ->
event.hasWorkUpdated() &&
- event.workUpdated.scheduleRequestedAt != WorkSpec.SCHEDULE_NOT_REQUESTED_YET
+ event.workUpdated.scheduleRequestedAt != WorkSpec.SCHEDULE_NOT_REQUESTED_YET
}.let { event ->
assertThat(event.workUpdated.id).isEqualTo(request.stringId)
}
diff --git a/work/workmanager-inspection/src/main/java/androidx/work/inspection/WorkManagerInspector.kt b/work/workmanager-inspection/src/main/java/androidx/work/inspection/WorkManagerInspector.kt
index 2875212..6a41f13 100644
--- a/work/workmanager-inspection/src/main/java/androidx/work/inspection/WorkManagerInspector.kt
+++ b/work/workmanager-inspection/src/main/java/androidx/work/inspection/WorkManagerInspector.kt
@@ -128,19 +128,22 @@
listener: (oldValue: T?, newValue: T) -> Unit
) {
mainHandler.post {
- observe(owner, object : Observer<T> {
- private var lastValue: T? = null
- override fun onChanged(t: T) {
- if (t == null) {
- removeObserver(this)
- } else {
- executor.execute {
- listener(lastValue, t)
- lastValue = t
+ observe(
+ owner,
+ object : Observer<T> {
+ private var lastValue: T? = null
+ override fun onChanged(t: T) {
+ if (t == null) {
+ removeObserver(this)
+ } else {
+ executor.execute {
+ listener(lastValue, t)
+ lastValue = t
+ }
}
}
}
- })
+ )
}
}
@@ -151,7 +154,7 @@
private fun List<StackTraceElement>.prune(): List<StackTraceElement> {
val entryHookIndex = indexOfFirst {
it.className.startsWith("androidx.work.impl.WorkContinuationImpl") &&
- it.methodName == "enqueue"
+ it.methodName == "enqueue"
}
if (entryHookIndex != -1) {
return subList(entryHookIndex + 1, size)
diff --git a/work/workmanager-inspection/src/main/java/androidx/work/inspection/WorkManagerProtoConversionUtil.kt b/work/workmanager-inspection/src/main/java/androidx/work/inspection/WorkManagerProtoConversionUtil.kt
index 1dcdd37..641447e 100644
--- a/work/workmanager-inspection/src/main/java/androidx/work/inspection/WorkManagerProtoConversionUtil.kt
+++ b/work/workmanager-inspection/src/main/java/androidx/work/inspection/WorkManagerProtoConversionUtil.kt
@@ -32,7 +32,8 @@
.setKey(it.key)
.setValue(it.value.toString())
.build()
- })
+ }
+ )
.build()
}
diff --git a/work/workmanager-ktx/src/androidTest/java/androidx/work/CoroutineWorkerTest.kt b/work/workmanager-ktx/src/androidTest/java/androidx/work/CoroutineWorkerTest.kt
index 07f705a..45c89c7 100644
--- a/work/workmanager-ktx/src/androidTest/java/androidx/work/CoroutineWorkerTest.kt
+++ b/work/workmanager-ktx/src/androidTest/java/androidx/work/CoroutineWorkerTest.kt
@@ -82,7 +82,8 @@
.setExecutor(SynchronousExecutor())
.setMinimumLoggingLevel(Log.DEBUG)
.build()
- workManagerImpl = WorkManagerImpl(context, configuration,
+ workManagerImpl = WorkManagerImpl(
+ context, configuration,
InstantWorkTaskExecutor()
)
WorkManagerImpl.setDelegate(workManagerImpl)
@@ -118,7 +119,9 @@
workManagerImpl.workTaskExecutor,
workerFactory,
progressUpdater,
- mForegroundUpdater)) as SynchronousCoroutineWorker
+ mForegroundUpdater
+ )
+ ) as SynchronousCoroutineWorker
assertThat(worker.job.isCompleted, `is`(false))
@@ -128,9 +131,12 @@
assertThat(future.isDone, `is`(true))
assertThat(future.isCancelled, `is`(false))
assertThat(result, `is`(instanceOf(ListenableWorker.Result.Success::class.java)))
- assertThat((result as ListenableWorker.Result.Success).outputData.getLong(
- "output", 0L),
- `is`(999L))
+ assertThat(
+ (result as ListenableWorker.Result.Success).outputData.getLong(
+ "output", 0L
+ ),
+ `is`(999L)
+ )
}
@Test
@@ -149,7 +155,9 @@
workManagerImpl.workTaskExecutor,
workerFactory,
progressUpdater,
- mForegroundUpdater)) as SynchronousCoroutineWorker
+ mForegroundUpdater
+ )
+ ) as SynchronousCoroutineWorker
assertThat(worker.job.isCancelled, `is`(false))
worker.future.cancel(true)
@@ -187,7 +195,8 @@
.updateProgress(
any(Context::class.java),
any(UUID::class.java),
- captor.capture())
+ captor.capture()
+ )
assertThat(result, `is`(instanceOf(ListenableWorker.Result.Success::class.java)))
val recent = captor.allValues.lastOrNull()
assertThat(recent?.getInt(ProgressUpdatingWorker.Progress, 0), `is`(100))
@@ -230,7 +239,8 @@
.updateProgress(
any(Context::class.java),
any(UUID::class.java),
- captor.capture())
+ captor.capture()
+ )
assertThat(result, `is`(instanceOf(ListenableWorker.Result.Success::class.java)))
val recent = captor.allValues.lastOrNull()
assertThat(recent?.getInt(ProgressUpdatingWorker.Progress, 0), `is`(100))
diff --git a/work/workmanager-ktx/src/androidTest/java/androidx/work/DataTest.kt b/work/workmanager-ktx/src/androidTest/java/androidx/work/DataTest.kt
index 40fe5a1..f21fcd4 100644
--- a/work/workmanager-ktx/src/androidTest/java/androidx/work/DataTest.kt
+++ b/work/workmanager-ktx/src/androidTest/java/androidx/work/DataTest.kt
@@ -30,10 +30,12 @@
class DataTest {
@Test
fun testDataExtensions() {
- val data = workDataOf("one" to 1,
- "two" to 2L,
- "three" to "Three",
- "four" to longArrayOf(1L, 2L))
+ val data = workDataOf(
+ "one" to 1,
+ "two" to 2L,
+ "three" to "Three",
+ "four" to longArrayOf(1L, 2L)
+ )
assertEquals(data.getInt("one", 0), 1)
assertEquals(data.getLong("two", 0L), 2L)
assertEquals(data.getString("three"), "Three")
diff --git a/work/workmanager-ktx/src/androidTest/java/androidx/work/OneTimeWorkRequestTest.kt b/work/workmanager-ktx/src/androidTest/java/androidx/work/OneTimeWorkRequestTest.kt
index e6c1be1..579a282 100644
--- a/work/workmanager-ktx/src/androidTest/java/androidx/work/OneTimeWorkRequestTest.kt
+++ b/work/workmanager-ktx/src/androidTest/java/androidx/work/OneTimeWorkRequestTest.kt
@@ -32,8 +32,10 @@
builder.setInputMerger(ArrayCreatingInputMerger::class)
val request = builder.build()
assertEquals(request.workSpec.workerClassName, TestWorker::class.java.name)
- assertEquals(request.workSpec.inputMergerClassName,
- ArrayCreatingInputMerger::class.java.name)
+ assertEquals(
+ request.workSpec.inputMergerClassName,
+ ArrayCreatingInputMerger::class.java.name
+ )
}
@Test
@@ -41,7 +43,9 @@
val builder = OneTimeWorkRequestBuilder<TestWorker>()
val request = builder.build()
assertEquals(request.workSpec.workerClassName, TestWorker::class.java.name)
- assertEquals(request.workSpec.inputMergerClassName,
- OverwritingInputMerger::class.java.name)
+ assertEquals(
+ request.workSpec.inputMergerClassName,
+ OverwritingInputMerger::class.java.name
+ )
}
}
diff --git a/work/workmanager-ktx/src/androidTest/java/androidx/work/PeriodicWorkRequestTest.kt b/work/workmanager-ktx/src/androidTest/java/androidx/work/PeriodicWorkRequestTest.kt
index 204c5f6..f406101 100644
--- a/work/workmanager-ktx/src/androidTest/java/androidx/work/PeriodicWorkRequestTest.kt
+++ b/work/workmanager-ktx/src/androidTest/java/androidx/work/PeriodicWorkRequestTest.kt
@@ -32,8 +32,9 @@
@Test
fun testPeriodicWorkRequestBuilder() {
val builder = PeriodicWorkRequestBuilder<TestWorker>(
- repeatInterval = 15L,
- repeatIntervalTimeUnit = TimeUnit.MINUTES)
+ repeatInterval = 15L,
+ repeatIntervalTimeUnit = TimeUnit.MINUTES
+ )
val workRequest = builder.build()
assertEquals(workRequest.workSpec.workerClassName, TestWorker::class.java.name)
assertEquals(workRequest.workSpec.isPeriodic, true)
@@ -56,10 +57,11 @@
@Test
fun testPeriodicWorkRequestBuilder_withFlexTime() {
val builder = PeriodicWorkRequestBuilder<TestWorker>(
- repeatInterval = 15L,
- repeatIntervalTimeUnit = TimeUnit.MINUTES,
- flexTimeInterval = 10L,
- flexTimeIntervalUnit = TimeUnit.MINUTES)
+ repeatInterval = 15L,
+ repeatIntervalTimeUnit = TimeUnit.MINUTES,
+ flexTimeInterval = 10L,
+ flexTimeIntervalUnit = TimeUnit.MINUTES
+ )
val workRequest = builder.build()
assertEquals(workRequest.workSpec.workerClassName, TestWorker::class.java.name)
assertEquals(workRequest.workSpec.isPeriodic, true)
@@ -72,8 +74,9 @@
val repeatInterval = Duration.ofHours(3).plusMinutes(25)
val flexInterval = repeatInterval.minusMinutes(15)
val builder = PeriodicWorkRequestBuilder<TestWorker>(
- repeatInterval = repeatInterval,
- flexTimeInterval = flexInterval)
+ repeatInterval = repeatInterval,
+ flexTimeInterval = flexInterval
+ )
val workRequest = builder.build()
assertEquals(workRequest.workSpec.workerClassName, TestWorker::class.java.name)
assertEquals(workRequest.workSpec.isPeriodic, true)
diff --git a/work/workmanager-ktx/src/main/java/androidx/work/ListenableFuture.kt b/work/workmanager-ktx/src/main/java/androidx/work/ListenableFuture.kt
index 51504ab..8704fe3 100644
--- a/work/workmanager-ktx/src/main/java/androidx/work/ListenableFuture.kt
+++ b/work/workmanager-ktx/src/main/java/androidx/work/ListenableFuture.kt
@@ -44,16 +44,19 @@
}
}
return suspendCancellableCoroutine { cancellableContinuation ->
- addListener(Runnable {
- try {
- cancellableContinuation.resume(get())
- } catch (throwable: Throwable) {
- val cause = throwable.cause ?: throwable
- when (throwable) {
- is CancellationException -> cancellableContinuation.cancel(cause)
- else -> cancellableContinuation.resumeWithException(cause)
+ addListener(
+ Runnable {
+ try {
+ cancellableContinuation.resume(get())
+ } catch (throwable: Throwable) {
+ val cause = throwable.cause ?: throwable
+ when (throwable) {
+ is CancellationException -> cancellableContinuation.cancel(cause)
+ else -> cancellableContinuation.resumeWithException(cause)
+ }
}
- }
- }, DirectExecutor.INSTANCE)
+ },
+ DirectExecutor.INSTANCE
+ )
}
}
diff --git a/work/workmanager-ktx/src/main/java/androidx/work/OneTimeWorkRequest.kt b/work/workmanager-ktx/src/main/java/androidx/work/OneTimeWorkRequest.kt
index e161c11..3b8a6e9 100644
--- a/work/workmanager-ktx/src/main/java/androidx/work/OneTimeWorkRequest.kt
+++ b/work/workmanager-ktx/src/main/java/androidx/work/OneTimeWorkRequest.kt
@@ -26,7 +26,7 @@
* Creates a [OneTimeWorkRequest] with the given [ListenableWorker].
*/
inline fun <reified W : ListenableWorker> OneTimeWorkRequestBuilder() =
- OneTimeWorkRequest.Builder(W::class.java)
+ OneTimeWorkRequest.Builder(W::class.java)
/**
* Sets an [InputMerger] on the [OneTimeWorkRequest.Builder].
diff --git a/work/workmanager-ktx/src/main/java/androidx/work/PeriodicWorkRequest.kt b/work/workmanager-ktx/src/main/java/androidx/work/PeriodicWorkRequest.kt
index f5c453a..ac7c657 100644
--- a/work/workmanager-ktx/src/main/java/androidx/work/PeriodicWorkRequest.kt
+++ b/work/workmanager-ktx/src/main/java/androidx/work/PeriodicWorkRequest.kt
@@ -61,11 +61,12 @@
): PeriodicWorkRequest.Builder {
return PeriodicWorkRequest.Builder(
- W::class.java,
- repeatInterval,
- repeatIntervalTimeUnit,
- flexTimeInterval,
- flexTimeIntervalUnit)
+ W::class.java,
+ repeatInterval,
+ repeatIntervalTimeUnit,
+ flexTimeInterval,
+ flexTimeIntervalUnit
+ )
}
/**
diff --git a/work/workmanager-lint/src/main/java/androidx/work/lint/PeriodicEnqueueIssueDetector.kt b/work/workmanager-lint/src/main/java/androidx/work/lint/PeriodicEnqueueIssueDetector.kt
index 3f14013..61d708f 100644
--- a/work/workmanager-lint/src/main/java/androidx/work/lint/PeriodicEnqueueIssueDetector.kt
+++ b/work/workmanager-lint/src/main/java/androidx/work/lint/PeriodicEnqueueIssueDetector.kt
@@ -55,8 +55,8 @@
val periodic = node.valueArguments.filter { argument ->
val type = argument.getExpressionType()?.canonicalText
type == "androidx.work.PeriodicWorkRequest" ||
- type == "java.util.List<? extends androidx.work.PeriodicWorkRequest>" ||
- type == "java.util.List<? extends androidx.work.WorkRequest>"
+ type == "java.util.List<? extends androidx.work.PeriodicWorkRequest>" ||
+ type == "java.util.List<? extends androidx.work.WorkRequest>"
}
if (periodic.isNotEmpty()) {
context.report(
diff --git a/work/workmanager-lint/src/main/java/androidx/work/lint/RemoveWorkManagerInitializerDetector.kt b/work/workmanager-lint/src/main/java/androidx/work/lint/RemoveWorkManagerInitializerDetector.kt
index a300883..c988b43 100644
--- a/work/workmanager-lint/src/main/java/androidx/work/lint/RemoveWorkManagerInitializerDetector.kt
+++ b/work/workmanager-lint/src/main/java/androidx/work/lint/RemoveWorkManagerInitializerDetector.kt
@@ -47,7 +47,7 @@
companion object {
private const val DESCRIPTION = "Remove androidx.work.impl.WorkManagerInitializer from " +
- "your AndroidManifest.xml when using on-demand initialization."
+ "your AndroidManifest.xml when using on-demand initialization."
val ISSUE = Issue.create(
id = "RemoveWorkManagerInitializer",
diff --git a/work/workmanager-lint/src/main/java/androidx/work/lint/SpecifyForegroundServiceTypeIssueDetector.kt b/work/workmanager-lint/src/main/java/androidx/work/lint/SpecifyForegroundServiceTypeIssueDetector.kt
index 760154c..0d6e67d 100644
--- a/work/workmanager-lint/src/main/java/androidx/work/lint/SpecifyForegroundServiceTypeIssueDetector.kt
+++ b/work/workmanager-lint/src/main/java/androidx/work/lint/SpecifyForegroundServiceTypeIssueDetector.kt
@@ -100,7 +100,7 @@
issue = ISSUE,
location = context.getLocation(node),
message = "Missing $name foregroundServiceType in " +
- "the AndroidManifest.xml"
+ "the AndroidManifest.xml"
)
}
}
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/BadConfigurationProviderTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/BadConfigurationProviderTest.kt
index 2dfbfe0..345bf8c 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/BadConfigurationProviderTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/BadConfigurationProviderTest.kt
@@ -87,10 +87,12 @@
invalidProvider
).issues(BadConfigurationProviderIssueDetector.ISSUE)
.run()
- .expect("""
+ .expect(
+ """
src/com/example/App.kt: Error: Expected Application subtype to implement Configuration.Provider [BadConfigurationProvider]
1 errors, 0 warnings
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
}
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt
index 3110fea..e0508e3 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt
@@ -70,7 +70,7 @@
val builder = PeriodicWorkRequest.Builder(worker, 15L, TimeUnit.MILLISECONDS)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 errors, 0 warnings
- """.trimIndent()
+ """.trimIndent()
)
/* ktlint-enable max-line-length */
}
@@ -165,7 +165,7 @@
val builder = PeriodicWorkRequest.Builder(worker, Duration.ofNanos(15))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 errors, 0 warnings
- """.trimIndent()
+ """.trimIndent()
)
/* ktlint-enable max-line-length */
}
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/PeriodicEnqueueIssueDetectorTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/PeriodicEnqueueIssueDetectorTest.kt
index 387df2a..7b4b9f8 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/PeriodicEnqueueIssueDetectorTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/PeriodicEnqueueIssueDetectorTest.kt
@@ -55,12 +55,14 @@
snippet
).issues(PeriodicEnqueueIssueDetector.ISSUE)
.run()
- .expect("""
+ .expect(
+ """
src/androidx/work/WorkManager.kt:4: Warning: Use enqueueUniquePeriodicWork() instead of enqueue() [BadPeriodicWorkRequestEnqueue]
fun enqueue(request: WorkRequest)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 errors, 1 warnings
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
}
@@ -93,12 +95,14 @@
snippet
).issues(PeriodicEnqueueIssueDetector.ISSUE)
.run()
- .expect("""
+ .expect(
+ """
src/androidx/work/WorkManager.kt:5: Warning: Use enqueueUniquePeriodicWork() instead of enqueue() [BadPeriodicWorkRequestEnqueue]
fun enqueue(requests: List<WorkRequest>)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 errors, 1 warnings
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
}
@@ -133,12 +137,14 @@
snippet
).issues(PeriodicEnqueueIssueDetector.ISSUE)
.run()
- .expect("""
+ .expect(
+ """
src/androidx/work/WorkManager.kt:5: Warning: Use enqueueUniquePeriodicWork() instead of enqueue() [BadPeriodicWorkRequestEnqueue]
fun enqueue(requests: List<WorkRequest>)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 errors, 1 warnings
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
}
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/RemoveWorkManagerInitializerDetectorTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/RemoveWorkManagerInitializerDetectorTest.kt
index 51a7dc2..98aa770 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/RemoveWorkManagerInitializerDetectorTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/RemoveWorkManagerInitializerDetectorTest.kt
@@ -157,10 +157,12 @@
customApplication
).issues(RemoveWorkManagerInitializerDetector.ISSUE)
.run()
- .expect("""
+ .expect(
+ """
project0: Error: Remove androidx.work.impl.WorkManagerInitializer from your AndroidManifest.xml when using on-demand initialization. [RemoveWorkManagerInitializer]
1 errors, 0 warnings
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
}
@@ -209,12 +211,14 @@
customApplication
).issues(RemoveWorkManagerInitializerDetector.ISSUE)
.run()
- .expect("""
+ .expect(
+ """
AndroidManifest.xml:5: Error: Remove androidx.work.impl.WorkManagerInitializer from your AndroidManifest.xml when using on-demand initialization. [RemoveWorkManagerInitializer]
<provider
^
1 errors, 0 warnings
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
}
}
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/RxWorkerSetProgressDetectorTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/RxWorkerSetProgressDetectorTest.kt
index e2a5fc9..2b33c84 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/RxWorkerSetProgressDetectorTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/RxWorkerSetProgressDetectorTest.kt
@@ -53,14 +53,16 @@
worker.setProgress()
~~~~~~~~~~~~~~~~~~~~
1 errors, 0 warnings
- """.trimIndent()
+ """.trimIndent()
)
- .expectFixDiffs("""
+ .expectFixDiffs(
+ """
Fix for src/com/example/App.kt line 8: Use setCompletableProgress instead:
@@ -8 +8
- worker.setProgress()
+ worker.setCompletableProgress()
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
}
}
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/SpecifyForegroundServiceTypeIssueDetectorTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/SpecifyForegroundServiceTypeIssueDetectorTest.kt
index f00b936..fcc25223 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/SpecifyForegroundServiceTypeIssueDetectorTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/SpecifyForegroundServiceTypeIssueDetectorTest.kt
@@ -57,7 +57,7 @@
val info = ForegroundInfo(0, notification, 1)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 errors, 0 warnings
- """.trimIndent()
+ """.trimIndent()
)
/* ktlint-enable max-line-length */
}
@@ -115,7 +115,7 @@
val info = ForegroundInfo(0, notification, 9)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 errors, 0 warnings
- """.trimIndent()
+ """.trimIndent()
)
/* ktlint-enable max-line-length */
}
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/SpecifyJobSchedulerIdRangeIssueDetectorTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/SpecifyJobSchedulerIdRangeIssueDetectorTest.kt
index d19fbd9..76e8132 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/SpecifyJobSchedulerIdRangeIssueDetectorTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/SpecifyJobSchedulerIdRangeIssueDetectorTest.kt
@@ -51,7 +51,7 @@
class TestJobService: JobService() {
^
0 errors, 1 warnings
- """.trimIndent()
+ """.trimIndent()
)
/* ktlint-enable max-line-length */
}
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/Stubs.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/Stubs.kt
index a3bf923..45855a3 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/Stubs.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/Stubs.kt
@@ -23,7 +23,8 @@
object Stubs {
val WORKER_FACTORY: TestFile = kotlin(
- "androidx/work/WorkerFactory.kt", """
+ "androidx/work/WorkerFactory.kt",
+ """
package androidx.work
open class WorkerFactory
@@ -145,7 +146,8 @@
).indented().within("src")
val CONSTRAINTS: TestFile = java(
- "androidx/work/Constraints.java", """
+ "androidx/work/Constraints.java",
+ """
package androidx.work;
class Constraints {
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/WorkerHasPublicModifierDetectorTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/WorkerHasPublicModifierDetectorTest.kt
index fb2561b..b9966a0 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/WorkerHasPublicModifierDetectorTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/WorkerHasPublicModifierDetectorTest.kt
@@ -44,12 +44,14 @@
worker
).issues(WorkerHasPublicModifierDetector.ISSUE)
.run()
- .expect("""
+ .expect(
+ """
src/com/example/Worker.kt:5: Error: com.example.Worker needs to be public [WorkerHasAPublicModifier]
private class Worker: ListenableWorker()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 errors, 0 warnings
- """.trimIndent())
+ """.trimIndent()
+ )
/* ktlint-enable max-line-length */
}
diff --git a/work/workmanager/src/androidTest/java/androidx/work/DelegatingWorkerFactoryTest.kt b/work/workmanager/src/androidTest/java/androidx/work/DelegatingWorkerFactoryTest.kt
index 51f6056..cc68256 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/DelegatingWorkerFactoryTest.kt
+++ b/work/workmanager/src/androidTest/java/androidx/work/DelegatingWorkerFactoryTest.kt
@@ -91,17 +91,17 @@
progressUpdater: ProgressUpdater,
foregroundUpdater: ForegroundUpdater
) = WorkerParameters(
- UUID.randomUUID(),
- Data.EMPTY,
- listOf<String>(),
- WorkerParameters.RuntimeExtras(),
- 1,
- SynchronousExecutor(),
- WorkManagerTaskExecutor(SynchronousExecutor()),
- factory,
- progressUpdater,
- foregroundUpdater
- )
+ UUID.randomUUID(),
+ Data.EMPTY,
+ listOf<String>(),
+ WorkerParameters.RuntimeExtras(),
+ 1,
+ SynchronousExecutor(),
+ WorkManagerTaskExecutor(SynchronousExecutor()),
+ factory,
+ progressUpdater,
+ foregroundUpdater
+ )
}
class NoOpFactory : WorkerFactory() {
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java
index ce850422..ad2f152 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/WorkerWrapperTest.java
@@ -978,6 +978,7 @@
workerWrapper.interrupt();
Thread.sleep(1000L);
assertThat(listener.mResult, is(true));
+ assertThat(mWorkSpecDao.getState(work.getStringId()), is(ENQUEUED));
}
@Test
@@ -996,6 +997,7 @@
workerWrapper.interrupt();
Thread.sleep(1000L);
assertThat(listener.mResult, is(true));
+ assertThat(mWorkSpecDao.getState(work.getStringId()), is(ENQUEUED));
verify(mMockScheduler).cancel(work.getStringId());
}
@@ -1074,6 +1076,7 @@
Executors.newSingleThreadExecutor().submit(workerWrapper);
workerWrapper.interrupt();
assertThat(worker.isStopped(), is(true));
+ assertThat(mWorkSpecDao.getState(work.getStringId()), is(ENQUEUED));
}
@Test
@@ -1108,6 +1111,7 @@
Executors.newSingleThreadExecutor().submit(workerWrapper);
workerWrapper.interrupt();
assertThat(worker.isStopped(), is(true));
+ assertThat(mWorkSpecDao.getState(work.getStringId()), is(ENQUEUED));
}
@Test
diff --git a/work/workmanager/src/androidTest/java/androidx/work/impl/foreground/WorkerWrapperForegroundTest.kt b/work/workmanager/src/androidTest/java/androidx/work/impl/foreground/WorkerWrapperForegroundTest.kt
index 8d660e5..1d6a142 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/impl/foreground/WorkerWrapperForegroundTest.kt
+++ b/work/workmanager/src/androidTest/java/androidx/work/impl/foreground/WorkerWrapperForegroundTest.kt
@@ -157,10 +157,13 @@
wrapper.run()
val future = wrapper.future as SettableFuture<Boolean>
val latch = CountDownLatch(1)
- future.addListener(Runnable {
- assertThat(future.isDone, `is`(true))
- latch.countDown()
- }, executor)
+ future.addListener(
+ Runnable {
+ assertThat(future.isDone, `is`(true))
+ latch.countDown()
+ },
+ executor
+ )
latch.await(5, TimeUnit.SECONDS)
assertThat(latch.count, `is`(0L))
diff --git a/work/workmanager/src/main/java/androidx/work/impl/Scheduler.java b/work/workmanager/src/main/java/androidx/work/impl/Scheduler.java
index 4779722..f60e66f 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/Scheduler.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/Scheduler.java
@@ -33,6 +33,12 @@
int MAX_SCHEDULER_LIMIT = 50;
/**
+ * The maximum number of {@link WorkSpec}s that are considered for execution by the greedy
+ * scheduler.
+ */
+ int MAX_GREEDY_SCHEDULER_LIMIT = 200;
+
+ /**
* Schedule the given {@link WorkSpec}s for background execution. The Scheduler does NOT need
* to check if there are any dependencies.
*
diff --git a/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java b/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java
index d2caaf4..b43c623 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/Schedulers.java
@@ -16,6 +16,7 @@
package androidx.work.impl;
+import static androidx.work.impl.Scheduler.MAX_GREEDY_SCHEDULER_LIMIT;
import static androidx.work.impl.utils.PackageManagerHelper.setComponentEnabled;
import android.content.Context;
@@ -74,7 +75,8 @@
configuration.getMaxSchedulerLimit());
// Enqueued workSpecs when scheduling limits are NOT applicable.
- allEligibleWorkSpecs = workSpecDao.getAllEligibleWorkSpecsForScheduling();
+ allEligibleWorkSpecs = workSpecDao.getAllEligibleWorkSpecsForScheduling(
+ MAX_GREEDY_SCHEDULER_LIMIT);
if (eligibleWorkSpecsForLimitedSlots != null
&& eligibleWorkSpecsForLimitedSlots.size() > 0) {
diff --git a/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java b/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java
index eec4054..76bbf74 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/WorkerWrapper.java
@@ -439,7 +439,9 @@
mAppContext, RescheduleReceiver.class, false);
}
if (needsReschedule) {
+ // Set state to ENQUEUED again.
// Reset scheduled state so its picked up by background schedulers again.
+ mWorkSpecDao.setState(ENQUEUED, mWorkSpecId);
mWorkSpecDao.markWorkSpecScheduled(mWorkSpecId, SCHEDULE_NOT_REQUESTED_YET);
}
if (mWorkSpec != null && mWorker != null && mWorker.isRunInForeground()) {
diff --git a/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpecDao.java b/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpecDao.java
index a1ef4cdb..68b0e28 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpecDao.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/model/WorkSpecDao.java
@@ -313,8 +313,9 @@
+ "state=" + WorkTypeConverters.StateIds.ENQUEUED
// Order by period start time so we execute scheduled WorkSpecs in FIFO order
+ " ORDER BY period_start_time"
+ + " LIMIT :maxLimit"
)
- List<WorkSpec> getAllEligibleWorkSpecsForScheduling();
+ List<WorkSpec> getAllEligibleWorkSpecsForScheduling(int maxLimit);
/**
* @return The List of {@link WorkSpec}s that are unfinished and scheduled.
diff --git a/work/workmanager/src/main/java/androidx/work/impl/workers/DiagnosticsWorker.java b/work/workmanager/src/main/java/androidx/work/impl/workers/DiagnosticsWorker.java
index a67c3b1..3f20289 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/workers/DiagnosticsWorker.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/workers/DiagnosticsWorker.java
@@ -16,6 +16,8 @@
package androidx.work.impl.workers;
+import static androidx.work.impl.Scheduler.MAX_GREEDY_SCHEDULER_LIMIT;
+
import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
@@ -64,7 +66,8 @@
long startAt = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
List<WorkSpec> completed = workSpecDao.getRecentlyCompletedWork(startAt);
List<WorkSpec> running = workSpecDao.getRunningWork();
- List<WorkSpec> enqueued = workSpecDao.getAllEligibleWorkSpecsForScheduling();
+ List<WorkSpec> enqueued = workSpecDao.getAllEligibleWorkSpecsForScheduling(
+ MAX_GREEDY_SCHEDULER_LIMIT);
if (completed != null && !completed.isEmpty()) {
Logger.get().info(TAG, "Recently completed work:\n\n");