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

Fix PMD rule LiteralsFirstInComparisons for compareTo* and contentEquals #362

Open
punkratz312 opened this issue Oct 14, 2024 · 7 comments
Assignees
Labels
good first issue Good for newcomers recipe

Comments

@punkratz312
Copy link
Contributor

punkratz312 commented Oct 14, 2024

Simply switch the arguments; that should be a very small change to make, just similar to the Inline Variable recipe.

What problem are you trying to solve?

https://pmd.github.io/pmd/pmd_rules_java_bestpractices.html#literalsfirstincomparisons

Describe the situation before applying the recipe

class A {
    boolean bar(String x) {
        return x.equals("2"); // should be "2".equals(x)
    }
}

Describe the situation after applying the recipe

class A {
    boolean bar(String x) {
        return "2".equals(x);
    }
}

Further examples from the PMD:

class Foo {
    boolean bar(String x) {
        return x.equals("2"); // should be "2".equals(x)
    }
    boolean bar(String x) {
        return x.equalsIgnoreCase("2"); // should be "2".equalsIgnoreCase(x)
    }
    boolean bar(String x) {
        return (x.compareTo("bar") > 0); // should be: "bar".compareTo(x) < 0
    }
    boolean bar(String x) {
        return (x.compareToIgnoreCase("bar") > 0); // should be: "bar".compareToIgnoreCase(x) < 0
    }
    boolean bar(String x) {
        return x.contentEquals("bar"); // should be "bar".contentEquals(x)
    }
}
@punkratz312
Copy link
Contributor Author

punkratz312 commented Oct 14, 2024

I would love to volunteer and implement it if you could provide me with the snippet to flip the arguments. It should be very similar to my favorite rule, 1488 InlineVariable. https://docs.openrewrite.org/recipes/staticanalysis/inlinevariable.

@knutwannheden
Copy link
Contributor

For the equals() case there is already a recipe here: https://github.com/openrewrite/rewrite-static-analysis/blob/main/src/main/java/org/openrewrite/staticanalysis/EqualsAvoidsNull.java. The others are not covered as far as I know.

@timtebeek
Copy link
Contributor

Thanks for the offer to help @punkratz312 ! As Knut has indicated String#equals and String#equalsIgnoreCase are already handled in this existing recipe:

public class EqualsAvoidsNullVisitor<P> extends JavaVisitor<P> {
private static final MethodMatcher STRING_EQUALS = new MethodMatcher("String equals(java.lang.Object)");
private static final MethodMatcher STRING_EQUALS_IGNORE_CASE = new MethodMatcher("String equalsIgnoreCase(java.lang.String)");

I suppose contentEquals could easily be added there as well, and we'd welcome such a change. Once that's covered a separate recipe can likely do the same for compareTo and compareToIgnoreCase.

Great to see you join the project and actively look for areas to improve. :)

@timtebeek timtebeek moved this to Backlog in OpenRewrite Oct 14, 2024
@timtebeek timtebeek changed the title LiteralsFirstInComparisons Fix PMD rule LiteralsFirstInComparisons for compareTo* and contentEquals Oct 14, 2024
@timtebeek timtebeek moved this from Backlog to Recipes Wanted in OpenRewrite Oct 14, 2024
@timtebeek timtebeek added good first issue Good for newcomers recipe labels Oct 14, 2024
@punkratz312
Copy link
Contributor Author

punkratz312 commented Oct 14, 2024

Thanks for the quick win! I'm looking forward to this fix in our codebase. When will it be available after the merge?

@timtebeek
Copy link
Contributor

Once merged it'll be available from our snapshot versions in a matter of minutes (provided the build succeeds). From there it'll get included in the next release; which is every other week on Wednesday, with the next one on the 23rd. Thanks again!

@timtebeek
Copy link
Contributor

@timtebeek
Copy link
Contributor

A subtlety was missed in the earlier implementation, where the comparison used with compareTo needs to be inverted, such that < 0 becomes > 0, as pointed out in

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers recipe
Projects
Archived in project
Development

No branches or pull requests

3 participants