micronaut-projects / micronaut-sourcegen

Compilation time source code generators
Apache License 2.0
7 stars 3 forks source link

Generate toString, equals and hashCode implementations #126

Open andriy-dmytruk opened 1 month ago

andriy-dmytruk commented 1 month ago

Feature description

We can generate implementations for these methods to simplify development. We should probably include superclasses.

Since we cannot generate methods in the original class, we could generate something like [classname]Utils similarly to the way we generate [classname]Builder. Then the original class would reference the generated utility methods instead of needing to implement them similarly to how builder() static method can return a new builder.

Swagger generator mustache templates can be used as a reference, although we probably cannot support all the features, like hiding password in toString:

@Override
    public String toString() { {{#format-2}}
        java.lang.StringBuilder sb = new java.lang.StringBuilder();
        sb.append("{{classname}} (");
        {{#allVars}}
        sb.append("{{^-first}}, {{/-first}}{{name}}=");
            {{^isByteArray}}
                {{#isFormatPassword}}
        sb.append({{#isFormatPassword}}"<redacted>"{{/isFormatPassword}});
                {{/isFormatPassword}}
                {{^isFormatPassword}}
        sb.append(String.valueOf({{getter}}()));
                {{/isFormatPassword}}
            {{/isByteArray}}
            {{#isByteArray}}
        sb.append(String.valueOf({{getter}}()) + ({{getter}}() != null ? " (byte[" + {{getter}}().length + "])" : ""));
            {{/isByteArray}}
        {{/allVars}}
        sb.append(")");
        return sb.toString();
        {{/format-2}}
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof {{classname}})) {
            return false;
        }

        {{classname}} other = ({{classname}}) o;
        return {{#vars}}{{^-first}}    {{/-first}}{{^isByteArray}}java.util.Objects.equals(this.{{name}}, other.{{name}}){{/isByteArray}}{{#isByteArray}}java.util.Arrays.equals(this.{{name}}, other.{{name}}){{/isByteArray}}{{^-last}} &&
        {{/-last}}{{/vars}}{{^parent}}{{/parent}}{{#parent}}{{#hasVars}} &&
            {{/hasVars}}super.equals(other){{/parent}}{{^parent}}{{^hasVars}}true{{/hasVars}}{{/parent}};
    }

    @Override
    public int hashCode() {
        final int PRIME = 59;
        int result = {{#discriminator}}{{^hasSubtypes}}{{#parent}}super.hashCode(){{/parent}}{{^parent}}1{{/parent}}{{/hasSubtypes}}{{#hasSubtypes}}1{{/hasSubtypes}}{{/discriminator}}{{^discriminator}}1{{/discriminator}};
        {{#vars}}
        result = (result * PRIME) + {{^isByteArray}}(this.{{name}} == null ? 43 : this.{{name}}.hashCode()){{/isByteArray}}{{#isByteArray}}java.util.Arrays.hashCode(this.{{name}}){{/isByteArray}};
        {{/vars}}
        return result;
    }
graemerocher commented 1 month ago

great idea