Skip to content
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

Merged
merged 2 commits into from
Sep 18, 2022

Conversation

rickie
Copy link
Member

@rickie rickie commented Sep 13, 2022

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 of improvement right, as the Matcher is now available for use.

@rickie rickie requested a review from Stephan202 September 13, 2022 09:18
@rickie rickie added this to the 0.2.1 milestone Sep 13, 2022
import com.sun.source.tree.ExpressionTree;

/** A matcher of {@link Character}-typed expressions. */
public final class IsCharacter implements Matcher<ExpressionTree> {
Copy link
Member Author

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.

Copy link
Contributor

@CoolTomatos CoolTomatos left a 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> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we "generify" this?

Copy link
Member Author

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 Matchers we want to use.

Good question though 😉.

Copy link
Member

@Stephan202 Stephan202 Sep 17, 2022

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.

Base automatically changed from sschroevers/prefer-mono-from-supplier to master September 15, 2022 07:42
@Stephan202 Stephan202 force-pushed the rossendrijver/char_matcher branch from 774f8b7 to cb9fc83 Compare September 17, 2022 17:43
Copy link
Member

@Stephan202 Stephan202 left a 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> {
Copy link
Member

@Stephan202 Stephan202 Sep 17, 2022

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.

Copy link
Member

@Stephan202 Stephan202 left a 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.
Copy link
Member

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.

Copy link
Member Author

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.
Copy link
Member

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));
Copy link
Member

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:

Suggested change
anyOf(isSameType(Character.class), isSameType(s -> s.getSymtab().charType));
anyOf(isSameType(CHAR_TYPE), isSameType(Character.class));

Comment on lines 25 to 48
" 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;",
" }",
Copy link
Member

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).

Copy link
Member Author

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 {
Copy link
Member

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.)

@rickie
Copy link
Member Author

rickie commented Sep 18, 2022

Changes LGTM and the suggested commit message as well 👍🏻.

@Stephan202 Stephan202 merged commit bfc951b into master Sep 18, 2022
@Stephan202 Stephan202 deleted the rossendrijver/char_matcher branch September 18, 2022 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

3 participants