Skip to content

Commit 1fe5a46

Browse files
authored
Adjust reactor.util.Logger vararg nullability (reactor#4098)
With JSpecify annotations, array and varargs nullability checks are more expressive and provide more out-of-the-box strictness. The reactor.util.Logger interface has relaxed requirements regarding varargs parameters when logging so that is now reflected using the type-use annotations syntax. Additionally, the TestLogger was adjusted to avoid NPE when null varargs elements are provided. Resolves reactor#4095 Signed-off-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com>
1 parent 300f627 commit 1fe5a46

7 files changed

Lines changed: 141 additions & 57 deletions

File tree

reactor-core/src/jcstress/java/reactor/core/util/FastLogger.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022 VMware Inc. or its affiliates, All Rights Reserved.
2+
* Copyright (c) 2022-2025 VMware Inc. or its affiliates, All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
2626
import java.util.regex.Pattern;
2727
import java.util.stream.Collectors;
2828

29+
import org.jspecify.annotations.Nullable;
2930
import reactor.util.Logger;
3031

3132
/**
@@ -86,7 +87,7 @@ public void trace(String msg) {
8687
}
8788

8889
@Override
89-
public void trace(String format, Object... arguments) {
90+
public void trace(String format, @Nullable Object @Nullable... arguments) {
9091
trace(String.format(format, arguments));
9192
}
9293

@@ -106,7 +107,7 @@ public void debug(String msg) {
106107
}
107108

108109
@Override
109-
public void debug(String format, Object... arguments) {
110+
public void debug(String format, @Nullable Object @Nullable... arguments) {
110111

111112
}
112113

@@ -126,7 +127,7 @@ public void info(String msg) {
126127
}
127128

128129
@Override
129-
public void info(String format, Object... arguments) {
130+
public void info(String format, @Nullable Object @Nullable... arguments) {
130131

131132
}
132133

@@ -146,7 +147,7 @@ public void warn(String msg) {
146147
}
147148

148149
@Override
149-
public void warn(String format, Object... arguments) {
150+
public void warn(String format, @Nullable Object @Nullable... arguments) {
150151

151152
}
152153

@@ -166,7 +167,7 @@ public void error(String msg) {
166167
}
167168

168169
@Override
169-
public void error(String format, Object... arguments) {
170+
public void error(String format, @Nullable Object @Nullable... arguments) {
170171

171172
}
172173

reactor-core/src/main/java/reactor/util/Logger.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ interface ChoiceOfMessageSupplier {
7575
* @param format the format string
7676
* @param arguments a list of 3 or more arguments
7777
*/
78-
void trace(String format, @Nullable Object... arguments);
78+
void trace(String format, @Nullable Object @Nullable... arguments);
7979

8080
/**
8181
* Log an exception (throwable) at the TRACE level with an
@@ -113,7 +113,7 @@ interface ChoiceOfMessageSupplier {
113113
* @param format the format string
114114
* @param arguments a list of 3 or more arguments
115115
*/
116-
void debug(String format, Object... arguments);
116+
void debug(String format, @Nullable Object @Nullable... arguments);
117117

118118
/**
119119
* Log an exception (throwable) at the DEBUG level with an
@@ -151,7 +151,7 @@ interface ChoiceOfMessageSupplier {
151151
* @param format the format string
152152
* @param arguments a list of 3 or more arguments
153153
*/
154-
void info(String format, Object... arguments);
154+
void info(String format, @Nullable Object @Nullable... arguments);
155155

156156
/**
157157
* Log an exception (throwable) at the INFO level with an
@@ -233,7 +233,7 @@ else if (isInfoEnabled()) {
233233
* @param format the format string
234234
* @param arguments a list of 3 or more arguments
235235
*/
236-
void warn(String format, Object... arguments);
236+
void warn(String format, @Nullable Object @Nullable... arguments);
237237

238238
/**
239239
* Log an exception (throwable) at the WARN level with an
@@ -315,7 +315,7 @@ else if (isWarnEnabled()) {
315315
* @param format the format string
316316
* @param arguments a list of 3 or more arguments
317317
*/
318-
void error(String format, Object... arguments);
318+
void error(String format, @Nullable Object @Nullable... arguments);
319319

320320
/**
321321
* Log an exception (throwable) at the ERROR level with an

reactor-core/src/main/java/reactor/util/Loggers.java

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ public void trace(String msg) {
235235
}
236236

237237
@Override
238-
public void trace(String format, Object... arguments) {
238+
public void trace(String format, @Nullable Object @Nullable... arguments) {
239239
logger.trace(format, arguments);
240240
}
241241

@@ -255,7 +255,7 @@ public void debug(String msg) {
255255
}
256256

257257
@Override
258-
public void debug(String format, Object... arguments) {
258+
public void debug(String format, @Nullable Object @Nullable... arguments) {
259259
logger.debug(format, arguments);
260260
}
261261

@@ -275,7 +275,7 @@ public void info(String msg) {
275275
}
276276

277277
@Override
278-
public void info(String format, Object... arguments) {
278+
public void info(String format, @Nullable Object @Nullable... arguments) {
279279
logger.info(format, arguments);
280280
}
281281

@@ -295,7 +295,7 @@ public void warn(String msg) {
295295
}
296296

297297
@Override
298-
public void warn(String format, Object... arguments) {
298+
public void warn(String format, @Nullable Object @Nullable... arguments) {
299299
logger.warn(format, arguments);
300300
}
301301

@@ -315,7 +315,7 @@ public void error(String msg) {
315315
}
316316

317317
@Override
318-
public void error(String format, Object... arguments) {
318+
public void error(String format, @Nullable Object @Nullable... arguments) {
319319
logger.error(format, arguments);
320320
}
321321

@@ -352,7 +352,7 @@ public void trace(String msg) {
352352
}
353353

354354
@Override
355-
public void trace(String format, Object... arguments) {
355+
public void trace(String format, @Nullable Object @Nullable... arguments) {
356356
logWithPotentialThrowable(Level.FINEST, format, arguments);
357357
}
358358

@@ -372,7 +372,7 @@ public void debug(String msg) {
372372
}
373373

374374
@Override
375-
public void debug(String format, Object... arguments) {
375+
public void debug(String format, @Nullable Object @Nullable... arguments) {
376376
logWithPotentialThrowable(Level.FINE, format, arguments);
377377
}
378378

@@ -392,7 +392,7 @@ public void info(String msg) {
392392
}
393393

394394
@Override
395-
public void info(String format, Object... arguments) {
395+
public void info(String format, @Nullable Object @Nullable... arguments) {
396396
logWithPotentialThrowable(Level.INFO, format, arguments);
397397
}
398398

@@ -412,7 +412,7 @@ public void warn(String msg) {
412412
}
413413

414414
@Override
415-
public void warn(String format, Object... arguments) {
415+
public void warn(String format, @Nullable Object @Nullable... arguments) {
416416
logWithPotentialThrowable(Level.WARNING, format, arguments);
417417
}
418418

@@ -432,7 +432,7 @@ public void error(String msg) {
432432
}
433433

434434
@Override
435-
public void error(String format, Object... arguments) {
435+
public void error(String format, @Nullable Object @Nullable... arguments) {
436436
logWithPotentialThrowable(Level.SEVERE, format, arguments);
437437
}
438438

@@ -441,11 +441,13 @@ public void error(String msg, Throwable t) {
441441
logger.log(Level.SEVERE, msg, t);
442442
}
443443

444-
private @Nullable String format(@Nullable String from, Object @Nullable[] arguments) {
444+
private @Nullable String format(@Nullable String from,
445+
@Nullable Object @Nullable [] arguments) {
445446
return format(from, arguments, false);
446447
}
447448

448-
private @Nullable String format(@Nullable String from, Object @Nullable[] arguments, boolean skipLast) {
449+
private @Nullable String format(@Nullable String from,
450+
@Nullable Object @Nullable [] arguments, boolean skipLast) {
449451
if (from != null) {
450452
String computed = from;
451453
if (arguments != null && arguments.length != 0) {
@@ -455,15 +457,17 @@ public void error(String msg, Throwable t) {
455457
}
456458

457459
for (int index = 0; index < lastIndex; ++index) {
458-
computed = computed.replaceFirst("\\{\\}", Matcher.quoteReplacement(String.valueOf(arguments[index])));
460+
computed = computed.replaceFirst("\\{\\}",
461+
Matcher.quoteReplacement(String.valueOf(arguments[index])));
459462
}
460463
}
461464
return computed;
462465
}
463466
return null;
464467
}
465468

466-
private void logWithPotentialThrowable(Level level, String format, Object... arguments) {
469+
private void logWithPotentialThrowable(Level level, String format,
470+
@Nullable Object @Nullable... arguments) {
467471
Throwable t = getPotentialThrowable(arguments);
468472
if (t != null) {
469473
logger.log(level, format(format, arguments, true), t);
@@ -473,7 +477,7 @@ private void logWithPotentialThrowable(Level level, String format, Object... arg
473477
logger.log(level, format(format, arguments));
474478
}
475479

476-
private @Nullable Throwable getPotentialThrowable(Object... arguments) {
480+
private @Nullable Throwable getPotentialThrowable(@Nullable Object @Nullable... arguments) {
477481
if (arguments == null) {
478482
return null;
479483
}
@@ -524,11 +528,11 @@ public String getName() {
524528
return identifier.name;
525529
}
526530

527-
private @Nullable String format(@Nullable String from, Object @Nullable[] arguments) {
531+
private @Nullable String format(@Nullable String from, @Nullable Object @Nullable[] arguments) {
528532
return format(from, arguments, false);
529533
}
530534

531-
private @Nullable String format(@Nullable String from, Object @Nullable[] arguments, boolean skipLast) {
535+
private @Nullable String format(@Nullable String from, @Nullable Object @Nullable[] arguments, boolean skipLast) {
532536
if (from != null) {
533537
String computed = from;
534538
if (arguments != null && arguments.length != 0) {
@@ -546,7 +550,7 @@ public String getName() {
546550
return null;
547551
}
548552

549-
private synchronized void logWithPotentialThrowable(PrintStream logger, String level, String format, Object... arguments) {
553+
private synchronized void logWithPotentialThrowable(PrintStream logger, String level, String format, @Nullable Object @Nullable... arguments) {
550554
Throwable t = getPotentialThrowable(arguments);
551555
if (t != null) {
552556
logger.format(
@@ -567,7 +571,7 @@ private synchronized void logWithPotentialThrowable(PrintStream logger, String l
567571
);
568572
}
569573

570-
private static @Nullable Throwable getPotentialThrowable(Object... arguments) {
574+
private static @Nullable Throwable getPotentialThrowable(@Nullable Object @Nullable... arguments) {
571575
if (arguments == null) {
572576
return null;
573577
}
@@ -594,7 +598,7 @@ public synchronized void trace(String msg) {
594598
}
595599

596600
@Override
597-
public void trace(String format, Object... arguments) {
601+
public void trace(String format, @Nullable Object @Nullable... arguments) {
598602
if (!identifier.verbose) {
599603
return;
600604
}
@@ -624,7 +628,7 @@ public synchronized void debug(String msg) {
624628
}
625629

626630
@Override
627-
public void debug(String format, Object... arguments) {
631+
public void debug(String format, @Nullable Object @Nullable... arguments) {
628632
if (!identifier.verbose) {
629633
return;
630634
}
@@ -651,7 +655,7 @@ public synchronized void info(String msg) {
651655
}
652656

653657
@Override
654-
public void info(String format, Object... arguments) {
658+
public void info(String format, @Nullable Object @Nullable... arguments) {
655659
logWithPotentialThrowable(this.log, " INFO", format, arguments);
656660
}
657661

@@ -672,7 +676,7 @@ public synchronized void warn(String msg) {
672676
}
673677

674678
@Override
675-
public void warn(String format, Object... arguments) {
679+
public void warn(String format, @Nullable Object @Nullable... arguments) {
676680
logWithPotentialThrowable(this.err, " WARN", format, arguments);
677681
}
678682

@@ -693,7 +697,7 @@ public synchronized void error(String msg) {
693697
}
694698

695699
@Override
696-
public void error(String format, Object... arguments) {
700+
public void error(String format, @Nullable Object @Nullable... arguments) {
697701
logWithPotentialThrowable(this.err, "ERROR", format, arguments);
698702
}
699703

reactor-core/src/test/java/reactor/core/publisher/SignalLoggerTests.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2021 VMware Inc. or its affiliates, All Rights Reserved.
2+
* Copyright (c) 2016-2025 VMware Inc. or its affiliates, All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
2020
import java.util.Objects;
2121
import java.util.logging.Level;
2222

23+
import org.jspecify.annotations.Nullable;
2324
import org.junit.jupiter.api.Test;
2425
import org.mockito.Mockito;
2526
import org.reactivestreams.Subscription;
@@ -42,8 +43,8 @@ public class SignalLoggerTests {
4243
public void safeLogsWhenLoggerThrows() {
4344
TestLogger logger = new TestLogger() {
4445
@Override
45-
public synchronized void info(String format, Object... arguments) {
46-
if (arguments[0] instanceof SignalType && arguments[1] instanceof Integer) {
46+
public synchronized void info(String format, @Nullable Object @Nullable... arguments) {
47+
if (arguments != null && arguments[0] instanceof SignalType && arguments[1] instanceof Integer) {
4748
throw new UnsupportedOperationException("boom on integer");
4849
}
4950
super.info(format, arguments);
@@ -406,7 +407,10 @@ private Object collectionAsString(Object source) {
406407
return str.toString();
407408
}
408409

409-
private Object[] wrapArguments(Object... arguments) {
410+
private Object[] wrapArguments(@Nullable Object @Nullable... arguments) {
411+
if (arguments == null) {
412+
return null;
413+
}
410414
Object[] args = new Object[arguments.length];
411415
for (int i = 0; i < arguments.length; i++) {
412416
args[i] = collectionAsString(arguments[i]);
@@ -430,7 +434,7 @@ public void trace(String msg) {
430434
}
431435

432436
@Override
433-
public void trace(String format, Object... arguments) {
437+
public void trace(String format, @Nullable Object @Nullable... arguments) {
434438
delegate.trace(format, wrapArguments(arguments));
435439
}
436440

@@ -450,7 +454,7 @@ public void debug(String msg) {
450454
}
451455

452456
@Override
453-
public void debug(String format, Object... arguments) {
457+
public void debug(String format, @Nullable Object @Nullable... arguments) {
454458
delegate.debug(format, wrapArguments(arguments));
455459
}
456460

@@ -470,7 +474,7 @@ public void info(String msg) {
470474
}
471475

472476
@Override
473-
public void info(String format, Object... arguments) {
477+
public void info(String format, @Nullable Object @Nullable... arguments) {
474478
delegate.info(format, wrapArguments(arguments));
475479
}
476480

@@ -490,7 +494,7 @@ public void warn(String msg) {
490494
}
491495

492496
@Override
493-
public void warn(String format, Object... arguments) {
497+
public void warn(String format, @Nullable Object @Nullable... arguments) {
494498
delegate.warn(format, wrapArguments(arguments));
495499
}
496500

@@ -510,7 +514,7 @@ public void error(String msg) {
510514
}
511515

512516
@Override
513-
public void error(String format, Object... arguments) {
517+
public void error(String format, @Nullable Object @Nullable... arguments) {
514518
delegate.error(format, wrapArguments(arguments));
515519
}
516520

0 commit comments

Comments
 (0)