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

Prefer simple null reference check over calling Objects#{isNull,nonNull} #228

Merged
merged 8 commits into from
Sep 10, 2022

Conversation

jeandersonbc
Copy link
Contributor

@jeandersonbc jeandersonbc commented Sep 8, 2022

This PR introduces rules to prefer the use of == and != over Objects.isNull and Objects.nonNull for null checks on expressions.

Suggested commit message:

Prefer simple `null` reference check over `Objects#{isNull,nonNull}` (#228)

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 some comments.

I'm also fine with applying the suggestions myself, but I figured it could also be the nice part of this PR and playing around with Refaster, so I left most un-applied :).

@@ -22,4 +24,18 @@ long testIsNullFunction() {
long testNonNullFunction() {
return Stream.of("foo").filter(s -> s != null).count();
}

boolean testIsNullReference() {
var ref1 = "foo";
Copy link
Member

Choose a reason for hiding this comment

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

We do not use var in this codebase :).

Copy link
Member

Choose a reason for hiding this comment

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

We can simplify the tests quite a bit, we only need a simple and singular test case per before template. Besides that, we prefer using ImmutableSets over Sets. I don't think we need a Set here TBH and can have simplified test :).

As a reference, see other tests for the other templates from NullTemplates :).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure! My thought originally was to see whether refaster would match and apply the transformation for the 3 cases (including inferred type with var). I'm updating the test input/output.

*/
static final class IsNullReference<T> {
@BeforeTemplate
boolean before(@Nullable T ref) {
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
boolean before(@Nullable T ref) {
boolean before(@Nullable Object object) {

The parameter for isNull is Object therefore we can be more specific than using T. In such cases we name the parameter of the before template something like object or obj.

Copy link
Member

Choose a reason for hiding this comment

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

This also holds for the other template.

* Prefer <code>==</code> operator over {@link java.util.Objects#isNull(Object)} on boolean
* expressions.
*/
static final class IsNullReference<T> {
Copy link
Member

Choose a reason for hiding this comment

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

We have the convention to name Refaster templates after the content of the after template. In this case there is not a lot of content in the after template, but I'd suggest naming it something like:
ObjectEqualNull or ObjectEqualsNull.

The other template could be something like ObjectNotEqualNull.

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.

Another thought.

@@ -55,4 +56,30 @@ Predicate<T> after() {
return Objects::nonNull;
}
}

/** Prefer the <code>==</code> operator over {@link java.util.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.

Perhaps better to add for null checks? To the Javadoc, WDYT?

@jeandersonbc jeandersonbc requested a review from rickie September 9, 2022 07:21
@rickie rickie added this to the 0.2.1 milestone Sep 9, 2022
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 look good to me! Thanks for opening the PR @jeandersonbc 🚀 !

Suggested commit message:

Prefer simple `null` reference check over calling `Objects#{isNull,nonNull}` (#228)

@@ -22,4 +23,14 @@ long testIsNullFunction() {
long testNonNullFunction() {
return Stream.of("foo").filter(s -> s != null).count();
}

boolean testObjectEqualsNull() {
Object obj = null;
Copy link
Member

Choose a reason for hiding this comment

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

I think we can even use a simple String "foo" for this, will push a proposal.

@rickie
Copy link
Member

rickie commented Sep 9, 2022

Discussed some things offline with @Stephan202 , applied the feedback 😄. W.r.t. the naming suggestion for the template, it's hard but we plan to formalize this :).

Jeanderson Candido and others added 8 commits September 10, 2022 13:12
Augments NullTemplates to prefer == and != operators over Objects.isNull and
Objects.nonNull on boolean expressions.

E.g., ref == null is preferable over Objects.isNull(ref)
- Updated Javadoc
- Updated naming convention
- Updated test input/output
@Stephan202 Stephan202 force-pushed the jeandersonbc/null-check branch from ee7a386 to 478902e Compare September 10, 2022 11:24
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. Moved the templates up in the file, as they seem more "fundamental".

(If/when we sort templates lexicographically this'll change, but that's for another day.)

Slightly tweaked the suggested commit message; @rickie feel free to merge if you're okay with the changes.

Comment on lines 60 to 62
/**
* Prefer the {@code ==} operator over {@link java.util.Objects#isNull(Object)} for null checks.
*/
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 the {@code ==} operator over {@link java.util.Objects#isNull(Object)} for null checks.
*/
/** Prefer the {@code ==} operator over {@link Objects#isNull(Object)}. */

Comment on lines 75 to 77
/**
* Prefer the {@code !=} operator over {@link java.util.Objects#isNull(Object)} for null checks.
*/
Copy link
Member

Choose a reason for hiding this comment

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

Wrong method referenced 👀

@rickie
Copy link
Member

rickie commented Sep 10, 2022

Rebased and added a commit. Moved the templates up in the file, as they seem more "fundamental".

SGTM.

Nice catch with the Javadoc.

@rickie rickie changed the title Introduce rules for null check on references Prefer simple null reference check over calling Objects#{isNull,nonNull} Sep 10, 2022
@rickie rickie merged commit e34c2ba into master Sep 10, 2022
@rickie rickie deleted the jeandersonbc/null-check branch September 10, 2022 12:37
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