-
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 IsCharacter
matcher and assorted test improvements
#237
Conversation
import com.sun.source.tree.ExpressionTree; | ||
|
||
/** A matcher of {@link Character}-typed expressions. */ | ||
public final class IsCharacter implements Matcher<ExpressionTree> { |
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.
Was doubting a bit about the name. We flag both char
and Character
🤔. Not sure how to reflect it in the name, especially considering Refaster does auto-boxing by default. Therefore I went for this one.
79c9139
to
774f8b7
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.
Thanks.
import com.sun.source.tree.ExpressionTree; | ||
|
||
/** A matcher of {@link Character}-typed expressions. */ | ||
public final class IsCharacter implements Matcher<ExpressionTree> { |
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.
Shall we "generify" this?
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.
The idea of a Matcher
is to be specific in cases like this actually. We have to use this in a @Matches(value)
or @NotMatches(value)
annotation where value
is:
Class<? extends Matcher<? super ExpressionTree>> value();
This setup limits the expressiveness of specifying what Matcher
s we want to use.
Good question though 😉.
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.
To be more explicit about the limitation we're facing here: we can't pass constructor parameters.
774f8b7
to
cb9fc83
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, since #232 was merged
import com.sun.source.tree.ExpressionTree; | ||
|
||
/** A matcher of {@link Character}-typed expressions. */ | ||
public final class IsCharacter implements Matcher<ExpressionTree> { |
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.
To be more explicit about the limitation we're facing here: we can't pass constructor parameters.
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.
Suggested commit message:
Introduce `IsCharacter` matcher for use by Refaster templates (#237)
This new matcher is used to improve the `AssertThatIsOdd` and
`AssertThatIsEven` Refaster templates.
While there, apply assorted semi-related test improvements.
/** | ||
* Prefer {@link AbstractLongAssert#isOdd()} over more contrived alternatives. | ||
* | ||
* <p>Note that for {@link Character}s this rewrite would lead to non-compilable code. |
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 about being non-compilable, but that the alternative is not available.
That said, I still feel like this can be left out: it's implied, and people doubting can just try to see what happens if @NotMatches(IsCharacter.class)
is omitted.
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.
Ah correct, should've been more specific here.
@@ -226,9 +228,14 @@ AbstractBigDecimalAssert<?> before(AbstractBigDecimalAssert<?> numberAssert) { | |||
} | |||
} | |||
|
|||
/** | |||
* Prefer {@link AbstractLongAssert#isOdd()} over more contrived alternatives. |
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 just AbstractLongAssert#isOdd()
. Would also argue that the original code isn't contrived, but rather that it yields a less informative error message.
public final class IsCharacter implements Matcher<ExpressionTree> { | ||
private static final long serialVersionUID = 1L; | ||
private static final Matcher<ExpressionTree> DELEGATE = | ||
anyOf(isSameType(Character.class), isSameType(s -> s.getSymtab().charType)); |
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 suspect that the second case is more common. I.c.w. a predefined supplier we can do:
anyOf(isSameType(Character.class), isSameType(s -> s.getSymtab().charType)); | |
anyOf(isSameType(CHAR_TYPE), isSameType(Character.class)); |
" Character positive1() {", | ||
" // BUG: Diagnostic contains:", | ||
" return 'a';", | ||
" }", | ||
"", | ||
" Character positive2() {", | ||
" // BUG: Diagnostic contains:", | ||
" return Character.valueOf('a');", | ||
" }", | ||
"", | ||
" char positive3() {", | ||
" // BUG: Diagnostic contains:", | ||
" return \"a\".charAt(1);", | ||
" }", | ||
"", | ||
" char positive4() {", | ||
" // BUG: Diagnostic contains:", | ||
" return Character.valueOf((char) 1);", | ||
" }", | ||
"", | ||
" char positive5() {", | ||
" // BUG: Diagnostic contains:", | ||
" return (char) 1;", | ||
" }", |
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.
All these test cases also pass if we match only against isSameType(s -> s.getSymtab().charType)
(because they all contain a char
-typed (sub)expression).
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.
Ai, I thought I checked this 😬.
import com.google.errorprone.bugpatterns.BugChecker; | ||
import org.junit.jupiter.api.Test; | ||
|
||
final class IsCharacterTest { |
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.
Suggest we also verify that non-char primitives aren't flagged. (Not super relevant given the current IsCharacter
, but one could be tempted to perform a refactor that would then match too much.)
Changes LGTM and the suggested commit message as well 👍🏻. |
We extracted some commits from #225 to this PR and introduced the
IsCharacter
matcher.Didn't list the exact test improvements, as it feels too specific to mention in the suggested commit message.
I think this qualifies as
new feature
instead ofimprovement
right, as theMatcher
is now available for use.