diff --git a/api/BUILD b/api/BUILD index 4e98a80d..e3ab0443 100644 --- a/api/BUILD +++ b/api/BUILD @@ -112,7 +112,10 @@ java_library( name = "stack_getter_common", srcs = STACK_GETTER_COMMON_SRCS, javacopts = ["-source 8 -target 8"], - deps = [":checks"], + deps = [ + ":checks", + "@google_bazel_common//third_party/java/jspecify_annotations", + ], ) java_library( diff --git a/api/src/main/java/com/google/common/flogger/DurationRateLimiter.java b/api/src/main/java/com/google/common/flogger/DurationRateLimiter.java index 1f947fad..26088ee0 100644 --- a/api/src/main/java/com/google/common/flogger/DurationRateLimiter.java +++ b/api/src/main/java/com/google/common/flogger/DurationRateLimiter.java @@ -107,7 +107,7 @@ public int hashCode() { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof RateLimitPeriod) { RateLimitPeriod that = (RateLimitPeriod) obj; return this.n == that.n && this.unit == that.unit; diff --git a/api/src/main/java/com/google/common/flogger/LogContext.java b/api/src/main/java/com/google/common/flogger/LogContext.java index e9a9bf2c..c48f723f 100644 --- a/api/src/main/java/com/google/common/flogger/LogContext.java +++ b/api/src/main/java/com/google/common/flogger/LogContext.java @@ -329,15 +329,19 @@ public String toString() { private final long timestampNanos; /** Additional metadata for this log statement (added via fluent API methods). */ - private MutableMetadata metadata = null; + private @Nullable MutableMetadata metadata = null; + /** The log site information for this log statement (set immediately prior to post-processing). */ - private LogSite logSite = null; + private @Nullable LogSite logSite = null; + /** Rate limit status (only set if rate limiting occurs). */ - private RateLimitStatus rateLimitStatus = null; + private @Nullable RateLimitStatus rateLimitStatus = null; + /** The template context if formatting is required (set only after post-processing). */ - private TemplateContext templateContext = null; + private @Nullable TemplateContext templateContext = null; + /** The log arguments (set only after post-processing). */ - private Object[] args = null; + private Object @Nullable [] args = null; /** * Creates a logging context with the specified level, and with a timestamp obtained from the @@ -758,7 +762,7 @@ private void logImpl(String message, Object... args) { // ---- Log site injection (used by pre-processors and special cases) ---- @Override - public final API withInjectedLogSite(LogSite logSite) { + public final API withInjectedLogSite(@Nullable LogSite logSite) { // First call wins (since auto-injection will typically target the log() method at the end of // the chain and might not check for previous explicit injection). In particular it MUST be // allowed for a caller to specify the "INVALID" log site, and have that set the field here to diff --git a/api/src/main/java/com/google/common/flogger/LogSite.java b/api/src/main/java/com/google/common/flogger/LogSite.java index 9ec217fd..b3e6a138 100644 --- a/api/src/main/java/com/google/common/flogger/LogSite.java +++ b/api/src/main/java/com/google/common/flogger/LogSite.java @@ -44,11 +44,11 @@ public abstract class LogSite implements LogSiteKey { /** * An singleton LogSite instance used to indicate that valid log site information cannot be * determined. This can be used to indicate that log site information is not available by - * injecting it via {@link LoggingApi#withInjectedLogSite} which will suppress any further - * log site analysis for that log statement. This is also returned if stack trace analysis - * fails for any reason. - *

- * If a log statement does end up with invalid log site information, then any fluent logging + * injecting it via {@link LoggingApi#withInjectedLogSite} which will suppress any further log + * site analysis for that log statement. This is also returned if stack trace analysis fails for + * any reason. + * + *

If a log statement does end up with invalid log site information, then any fluent logging * methods which rely on being able to look up site specific metadata will be disabled and * essentially become "no ops". */ @@ -70,7 +70,7 @@ public int getLineNumber() { } @Override - public String getFileName() { + public @Nullable String getFileName() { return null; } // No need to implement equals() or hashCode() for a singleton instance. @@ -194,7 +194,7 @@ public int getLineNumber() { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof InjectedLogSite) { InjectedLogSite other = (InjectedLogSite) obj; // Probably not worth optimizing for "this == obj" because all strings should be interned. diff --git a/api/src/main/java/com/google/common/flogger/MetadataKey.java b/api/src/main/java/com/google/common/flogger/MetadataKey.java index 2f6b6bf6..7bf746c5 100644 --- a/api/src/main/java/com/google/common/flogger/MetadataKey.java +++ b/api/src/main/java/com/google/common/flogger/MetadataKey.java @@ -277,7 +277,7 @@ public final int hashCode() { } @Override - public final boolean equals(Object obj) { + public final boolean equals(@Nullable Object obj) { return super.equals(obj); } diff --git a/api/src/main/java/com/google/common/flogger/backend/FormatChar.java b/api/src/main/java/com/google/common/flogger/backend/FormatChar.java index 085c0861..db7816ea 100644 --- a/api/src/main/java/com/google/common/flogger/backend/FormatChar.java +++ b/api/src/main/java/com/google/common/flogger/backend/FormatChar.java @@ -16,6 +16,8 @@ package com.google.common.flogger.backend; +import org.jspecify.annotations.Nullable; + /** * An enum representing the printf-like formatting characters that must be supported by all logging * backends. It is important to note that while backends must accept any of these format specifiers, @@ -129,10 +131,10 @@ private static boolean isLowerCase(char letter) { } /** - * Returns the FormatChar instance associated with the given printf format specifier. If the - * given character is not an ASCII letter, a runtime exception is thrown. + * Returns the FormatChar instance associated with the given printf format specifier. If the given + * character is not an ASCII letter, a runtime exception is thrown. */ - public static FormatChar of(char c) { + public static @Nullable FormatChar of(char c) { // Get from the map by converting the char to lower-case (which is the most common case by far). // If the given value wasn't an ASCII letter then the index will be out-of-range, but when // called by the parser, it's always guaranteed to be an ASCII letter (but perhaps not a valid diff --git a/api/src/main/java/com/google/common/flogger/backend/KeyValueFormatter.java b/api/src/main/java/com/google/common/flogger/backend/KeyValueFormatter.java index 40b3f063..79abdddc 100644 --- a/api/src/main/java/com/google/common/flogger/backend/KeyValueFormatter.java +++ b/api/src/main/java/com/google/common/flogger/backend/KeyValueFormatter.java @@ -70,12 +70,13 @@ public final class KeyValueFormatter implements KeyValueHandler { Double.class)); /** - * Helper method to emit metadata key/value pairs in a format consistent with JSON. String - * values which need to be quoted are JSON escaped, while other values are appended without - * quoting or escaping. Labels are expected to be JSON "safe", and are never quoted. This format - * is compatible with various "lightweight" JSON representations. + * Helper method to emit metadata key/value pairs in a format consistent with JSON. String values + * which need to be quoted are JSON escaped, while other values are appended without quoting or + * escaping. Labels are expected to be JSON "safe", and are never quoted. This format is + * compatible with various "lightweight" JSON representations. */ - public static void appendJsonFormattedKeyAndValue(String label, Object value, StringBuilder out) { + public static void appendJsonFormattedKeyAndValue( + String label, @Nullable Object value, StringBuilder out) { out.append(label).append('='); // We could also consider enums as safe if we used name() rather than toString(). if (value == null) { diff --git a/api/src/main/java/com/google/common/flogger/backend/MessageUtils.java b/api/src/main/java/com/google/common/flogger/backend/MessageUtils.java index a37a9116..8cf38369 100644 --- a/api/src/main/java/com/google/common/flogger/backend/MessageUtils.java +++ b/api/src/main/java/com/google/common/flogger/backend/MessageUtils.java @@ -29,6 +29,7 @@ import java.util.FormattableFlags; import java.util.Formatter; import java.util.Locale; +import org.jspecify.annotations.Nullable; /** * Static utilities for classes wishing to implement their own log message formatting. None of the @@ -82,7 +83,7 @@ public static String safeToString(Object value) { * @param value the value to be formatted (possibly null). * @return a non-null string representation of the given value (possibly "null"). */ - private static String toNonNullString(Object value) { + private static String toNonNullString(@Nullable Object value) { if (value == null) { return "null"; } diff --git a/api/src/main/java/com/google/common/flogger/backend/MetadataHandler.java b/api/src/main/java/com/google/common/flogger/backend/MetadataHandler.java index d39bc15c..a764c297 100644 --- a/api/src/main/java/com/google/common/flogger/backend/MetadataHandler.java +++ b/api/src/main/java/com/google/common/flogger/backend/MetadataHandler.java @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import org.jspecify.annotations.Nullable; /** * Callback API for logger backend implementations to handle metadata keys/values. The API methods @@ -150,7 +151,7 @@ public void handle(MetadataKey key, Iterator value, Object conte private final Map, RepeatedValueHandler> repeatedValueHandlers = new HashMap, RepeatedValueHandler>(); private final ValueHandler defaultHandler; - private RepeatedValueHandler defaultRepeatedHandler = null; + private @Nullable RepeatedValueHandler defaultRepeatedHandler = null; private Builder(ValueHandler defaultHandler) { this.defaultHandler = checkNotNull(defaultHandler, "default handler"); @@ -289,7 +290,7 @@ private static final class MapBasedhandler extends MetadataHandler { private final Map, RepeatedValueHandler> repeatedValueHandlers = new HashMap, RepeatedValueHandler>(); private final ValueHandler defaultHandler; - private final RepeatedValueHandler defaultRepeatedHandler; + private final @Nullable RepeatedValueHandler defaultRepeatedHandler; private MapBasedhandler(Builder builder) { this.singleValueHandlers.putAll(builder.singleValueHandlers); diff --git a/api/src/main/java/com/google/common/flogger/backend/MetadataProcessor.java b/api/src/main/java/com/google/common/flogger/backend/MetadataProcessor.java index e31f7c93..b6e511e4 100644 --- a/api/src/main/java/com/google/common/flogger/backend/MetadataProcessor.java +++ b/api/src/main/java/com/google/common/flogger/backend/MetadataProcessor.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.jspecify.annotations.Nullable; /** * Processor combining scope and log-site metadata into a single view. This is necessary when @@ -53,28 +54,29 @@ */ public abstract class MetadataProcessor { // Immutable empty processor which never handles any metadata. - private static final MetadataProcessor EMPTY_PROCESSOR = new MetadataProcessor() { - @Override - public void process(MetadataHandler handler, C context) {} + private static final MetadataProcessor EMPTY_PROCESSOR = + new MetadataProcessor() { + @Override + public void process(MetadataHandler handler, C context) {} - @Override - public void handle(MetadataKey key, MetadataHandler handler, C context) {} + @Override + public void handle(MetadataKey key, MetadataHandler handler, C context) {} - @Override - public T getSingleValue(MetadataKey key) { - return null; - } + @Override + public @Nullable T getSingleValue(MetadataKey key) { + return null; + } - @Override - public int keyCount() { - return 0; - } + @Override + public int keyCount() { + return 0; + } - @Override - public Set> keySet() { - return Collections.emptySet(); - } - }; + @Override + public Set> keySet() { + return Collections.emptySet(); + } + }; /** * Returns a new processor for the combined scope and log-site metadata. Note that this returned @@ -220,7 +222,7 @@ public void handle(MetadataKey key, MetadataHandler handler, C context } @Override - public T getSingleValue(MetadataKey key) { + public @Nullable T getSingleValue(MetadataKey key) { checkArgument(!key.canRepeat(), "key must be single valued"); int index = indexOf(key, keyMap, keyCount); // For single keys, the keyMap values are just the value index. @@ -446,7 +448,7 @@ public void handle(MetadataKey key, MetadataHandler handler, C context // It's safe to ignore warnings since single keys are only ever 'T' when added to the map. @Override @SuppressWarnings("unchecked") - public T getSingleValue(MetadataKey key) { + public @Nullable T getSingleValue(MetadataKey key) { checkArgument(!key.canRepeat(), "key must be single valued"); Object value = map.get(key); return (value != null) ? (T) value : null; diff --git a/api/src/main/java/com/google/common/flogger/backend/TemplateContext.java b/api/src/main/java/com/google/common/flogger/backend/TemplateContext.java index 5fc0071f..b63e9f57 100644 --- a/api/src/main/java/com/google/common/flogger/backend/TemplateContext.java +++ b/api/src/main/java/com/google/common/flogger/backend/TemplateContext.java @@ -19,6 +19,7 @@ import static com.google.common.flogger.util.Checks.checkNotNull; import com.google.common.flogger.parser.MessageParser; +import org.jspecify.annotations.Nullable; /** * A context object for templates that allows caches to validate existing templates or create new @@ -49,7 +50,7 @@ public String getMessage() { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof TemplateContext) { TemplateContext other = (TemplateContext) obj; return parser.equals(other.parser) && message.equals(other.message); diff --git a/api/src/main/java/com/google/common/flogger/backend/system/AbstractBackend.java b/api/src/main/java/com/google/common/flogger/backend/system/AbstractBackend.java index 6ac69732..022effe9 100644 --- a/api/src/main/java/com/google/common/flogger/backend/system/AbstractBackend.java +++ b/api/src/main/java/com/google/common/flogger/backend/system/AbstractBackend.java @@ -22,6 +22,7 @@ import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; +import org.jspecify.annotations.Nullable; /** * Common backend to handle everything except formatting of log message and metadata. This is an @@ -145,7 +146,7 @@ public final void log(LogRecord record, boolean wasForced) { // would get a lot of extra stack frames to search through). However for Flogger, the LogSite // was already determined in the "shouldLog()" method because it's needed for things like // rate limiting. Thus we don't have to care about using iterative methods vs recursion here. - private static void publish(Logger logger, LogRecord record) { + private static void publish(@Nullable Logger logger, LogRecord record) { // Annoyingly this method appears to copy the array every time it is called, but there's // nothing much we can do about this (and there could be synchronization issues even if we // could access things directly because handlers can be changed at any time). Most of the diff --git a/api/src/main/java/com/google/common/flogger/backend/system/AbstractLogRecord.java b/api/src/main/java/com/google/common/flogger/backend/system/AbstractLogRecord.java index a3a08140..cad52abf 100644 --- a/api/src/main/java/com/google/common/flogger/backend/system/AbstractLogRecord.java +++ b/api/src/main/java/com/google/common/flogger/backend/system/AbstractLogRecord.java @@ -31,6 +31,7 @@ import java.util.ResourceBundle; import java.util.logging.Formatter; import java.util.logging.LogRecord; +import org.jspecify.annotations.Nullable; /** * Abstract base class for {@code java.util.logging} compatible log records produced by Flogger @@ -157,7 +158,7 @@ protected LogMessageFormatter getLogMessageFormatter() { } @Override - public final void setParameters(Object[] parameters) { + public final void setParameters(Object @Nullable [] parameters) { // IMPORTANT: We call getMessage() to cache the internal formatted message if someone indicates // they want to change the parameters. This is to avoid a situation in which parameters are set, // but the underlying message is still null. Do this first to switch internal states. @@ -170,7 +171,7 @@ public final void setParameters(Object[] parameters) { } @Override - public final void setMessage(String message) { + public final void setMessage(@Nullable String message) { if (message == null) { message = ""; } diff --git a/api/src/main/java/com/google/common/flogger/context/ScopedLoggingContext.java b/api/src/main/java/com/google/common/flogger/context/ScopedLoggingContext.java index 4c45f2d2..af00758a 100644 --- a/api/src/main/java/com/google/common/flogger/context/ScopedLoggingContext.java +++ b/api/src/main/java/com/google/common/flogger/context/ScopedLoggingContext.java @@ -132,9 +132,9 @@ public ScopeList(ScopeType key, LoggingScope scope, @Nullable ScopeList next) { * reference to a builder instance for any length of time is not recommended. */ public abstract static class Builder { - private Tags tags = null; - private ContextMetadata.Builder metadata = null; - private LogLevelMap logLevelMap = null; + private @Nullable Tags tags = null; + private ContextMetadata.@Nullable Builder metadata = null; + private @Nullable LogLevelMap logLevelMap = null; private boolean hasLogLevelMap = false; protected Builder() {} diff --git a/api/src/main/java/com/google/common/flogger/context/Tags.java b/api/src/main/java/com/google/common/flogger/context/Tags.java index e5d70eee..7d2030db 100644 --- a/api/src/main/java/com/google/common/flogger/context/Tags.java +++ b/api/src/main/java/com/google/common/flogger/context/Tags.java @@ -404,8 +404,8 @@ public int compare(Object s1, Object s2) { new SortedArraySet>>(-1); // Cache these if anyone needs them (not likely in normal usage). - private Integer hashCode = null; - private String toString = null; + private @Nullable Integer hashCode = null; + private @Nullable String toString = null; // ---- Singleton constructor ---- @@ -641,7 +641,7 @@ private Map.Entry> newEntry(String key, int index } @SuppressWarnings("unchecked") // Safe when the index is in range. - private Map.Entry> getEntryOrNull(int index) { + private Map.@Nullable Entry> getEntryOrNull(int index) { return index < offsets[0] ? (Map.Entry>) array[index] : null; } diff --git a/api/src/main/java/com/google/common/flogger/util/CallerFinder.java b/api/src/main/java/com/google/common/flogger/util/CallerFinder.java index 1ace2000..ac2e6e01 100644 --- a/api/src/main/java/com/google/common/flogger/util/CallerFinder.java +++ b/api/src/main/java/com/google/common/flogger/util/CallerFinder.java @@ -43,7 +43,7 @@ private static StackGetter getBestStackGetter() { return new ThrowableStackGetter(); } - private static StackGetter maybeCreateStackGetter(String className) { + private static @Nullable StackGetter maybeCreateStackGetter(String className) { try { return Class.forName(className) .asSubclass(StackGetter.class) diff --git a/api/src/main/java/com/google/common/flogger/util/StaticMethodCaller.java b/api/src/main/java/com/google/common/flogger/util/StaticMethodCaller.java index 285621da..807dedf1 100644 --- a/api/src/main/java/com/google/common/flogger/util/StaticMethodCaller.java +++ b/api/src/main/java/com/google/common/flogger/util/StaticMethodCaller.java @@ -111,7 +111,7 @@ public static T getInstanceFromSystemProperty(String propertyName, Class return null; } - private static String readProperty(String propertyName, @Nullable String defaultValue) { + private static @Nullable String readProperty(String propertyName, @Nullable String defaultValue) { Checks.checkNotNull(propertyName, "property name"); try { return System.getProperty(propertyName, defaultValue); diff --git a/api/src/main/java/com/google/common/flogger/util/ThrowableStackGetter.java b/api/src/main/java/com/google/common/flogger/util/ThrowableStackGetter.java index 6a2732b7..cb3254a1 100644 --- a/api/src/main/java/com/google/common/flogger/util/ThrowableStackGetter.java +++ b/api/src/main/java/com/google/common/flogger/util/ThrowableStackGetter.java @@ -18,11 +18,13 @@ import static com.google.common.flogger.util.Checks.checkArgument; +import org.jspecify.annotations.Nullable; + /** Default implementation of {@link StackGetter} using {@link Throwable#getStackTrace}. */ final class ThrowableStackGetter implements StackGetter { @Override - public StackTraceElement callerOf(Class target, int skipFrames) { + public @Nullable StackTraceElement callerOf(Class target, int skipFrames) { checkArgument(skipFrames >= 0, "skipFrames must be >= 0"); StackTraceElement[] stack = new Throwable().getStackTrace(); int callerIndex = findCallerIndex(stack, target, skipFrames + 1); diff --git a/api/src/test/java/com/google/common/flogger/StackBasedLogSiteTest.java b/api/src/test/java/com/google/common/flogger/StackBasedLogSiteTest.java index 0c30f22b..03a184c3 100644 --- a/api/src/test/java/com/google/common/flogger/StackBasedLogSiteTest.java +++ b/api/src/test/java/com/google/common/flogger/StackBasedLogSiteTest.java @@ -23,6 +23,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import org.jspecify.annotations.Nullable; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -94,7 +95,7 @@ public void testEqualsAndHashCode() { // Helper to keep callers a bit less cluttered and make tests a bit more readable. private static StackBasedLogSite stackBasedLogSite( - String className, String methodName, String fileName, int lineNumber) { + String className, String methodName, @Nullable String fileName, int lineNumber) { return new StackBasedLogSite( new StackTraceElement(className, methodName, fileName, lineNumber)); } diff --git a/api/src/test/java/com/google/common/flogger/backend/KeyValueFormatterTest.java b/api/src/test/java/com/google/common/flogger/backend/KeyValueFormatterTest.java index 1b434b42..6f86437d 100644 --- a/api/src/test/java/com/google/common/flogger/backend/KeyValueFormatterTest.java +++ b/api/src/test/java/com/google/common/flogger/backend/KeyValueFormatterTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; +import org.jspecify.annotations.Nullable; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -117,7 +118,7 @@ private static KeyValueFormatter formatter(StringBuilder out) { return new KeyValueFormatter("<< ", " >>", out); } - private static String format(String key, Object value) { + private static String format(String key, @Nullable Object value) { StringBuilder out = new StringBuilder(); KeyValueFormatter kvf = new KeyValueFormatter("", "", out); kvf.handle(key, value); diff --git a/api/src/test/java/com/google/common/flogger/backend/MetadataProcessorTest.java b/api/src/test/java/com/google/common/flogger/backend/MetadataProcessorTest.java index 8349e610..76bea1db 100644 --- a/api/src/test/java/com/google/common/flogger/backend/MetadataProcessorTest.java +++ b/api/src/test/java/com/google/common/flogger/backend/MetadataProcessorTest.java @@ -29,6 +29,7 @@ import java.util.Iterator; import java.util.List; import java.util.function.BiFunction; +import org.jspecify.annotations.Nullable; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -218,13 +219,14 @@ public void testReadOnlyIterable() { scope.add(REP_1, "two"); MetadataProcessor metadata = factory.apply(scope, Metadata.empty()); - MetadataHandler handler = - new MetadataHandler() { + MetadataHandler<@Nullable Void> handler = + new MetadataHandler<@Nullable Void>() { @Override - protected void handle(MetadataKey key, T value, Void context) {} + protected void handle(MetadataKey key, T value, @Nullable Void context) {} @Override - protected void handleRepeated(MetadataKey key, Iterator values, Void context) { + protected void handleRepeated( + MetadataKey key, Iterator values, @Nullable Void context) { assertThat(values.hasNext()).isTrue(); assertThat(values.next()).isEqualTo("one"); values.remove(); diff --git a/api/src/test/java/com/google/common/flogger/backend/system/AbstractBackendTest.java b/api/src/test/java/com/google/common/flogger/backend/system/AbstractBackendTest.java index b1814ff1..19c09e03 100644 --- a/api/src/test/java/com/google/common/flogger/backend/system/AbstractBackendTest.java +++ b/api/src/test/java/com/google/common/flogger/backend/system/AbstractBackendTest.java @@ -23,6 +23,7 @@ import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; +import org.jspecify.annotations.Nullable; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -78,8 +79,8 @@ void assertUsedForcingLogger(boolean expectForced) { } private static final class TestLogger extends Logger { - private String captured = null; - private String published = null; + private @Nullable String captured = null; + private @Nullable String published = null; TestLogger(String name, Level level) { super(name, null); @@ -101,12 +102,12 @@ public void log(LogRecord record) { super.log(record); } - void assertLogged(String expectedLogMessage) { + void assertLogged(@Nullable String expectedLogMessage) { assertThat(captured).isEqualTo(expectedLogMessage); captured = null; } - void assertPublished(String expectedLogMessage) { + void assertPublished(@Nullable String expectedLogMessage) { assertThat(published).isEqualTo(expectedLogMessage); published = null; } diff --git a/api/src/test/java/com/google/common/flogger/parameter/ParameterTest.java b/api/src/test/java/com/google/common/flogger/parameter/ParameterTest.java index f971f5fc..87e83d26 100644 --- a/api/src/test/java/com/google/common/flogger/parameter/ParameterTest.java +++ b/api/src/test/java/com/google/common/flogger/parameter/ParameterTest.java @@ -21,6 +21,7 @@ import com.google.common.flogger.backend.FormatOptions; import com.google.common.flogger.parser.ParseException; +import org.jspecify.annotations.Nullable; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -29,7 +30,7 @@ public class ParameterTest { // We just need a concrete class here. private static class TestParameter extends Parameter { - public TestParameter(FormatOptions options, int index) { + public TestParameter(@Nullable FormatOptions options, int index) { super(options, index); } diff --git a/api/src/test/java/com/google/common/flogger/testing/AssertingLogger.java b/api/src/test/java/com/google/common/flogger/testing/AssertingLogger.java index 5516a428..0b7be1e0 100644 --- a/api/src/test/java/com/google/common/flogger/testing/AssertingLogger.java +++ b/api/src/test/java/com/google/common/flogger/testing/AssertingLogger.java @@ -26,6 +26,7 @@ import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; +import org.jspecify.annotations.Nullable; /** * Helper class for testing system backends, which need to mimic the JDK's log record. @@ -45,7 +46,7 @@ private static class LogEntry { } private final String message; - private final Object[] parameters; + private final Object @Nullable [] parameters; private final Level level; private final Throwable thrown; } diff --git a/api/src/test/java/com/google/common/flogger/testing/FakeLogData.java b/api/src/test/java/com/google/common/flogger/testing/FakeLogData.java index 57444fb3..35050acb 100644 --- a/api/src/test/java/com/google/common/flogger/testing/FakeLogData.java +++ b/api/src/test/java/com/google/common/flogger/testing/FakeLogData.java @@ -65,9 +65,9 @@ public static FakeLogData withBraceStyle(String message, Object... arguments) { } private Level level = Level.INFO; - private TemplateContext context = null; - private Object[] arguments = null; - private Object literalArgument = null; + private @Nullable TemplateContext context = null; + private Object @Nullable [] arguments = null; + private @Nullable Object literalArgument = null; private long timestampNanos = 0L; private FakeMetadata metadata = new FakeMetadata(); private LogSite logSite = FAKE_LOG_SITE; diff --git a/api/src/test/java/com/google/common/flogger/testing/FakeLogSite.java b/api/src/test/java/com/google/common/flogger/testing/FakeLogSite.java index f777001f..74e04f08 100644 --- a/api/src/test/java/com/google/common/flogger/testing/FakeLogSite.java +++ b/api/src/test/java/com/google/common/flogger/testing/FakeLogSite.java @@ -19,6 +19,7 @@ import com.google.common.flogger.LogSite; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; +import org.jspecify.annotations.Nullable; /** A simplified LogSite implementation used for testing. */ public final class FakeLogSite extends LogSite { @@ -68,7 +69,7 @@ public String getFileName() { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof FakeLogSite)) { return false; } diff --git a/api/src/test/java/com/google/common/flogger/util/CallerFinderTest.java b/api/src/test/java/com/google/common/flogger/util/CallerFinderTest.java index 512fa786..fdf761ed 100644 --- a/api/src/test/java/com/google/common/flogger/util/CallerFinderTest.java +++ b/api/src/test/java/com/google/common/flogger/util/CallerFinderTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; +import org.jspecify.annotations.Nullable; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -66,7 +67,7 @@ void loggingMethod() { /** Fake class that emulates the logging library which eventually calls 'findCallerOf()'. */ private static class LoggerCode { final int skipCount; - StackTraceElement caller = null; + @Nullable StackTraceElement caller = null; public LoggerCode(int skipCount) { this.skipCount = skipCount; diff --git a/api/src/test/java/com/google/common/flogger/util/StackGetterTestUtil.java b/api/src/test/java/com/google/common/flogger/util/StackGetterTestUtil.java index a4c22fed..6a0b6681 100644 --- a/api/src/test/java/com/google/common/flogger/util/StackGetterTestUtil.java +++ b/api/src/test/java/com/google/common/flogger/util/StackGetterTestUtil.java @@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.flogger.util.StackGetterTestUtil.LoggerCode; +import org.jspecify.annotations.Nullable; final class StackGetterTestUtil { @@ -45,7 +46,7 @@ void loggingMethod() { static class LoggerCode { final int skipCount; final StackGetter stackGetter; - StackTraceElement caller = null; + @Nullable StackTraceElement caller = null; public LoggerCode(int skipCount, StackGetter stackGetter) { this.skipCount = skipCount; diff --git a/google/src/test/java/com/google/common/flogger/GoogleLoggerTest.java b/google/src/test/java/com/google/common/flogger/GoogleLoggerTest.java index 56d36651..90b8d3e5 100644 --- a/google/src/test/java/com/google/common/flogger/GoogleLoggerTest.java +++ b/google/src/test/java/com/google/common/flogger/GoogleLoggerTest.java @@ -29,6 +29,7 @@ import java.util.logging.LogRecord; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; +import org.jspecify.annotations.Nullable; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -208,7 +209,7 @@ public void testInjectedInnerClassName() { } private static class AssertingHandler extends Handler { - private List logRecords = new ArrayList<>(); + private @Nullable List logRecords = new ArrayList<>(); @Override public void publish(LogRecord record) { diff --git a/grpc/src/main/java/com/google/common/flogger/grpc/GrpcContextDataProvider.java b/grpc/src/main/java/com/google/common/flogger/grpc/GrpcContextDataProvider.java index 23e01316..e795d070 100644 --- a/grpc/src/main/java/com/google/common/flogger/grpc/GrpcContextDataProvider.java +++ b/grpc/src/main/java/com/google/common/flogger/grpc/GrpcContextDataProvider.java @@ -59,7 +59,7 @@ static Context.Key getContextKey() { // GrpcContextDataProvider (which is created as the Platform instance is initialized). By doing // this we break any initialization cycles and allow the config API perform its own logging if // necessary. - private volatile GrpcScopedLoggingContext configInstance = null; + private volatile @Nullable GrpcScopedLoggingContext configInstance = null; // When this is false we can skip some work for every log statement. This is set to true if _any_ // context adds a log level map at any point (this is generally rare and only used for targeted diff --git a/log4j2/src/main/java/com/google/common/flogger/backend/log4j2/ValueQueue.java b/log4j2/src/main/java/com/google/common/flogger/backend/log4j2/ValueQueue.java index cdfb3840..48e45079 100644 --- a/log4j2/src/main/java/com/google/common/flogger/backend/log4j2/ValueQueue.java +++ b/log4j2/src/main/java/com/google/common/flogger/backend/log4j2/ValueQueue.java @@ -101,6 +101,7 @@ static ValueQueue appendValueToNewQueue(Object value) { * but you see "id=abcd" because someone else added "id=abcd" in a context you weren't aware of). * *

Given three tag mappings: + * *

    *
  • {@code "baz"} (no value) *
  • {@code "foo" -> true} @@ -108,6 +109,7 @@ static ValueQueue appendValueToNewQueue(Object value) { *
* * the value queue is going to store the mappings as: + * *
{@code
    * tags=[baz, foo=false, foo=true]
    * }
@@ -115,7 +117,7 @@ static ValueQueue appendValueToNewQueue(Object value) { *

Reusing the label 'tags' is intentional as this allows us to store the flatten tags in * Log4j2's ContextMap. */ - static void emit(String label, Object value, MetadataKey.KeyValueHandler kvh) { + static void emit(@Nullable String label, Object value, MetadataKey.KeyValueHandler kvh) { if (value instanceof Tags) { // Flatten tags to treat them as keys or key/value pairs, e.g. tags=[baz=bar, baz=bar2, foo] ((Tags) value) @@ -173,7 +175,7 @@ public String toString() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; } diff --git a/log4j2/src/test/java/com/google/common/flogger/backend/log4j2/Log4j2Test.java b/log4j2/src/test/java/com/google/common/flogger/backend/log4j2/Log4j2Test.java index 34cd9a1e..f28ea37b 100644 --- a/log4j2/src/test/java/com/google/common/flogger/backend/log4j2/Log4j2Test.java +++ b/log4j2/src/test/java/com/google/common/flogger/backend/log4j2/Log4j2Test.java @@ -42,6 +42,7 @@ import org.apache.logging.log4j.core.appender.AbstractAppender; import org.apache.logging.log4j.core.config.DefaultConfiguration; import org.apache.logging.log4j.core.layout.PatternLayout; +import org.jspecify.annotations.Nullable; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -126,7 +127,8 @@ void assertLogEntry(int index, Level level, String message) { assertThat(event.getThrown()).isNull(); } - void assertLogSite(int index, String className, String methodName, int line, String file) { + void assertLogSite( + int index, String className, String methodName, int line, @Nullable String file) { LogEvent event = events.get(index); StackTraceElement source = event.getSource(); assertThat(source.getClassName()).isEqualTo(className);