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

EqualsVerifier.forPackage fails in presence of classes with anonymous/local inner classes #517

Closed
kilink opened this issue Oct 12, 2021 · 4 comments

Comments

@kilink
Copy link
Contributor

kilink commented Oct 12, 2021

EqualsVerifier.forPackage picks up anonymous/local inner classes, which causes verification to fail.

Contrived example, we have a package net.kilink.example with a single class Thing.java, which happens to have methods with inner anonymous and local class referrences:

package net.kilink.example;

import java.util.Objects;
import java.util.function.Supplier;

public final class Thing {
    private String name;

    public Thing(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Thing)) return false;
        Thing thing = (Thing) o;
        return Objects.equals(name, thing.name);
    }

    public Supplier<String> nameSupplier() {
        return new Supplier<String>() {
            @Override
            public String get() {
                return name;
            }
        };
    }

    public Supplier<String> localClassNameSupplier() {
        class ThingNameSupplier implements Supplier<String> {
            @Override
            public String get() {
                return name;
            }
        }
        return new ThingNameSupplier();
    }
}

And then running EqualsVerifier like so:

EqualsVerifier.forPackage("net.kilink.example").verify();

We end up with the following failures:

EqualsVerifier found a problem in class net.kilink.example.Thing$1ThingNameSupplier.
-> Equals is inherited directly from Object.
Suppress Warning.INHERITED_DIRECTLY_FROM_OBJECT to skip this check.

...

EqualsVerifier found a problem in class net.kilink.example.Thing$1.
-> Equals is inherited directly from Object.
Suppress Warning.INHERITED_DIRECTLY_FROM_OBJECT to skip this check.

Note that this happens regardless of whether the anonymous / local class is returned from the method.

This fails even worse in the presence of a Guava / Gson TypeToken anonymous class. I think the package scanner can simply skip anonymous and local classes to work around the issue; the test suite all passes with that change, and I am struggling to think fo a legitimate scenario for scanning these.

@jqno
Copy link
Owner

jqno commented Oct 13, 2021

Thanks for the PR! I think it's a good idea to merge it, but maybe we can still add a test case for a synthetic class, as PITest suggests?

@kilink
Copy link
Contributor Author

kilink commented Oct 13, 2021

Thinking about it, in practice it can never be a synthetic class, which is a runtime generated class like a proxy. I've just removed the line filtering for synthetic classes altogether.

@jqno
Copy link
Owner

jqno commented Oct 14, 2021

Sounds good!
Thanks for the PR. I've merged it and will let you know when I make a release.

@jqno
Copy link
Owner

jqno commented Oct 15, 2021

Version 3.7.2 is syncing with Maven Central right now!

@jqno jqno closed this as completed Oct 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants