-
Notifications
You must be signed in to change notification settings - Fork 49
Introduce EmptyReactivePublisher bug checker
#1560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Introduce EmptyReactivePublisher bug checker
#1560
Conversation
| " Mono.just(16).subscribe(null, t -> {});", | ||
| "", | ||
| " // BUG: Diagnostic contains:", | ||
| " Mono.just(17).then().subscribe(i -> {});", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the statement that inspired this bug checker; this consumer is never called.
|
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed. |
e8a8e37 to
a83f846
Compare
|
Suggested commit message: |
| String.format( | ||
| "Operator `%s` on an empty `Mono`s is a no-op", | ||
| ASTHelpers.getSymbol(tree).getSimpleName())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Error Prone] reported by reviewdog 🐶
| String.format( | |
| "Operator `%s` on an empty `Mono`s is a no-op", | |
| ASTHelpers.getSymbol(tree).getSimpleName())) | |
| "Operator `%s` on an empty `Mono`s is a no-op" | |
| .formatted(ASTHelpers.getSymbol(tree).getSimpleName())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will apply.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed. |
rickie
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushing a commit with many small suggestions. PTAL and feel free to tweak 😄.
Very elegant PR. The testing makes refactoring easy 🚀.
|
|
||
| /** | ||
| * A {@link BugChecker} that flags {@link Publisher} operations that are known to be vacuous, given | ||
| * that they are invoked on a {@link Mono} or {@link Flux} that do not emit next signals. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * that they are invoked on a {@link Mono} or {@link Flux} that do not emit next signals. | |
| * that they are invoked on a {@link Mono} or {@link Flux} that does not emit next signals. |
Right?
| public final class EmptyReactivePublisher extends BugChecker | ||
| implements MethodInvocationTreeMatcher { | ||
| private static final long serialVersionUID = 1L; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| private static final Matcher<ExpressionTree> SUBSCRIBE = | ||
| instanceMethod() | ||
| .onDescendantOf(Suppliers.typeFromString("org.reactivestreams.Publisher")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| .onDescendantOf(Suppliers.typeFromString("org.reactivestreams.Publisher")) | |
| .onDescendantOf(type("org.reactivestreams.Publisher")) |
Also works :) ?
| Suppliers.typeFromString("reactor.core.publisher.Flux"); | ||
| private static final Matcher<Tree> CONSUMER = | ||
| isSubtypeOf(type(Consumer.class.getCanonicalName())); | ||
| private static final Supplier<Type> VOID = type(Void.class.getCanonicalName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is one in Error Prone itself we can use :)
|
|
||
| if (SUBSCRIBE.matches(tree, state)) { | ||
| // First argument passed to `#subscribe` is always an on next signal `Consumer`. | ||
| ExpressionTree firstArgument = Iterables.getFirst(tree.getArguments(), null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps simply .getFirst() on the collection?
| if (EMPTY_MONO.matches(receiver, state) && VACUOUS_EMPTY_MONO_OPERATORS.matches(tree, state)) { | ||
| return buildDescription(tree) | ||
| .setMessage( | ||
| "Operator `%s` on an empty `Mono`s is a no-op" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can extract this into a method :)
| .build(); | ||
| } | ||
|
|
||
| if (EMPTY_MONO.matches(receiver, state) && VACUOUS_EMPTY_MONO_OPERATORS.matches(tree, state)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can omit this first part of the if-statement
| isSubtypeOf(type(Consumer.class.getCanonicalName())); | ||
| private static final Supplier<Type> VOID = type(Void.class.getCanonicalName()); | ||
|
|
||
| private static final Matcher<ExpressionTree> EMPTY_FLUX = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably combine this one and the next
| Suppliers.typeFromString("reactor.core.publisher.Flux"); | ||
| private static final Matcher<Tree> CONSUMER = | ||
| isSubtypeOf(type(Consumer.class.getCanonicalName())); | ||
| private static final Supplier<Type> VOID = type(Void.class.getCanonicalName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is one provided by EP :D
| " Mono.just(6).handle((i, j) -> {});", | ||
| " Mono.just(7).map(i -> i);", | ||
| "", | ||
| " // BUG: Diagnostic contains: doOnNext", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's expand the message to be more accurate in testing :)
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed. |
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed. |
|
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed. |



Suggested commit message