0

Android: Add @MonotonicNonNull and use it in a few spots

Support for this annotation was recently added to NullAway. It removes
some uses of assumeNonNull().

Note: It does not yet work with static fields. Reported here:
https://github.com/uber/NullAway/issues/1148#issuecomment-2707363431

Bug: 389129271
Change-Id: I1c24769b48cb381ba6a5974b24d04f2c772d226d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6334458
Owners-Override: Andrew Grieve <agrieve@chromium.org>
Auto-Submit: Andrew Grieve <agrieve@chromium.org>
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1429766}
This commit is contained in:
Andrew Grieve
2025-03-07 14:39:27 -08:00
committed by Chromium LUCI CQ
parent 7b361016e7
commit bcbaa357ad
5 changed files with 44 additions and 6 deletions
build/android
BUILD.gn
java
src
org
chromium
build
components
browser_ui
site_settings
android
java
src
org
chromium
components
browser_ui
messages
android
java
src
org
chromium
components
styleguide/java

@ -56,6 +56,7 @@ if (enable_java_templates) {
"java/src/org/chromium/build/annotations/IdentifierNameString.java",
"java/src/org/chromium/build/annotations/Initializer.java",
"java/src/org/chromium/build/annotations/MockedInTests.java",
"java/src/org/chromium/build/annotations/MonotonicNonNull.java",
"java/src/org/chromium/build/annotations/NullMarked.java",
"java/src/org/chromium/build/annotations/NullUnmarked.java",
"java/src/org/chromium/build/annotations/Nullable.java",

@ -0,0 +1,20 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.build.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Fields that are never null once becoming non-null. Use to avoid warnings when such fields are
* accessed by lambdas after being assigned.
*
* <p>See: https://github.com/uber/NullAway/wiki/Supported-Annotations
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.CLASS)
public @interface MonotonicNonNull {}

@ -15,6 +15,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceDialogFragmentCompat;
import org.chromium.base.Callback;
import org.chromium.build.annotations.MonotonicNonNull;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.ui.base.ViewUtils;
@ -28,7 +29,7 @@ public class ClearWebsiteStorageDialog extends PreferenceDialogFragmentCompat {
private static @Nullable Callback<Boolean> sCallback;
// The view containing the dialog ui elements.
private @Nullable View mDialogView;
private @MonotonicNonNull View mDialogView;
public static ClearWebsiteStorageDialog newInstance(
Preference preference, Callback<Boolean> callback, boolean isGroup) {
@ -65,7 +66,7 @@ public class ClearWebsiteStorageDialog extends PreferenceDialogFragmentCompat {
.post(
() -> {
ViewUtils.requestLayout(
assumeNonNull(mDialogView),
mDialogView,
"ClearWebsiteStorageDialog.onConfigurationChanged"
+ " Runnable");
});

@ -4,8 +4,6 @@
package org.chromium.components.messages;
import static org.chromium.build.NullUtil.assumeNonNull;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
@ -18,6 +16,7 @@ import org.jni_zero.CalledByNative;
import org.jni_zero.JNINamespace;
import org.jni_zero.NativeMethods;
import org.chromium.build.annotations.MonotonicNonNull;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.ui.base.WindowAndroid;
@ -31,10 +30,11 @@ import org.chromium.ui.modelutil.PropertyModel;
public final class MessageWrapper implements ListMenu.Delegate {
private long mNativeMessageWrapper;
private final PropertyModel mMessageProperties;
private @Nullable MessageSecondaryMenuItems mMessageSecondaryMenuItems;
private @MonotonicNonNull MessageSecondaryMenuItems mMessageSecondaryMenuItems;
/**
* Creates an instance of MessageWrapper and links it with native MessageWrapper object.
*
* @param nativeMessageWrapper Pointer to native MessageWrapper.
* @param messageIdentifier Message identifier of the new message.
* @return reference to created MessageWrapper.
@ -137,7 +137,7 @@ public final class MessageWrapper implements ListMenu.Delegate {
mMessageProperties.set(MessageBannerProperties.SECONDARY_MENU_MAX_SIZE, maxSize);
mMessageProperties.set(
MessageBannerProperties.SECONDARY_MENU_BUTTON_DELEGATE,
() -> assumeNonNull(mMessageSecondaryMenuItems).createListMenu(context, this));
() -> mMessageSecondaryMenuItems.createListMenu(context, this));
}
}

@ -116,6 +116,22 @@ private boolean isParamNonNull(@Nullable String foo) {
}
```
### Field Annotations
```java
// Starts as null, but may not be assigned a nullable value.
private @MonotonicNonNull String mSomeValue;
public void doThing(String value) {
// Emits a warning since mSomeValue is nullable:
helper(mSomeValue);
mSomeValue = value;
// No warning about mSomeValue being nullable, even though it's used in a lambda.
PostTask.postTask(TaskTraits.USER_BLOCKING, () -> helper(mSomeValue));
}
```
### "assert", "assumeNonNull()", and "requireNonNull()"
```java