-
Notifications
You must be signed in to change notification settings - Fork 39
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
Introduce NonEmptyMono
check
#200
Conversation
Niiice! Won't have time right now to review, but love the simplicity! 🚀 Will try to review in the coming day(s) :) |
08de097
to
bc832c4
Compare
bc832c4
to
d81a6c4
Compare
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.
Rebased and added a commit. Did not yet review the Javadoc and tests; pondering whether we can generalize even a bit more... stay tuned :)
tags = SIMPLIFICATION) | ||
public final class FluxCollect extends BugChecker implements MethodInvocationTreeMatcher { | ||
private static final long serialVersionUID = 1L; | ||
private static final Matcher<ExpressionTree> FLUX_EMPTY_CHECK = |
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> FLUX_EMPTY_CHECK = | |
private static final Matcher<ExpressionTree> MONO_SIZE_CHECK = |
instanceMethod() | ||
.onDescendantOf("reactor.core.publisher.Flux") | ||
.namedAnyOf( | ||
"collect", "collectList", "collectSortedList", "collectMap", "collectMultimap"); |
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 sort 😄
if (tree.getMethodSelect().getKind() != MEMBER_SELECT) { | ||
return Description.NO_MATCH; | ||
} | ||
|
||
ExpressionTree selectExpression = ((MemberSelectTree) tree.getMethodSelect()).getExpression(); |
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 instead us ASTHelpers.getReceiver(tree)
:)
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.
Added a commit with a proposed generalization; PTAL.
The idea is not to pick up the XXX
comments in this PR: before doing so I would propose to look into a kind of "calculus" for reactive streams. That said, if this sounds interesting: let's talk! 😄
Did not yet review the tests. I suspect we should condense the test cases rather than ~quadruple the current amount. Let me know what you think :)
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.
Flushing my comments. Almost finished with a few test improvements as we often limit the amount of entries in the replacement
test. Will continue tomorrow :).
Very nice check @cernat-catalin 😄:rocket:!
private static final Matcher<ExpressionTree> MONO_SIZE_CHECK = | ||
instanceMethod() | ||
.onDescendantOf("reactor.core.publisher.Mono") | ||
.namedAnyOf("single", "defaultIfEmpty", "switchIfEmpty"); |
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 sort them :).
"last", | ||
"reduce", | ||
"reduceWith", | ||
"single"), |
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 have to ask, although I'm not 100% I understand the method, is there a reason for not including shareNext
?
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.
It's not included because that method might return a Mono
that completes empty. This test passes:
Flux.empty().shareNext().as(StepVerifier::create).verifyComplete();
instanceMethod() | ||
.onDescendantOf("reactor.core.publisher.Mono") | ||
.namedAnyOf("single", "defaultIfEmpty", "switchIfEmpty"); | ||
private static final Matcher<ExpressionTree> SINGLETON_MONO = |
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.
Not sure if SINGLETON
is the most ideal name here 🤔. Will try to come up with a different name tomorrow.
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.
NON_EMPTY_MONO
would match the class name. (Would actually prefer NONEMPTY_MONO
, but that doesn't quite match the type name and some other usages.)
39e4023
to
2319bfe
Compare
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.
Rebased and added a commit. Looking forward to the test tweaks 😄
instanceMethod() | ||
.onDescendantOf("reactor.core.publisher.Mono") | ||
.namedAnyOf("single", "defaultIfEmpty", "switchIfEmpty"); | ||
private static final Matcher<ExpressionTree> SINGLETON_MONO = |
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.
NON_EMPTY_MONO
would match the class name. (Would actually prefer NONEMPTY_MONO
, but that doesn't quite match the type name and some other usages.)
"last", | ||
"reduce", | ||
"reduceWith", | ||
"single"), |
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.
It's not included because that method might return a Mono
that completes empty. This test passes:
Flux.empty().shareNext().as(StepVerifier::create).verifyComplete();
error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/NonEmptyMono.java
Outdated
Show resolved
Hide resolved
Very nice additions @Stephan202 ! It is starting to become a very encompassing BugPattern |
Pushed a tweak for the I was working on a proposal for the identification part as well. However, I wasn't too sure how to proceed here. It's a bit too much to add tests for all variants + the three methods we flag. TBH, I think it'd be okay to remove some of the entries in the |
I would be in favour of that. Would I'd probably have one line for each method in |
Thanks both! I've pushed a commit which rewrites the entries in the However, I've removed from the |
57bf773
to
ad67fe9
Compare
Good catch, added a more specific part to the
I think it's fair to leave this one out for now. This one requires some extra thought. I added three extra test cases for the |
d858ec2
to
f75bd23
Compare
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.
However, I've removed from the
NON_EMPTY_MONO
set the methodsdefaultIfEmpty
(as it produced aFlux
not aMono
)
Check, that would be a type change. I rebased and added a comment about this, because ideally we introduce a generalization which does cover this case.
Next up: reviewing the tests.
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.
Really cool check @cernat-catalin, I'm curious what the downstream impact will be! 🚀
Suggested commit message:
Introduce `NonEmptyMono` check (#200)
P.s: Notice the nice PR number 😄.
f75bd23
to
1c832a8
Compare
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.
Rebased and added a commit with test cases for other overloads.
Very nice check!
"import reactor.core.publisher.Mono;", | ||
"", | ||
"class A {", | ||
" void m() {", |
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 should also add a few more expressions that aren't flagged.
Cool stuff! Thanks @rickie and @Stephan202 for the latest additions.
Nice round number! |
Latest changes LGTM!
Me too! 😄 |
Avoid doing
Flux#collect(...)
(and similar collector methods) followed by methods that check for an empty source (e.g.Mono#single()
,Mono#defaultIfEmpty(...)
,Mono#switchIfEmpty
) as collect method on a flux always emit a value (empty collection for an empty flux)See discussion here: https://teampicnic.slack.com/archives/C0172BMUWNL/p1660557240599619