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

Extend null check Refaster rules #523

Merged
merged 9 commits into from
Mar 27, 2023
Merged

Conversation

Ptijohn
Copy link
Contributor

@Ptijohn Ptijohn commented Mar 7, 2023

Follow up of this issue.

Suggested commit message:

Extend `null` check Refaster rules (#523)

Summary of changes:
- Replace `CheckNotNull` with `RequireNonNull{,WithMessage}{,Statement}`.
- Extend `Is{,Not}Null`.

Fixes #437.

@Ptijohn Ptijohn requested a review from rickie March 7, 2023 08:41
@github-actions
Copy link

github-actions bot commented Mar 7, 2023

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

3 similar comments
@github-actions
Copy link

github-actions bot commented Mar 7, 2023

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

@github-actions
Copy link

github-actions bot commented Mar 7, 2023

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

@github-actions
Copy link

github-actions bot commented Mar 7, 2023

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

@Ptijohn Ptijohn force-pushed the bdiederichs/require-not-null branch from 0181a9a to 942c604 Compare March 10, 2023 12:31
@github-actions
Copy link

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

1 similar comment
@github-actions
Copy link

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

Copy link
Member

@rickie rickie 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.

Changes LGTM 😄. Added an extra template to make our lives easier. We can make more assumptions about the code and we need to account for less cases.

@@ -78,7 +79,7 @@ void after(int index, int size, String message) {
static final class RequireNonNull<T> {
@BeforeTemplate
void before(T object) {
if (object == null) {
if (Refaster.anyOf(object == null, null == object)) {
Copy link
Member

Choose a reason for hiding this comment

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

Instead of having to add the inverse check, we can add another Refaster rule that rewrites null == object to object == null. That allows us to simplify the code in many other places.

@rickie rickie force-pushed the bdiederichs/require-not-null branch from 791ca72 to 1f2a953 Compare March 21, 2023 08:27
@rickie
Copy link
Member

rickie commented Mar 21, 2023

Rebased and tweaked suggested commit message.

@github-actions
Copy link

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

@rickie rickie requested a review from Stephan202 March 21, 2023 10:43
@rickie rickie added this to the 0.9.0 milestone Mar 21, 2023
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 and added a commit. Open point is about the IllegalArgumentException changes; IMHO those should be omitted.

checkArgument(clazz != null, "Visited node is not enclosed by a class");
requireNonNull(clazz, "Visited node is not enclosed by a class");
Copy link
Member

Choose a reason for hiding this comment

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

The fact that we're validating the input though a null check is a function of the findEnclosing API; it could also have returned an Optional<ClassTree>. In this case IllegalArgumentException seems like a more appropriate exception to throw. (IllegalStateException could perhaps also work.)

I don't have strong options for this particular bit of code, but IMHO it shows that we should not apply the checkArgument rewrite below 👇

Copy link
Member

Choose a reason for hiding this comment

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

Hmm this is a difficult one. A GH code search shows there are quite some good improvements here. However, indeed some of them are not entirely correct.

There is only one heuristic that comes to mind, but that is probably a bit weird and odd. If the message contains "null" than it's a good check in all our cases. However, I see why this wouldn't fly for the OSS world 😋.

In that case, we should indeed drop it 🤔.

Copy link
Member

Choose a reason for hiding this comment

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

Dropping is the safe way forward 👍

@@ -25,6 +25,11 @@ private NullRules() {}
static final class IsNull {
@BeforeTemplate
boolean before(@Nullable Object object) {
return null == object;
Copy link
Member

Choose a reason for hiding this comment

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

Nice one. Let's also update the documentation.

Comment on lines 91 to 103
@BeforeTemplate
void before3(T object) {
checkArgument(object != null);
}
Copy link
Member

Choose a reason for hiding this comment

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

As mentioned above, IMHO this change is too invasive/opinionated for this check. Note that impacted code may be part of a method with a documented contract of throwing IllegalArgumentException rather than NullArgumentException.

@@ -72,35 +74,55 @@ void after(int index, int size, String message) {
}
}

/** Prefer {@link Preconditions#checkNotNull(Object)} over more verbose alternatives. */
static final class CheckNotNull<T> {
/** Prefer {@link Objects#requireNonNull(Object)} over more verbose alternatives. */
Copy link
Member

Choose a reason for hiding this comment

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

checkNotNull is not more verbose 👀

@BeforeTemplate
void before(T object) {
if (object == null) {
throw new NullPointerException();
}
}

@BeforeTemplate
void before2(T object) {
checkNotNull(object);
Copy link
Member

Choose a reason for hiding this comment

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

This rule won't match expressions of this type. The way Renovate works, we'll need a separate rule for that. (And then drop the rule here, because expression rules match statements, but not vice versa.)

Copy link
Member

Choose a reason for hiding this comment

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

Haha Renovate 😉. But good one, this is where I should improve with reviewing 🤔.

Comment on lines 31 to 32
@BeforeTemplate
boolean before2(@Nullable Object object) {
return Objects.isNull(object);
}
Copy link
Member

Choose a reason for hiding this comment

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

Here and below: we can use Refaster.anyOf.

Copy link
Member

Choose a reason for hiding this comment

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

You are right (I hear you say it hehe) we should automate this :).

Copy link
Member

Choose a reason for hiding this comment

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

Indeed we should ;)

@Stephan202 Stephan202 force-pushed the bdiederichs/require-not-null branch from 1f2a953 to 26c323f Compare March 26, 2023 18:19
@github-actions
Copy link

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

Copy link
Member

@rickie rickie 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 and answered the open points :).

checkArgument(clazz != null, "Visited node is not enclosed by a class");
requireNonNull(clazz, "Visited node is not enclosed by a class");
Copy link
Member

Choose a reason for hiding this comment

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

Hmm this is a difficult one. A GH code search shows there are quite some good improvements here. However, indeed some of them are not entirely correct.

There is only one heuristic that comes to mind, but that is probably a bit weird and odd. If the message contains "null" than it's a good check in all our cases. However, I see why this wouldn't fly for the OSS world 😋.

In that case, we should indeed drop it 🤔.

Comment on lines 31 to 32
@BeforeTemplate
boolean before2(@Nullable Object object) {
return Objects.isNull(object);
}
Copy link
Member

Choose a reason for hiding this comment

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

You are right (I hear you say it hehe) we should automate this :).

@BeforeTemplate
void before(T object) {
if (object == null) {
throw new NullPointerException();
}
}

@BeforeTemplate
void before2(T object) {
checkNotNull(object);
Copy link
Member

Choose a reason for hiding this comment

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

Haha Renovate 😉. But good one, this is where I should improve with reviewing 🤔.

@BeforeTemplate
void before(T object) {
if (object == null) {
throw new NullPointerException();
}
}

@BeforeTemplate
void before3(T object) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
void before3(T object) {
void before2(T object) {

/** Prefer {@link Objects#requireNonNull(Object, String)} over non-JDK alternatives. */
static final class RequireNonNullWithMessage<T> {
@BeforeTemplate
T before2(T object, String message) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
T before2(T object, String message) {
T before(T object, String message) {

@github-actions
Copy link

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

}
}

/** Prefer {@link Objects#requireNonNull(Object)} over non-JDK alternatives. */
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/** Prefer {@link Objects#requireNonNull(Object)} over non-JDK alternatives. */
/** Prefer {@link Objects#requireNonNull(Object)} over more verbose or non-JDK alternatives. */

But, assuming we drop the checkArgument check:

Suggested change
/** Prefer {@link Objects#requireNonNull(Object)} over non-JDK alternatives. */
/** Prefer {@link Objects#requireNonNull(Object)} over more verbose alternatives. */

checkArgument(clazz != null, "Visited node is not enclosed by a class");
requireNonNull(clazz, "Visited node is not enclosed by a class");
Copy link
Member

Choose a reason for hiding this comment

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

Dropping is the safe way forward 👍

Copy link
Member

@rickie rickie 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 and rebased.

@rickie rickie force-pushed the bdiederichs/require-not-null branch from 9d8141e to 94900a4 Compare March 27, 2023 19:43
@rickie
Copy link
Member

rickie commented Mar 27, 2023

One open question is how to address the "Statement" part of the Refaster rules in the suggested commit message. I'm not sure if it adds value to put it there. Any suggestions @Stephan202 ?

@github-actions
Copy link

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

1 similar comment
@github-actions
Copy link

Looks good. No mutations were possible for these changes.
Mutation testing report by Pitest. Review any surviving mutants by inspecting the line comments under Files changed.

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.

Not sure either, but proposed something ;).

Code changes LGTM!

@rickie rickie changed the title Rewrite null check variants to requireNonNull Extend null check Refaster rules Mar 27, 2023
@rickie rickie merged commit 334c374 into master Mar 27, 2023
@rickie rickie deleted the bdiederichs/require-not-null branch March 27, 2023 20:08
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