Bug 424214 - Generation of equals and hashcode with java 7 Objects.equals and Objects.hashcode
Summary: Generation of equals and hashcode with java 7 Objects.equals and Objects.hash...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.4   Edit
Hardware: All All
: P3 enhancement with 27 votes (vote)
Target Milestone: 4.9 M3   Edit
Assignee: Pierre-Yves Bigourdan CLA
QA Contact: Till Brychcy CLA
URL:
Whiteboard:
Keywords: bugday, helpwanted, noteworthy
: 462484 (view as bug list)
Depends on:
Blocks:
 
Reported: 2013-12-17 04:57 EST by nicolas correard CLA
Modified: 2018-09-27 16:07 EDT (History)
32 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description nicolas correard CLA 2013-12-17 04:57:07 EST
A lot of us rely on the code generation for our equals and hashcode methods. This works wonders and alleviates the need to write long methods, which is error-prone.

Since Java 7, there are ways to write these methods in a more concise way, using Objects.equals and Objects.hashcode.

There were already some libraries to do this (apache, guava), and some eclipse plugins that were handling this. But the great advantage here is that this is pure java! 

At the moment, it is not possible to write a custom template in Eclipse to have this generated properly, this requires a core change.

http://stackoverflow.com/questions/17782032/how-to-teach-eclipse-to-generate-compact-equals-and-hashcode-from-the-jdk-7


Regards,
Nicolas
Comment 1 Lars Vogel CLA 2015-11-16 03:57:39 EST
I think this belongs to JDT UI, as a change in GenerateHashCodeEqualsDialog/SourceActionDialog is required.
Comment 2 Lars Vogel CLA 2015-11-16 03:59:47 EST
Also GenerateHashCodeEqualsAction needs to be adjusted.
Comment 3 Noopur Gupta CLA 2016-06-13 04:43:04 EDT
*** Bug 462484 has been marked as a duplicate of this bug. ***
Comment 4 Ivan Konstantinov CLA 2016-09-14 05:37:51 EDT
Hello,

Is anyone working on a fix for this bug? I'd like to help out with that.
Comment 5 Lars Vogel CLA 2016-09-14 05:46:03 EDT
> Is anyone working on a fix for this bug? I'd like to help out with that.

Markus set the keywords "bugday, helpwanted" so I assume help is welcome. If you are new to Gerrit, you can use http://www.vogella.com/tutorials/EclipsePlatformDevelopment/article.html
Comment 6 Ivan Konstantinov CLA 2016-09-14 05:52:05 EDT
(In reply to Lars Vogel from comment #5)
> > Is anyone working on a fix for this bug? I'd like to help out with that.
> 
> Markus set the keywords "bugday, helpwanted" so I assume help is welcome. If
> you are new to Gerrit, you can use
> http://www.vogella.com/tutorials/EclipsePlatformDevelopment/article.html

Thanks!
Comment 7 Eclipse Genie CLA 2016-09-15 07:43:57 EDT
New Gerrit change created: https://git.eclipse.org/r/81158
Comment 8 Ivan Konstantinov CLA 2016-09-30 03:47:14 EDT
Hi,

I uploaded an update on the Gerrit change, https://git.eclipse.org/r/81158
The build failed, with the build info page here: https://hudson.eclipse.org/platform/job/eclipse.jdt.ui-Gerrit/945/
I checked the build log, and also the error, it seems one particular test fails, which is 
org.eclipse.jdt.ui.tests.refactoring.ExtractConstantTests.test25 (from org.eclipse.jdt.ui.tests.refactoring.all.AllAllRefactoringTests) 

The actual test is this one:

public void test25() throws Exception {
	helper1(5, 27, 5, 40, false, false, "DEFAULT_NAME", "JEAN_PIERRE");
}

The console output from the build process ends with this,
[ERROR] Failed to execute goal org.eclipse.tycho:tycho-surefire-plugin:0.25.0:test (default-test) on project org.eclipse.jdt.ui.tests.refactoring: There are test failures.

I'm not sure what I'm supposed to do here, because I haven't touched this test case and it's not related to the change I've introduced. Also, I tested AllAllRefactoringTests locally and all tests were successful.

I'd appreciate any help with this, thanks.
Ivan
Comment 9 Ivan Konstantinov CLA 2016-10-03 05:19:28 EDT
https://git.eclipse.org/r/#/c/81158/

Verification and build successful.

Ivan
Comment 10 Till Brychcy CLA 2017-03-06 17:14:56 EST
@Noopur, I'm not sure if you have seen that there is a gerrit by a contributor.

There is a small merge conflict in GenerateHashCodeEqualsOperation caused by the change for bug 443146 which added TypeLocation-parameters to the ImportRewrite.addImport-calls.

I've rebased it in my workspace and tried it. I've noted two things:
- the setting "use 'instanceof' to compare types" isn't handled (that is 'instanceof' is always used when the option to use the java 7 methods is enabled)
- the option should probably be disabled, if the project uses java 6 or earlier.

So this still needs some work, but I don't think it is too late for 4.7
Comment 11 Noopur Gupta CLA 2017-03-07 02:06:19 EST
Thanks for taking a look, Till.

@Ivan, could you please handle the cases mentioned by Till in comment #10 so that the patch is ready for review?
Comment 12 Ivan Konstantinov CLA 2017-03-09 09:28:21 EST
Hi @Noopur,

Yes, I will look into it.

Thanks,
Ivan
Comment 13 Wenjie Zhang CLA 2017-04-01 18:59:01 EDT
Any idea when will this feature become available?
Comment 14 Noopur Gupta CLA 2017-04-03 05:22:37 EDT
(In reply to Wenjie Zhang from comment #13)
> Any idea when will this feature become available?

It is currently targetted for 4.7.

(In reply to Ivan Konstantinov from comment #12)
> Yes, I will look into it.

Ivan, I do not see any changes from comment #10 in patch set 10. Please add a comment when the patch is ready for review.
Comment 15 Ivan Konstantinov CLA 2017-04-03 07:47:44 EDT
(In reply to Noopur Gupta from comment #14)
> (In reply to Wenjie Zhang from comment #13)
> > Any idea when will this feature become available?
> 
> It is currently targetted for 4.7.
> 
> (In reply to Ivan Konstantinov from comment #12)
> > Yes, I will look into it.
> 
> Ivan, I do not see any changes from comment #10 in patch set 10. Please add
> a comment when the patch is ready for review.

Hi,

Patch set 11 is ready for review, I've implemented some checks as per comment #10.
Comment 16 Ivan Konstantinov CLA 2017-04-03 09:22:11 EDT
Tests have failed, so the patch is not ready yet.
Comment 17 Ivan Konstantinov CLA 2017-04-04 03:30:49 EDT
Patch set 13 is ready for review.

Ivan
Comment 18 Noopur Gupta CLA 2017-04-07 05:19:11 EDT
- Patch set 13 still doesn't handle this from comment #10:
the option should be disabled if the project uses java 6 or earlier.

- The generated #equals implementation results in NPE if the passed object is null.

- Use import statement and simple name for java.util.Objects instead of hard-coding the FQN.

- The #equals implementation still uses braces in at least one 'if' statement even when "Use blocks in 'if' statements" is not checked.

- Recheck the new implementation of methods, keeping it similar to the existing style.

- Please avoid code duplication.
Comment 19 Noopur Gupta CLA 2017-05-03 07:33:02 EDT
Ivan, I just tested your updated patch set 15 for the first review comment in comment #18 about the option being disabled for projects using Java 6 or earlier, and it is still not handled.

With a Java 5 project, the dialog doesn't show the new option at all and clicking OK still creates the methods using Objects methods resulting in compile errors.

Moving this to 4.8.
Comment 20 Ivan Konstantinov CLA 2017-05-03 08:48:56 EDT
(In reply to Noopur Gupta from comment #19)
> Ivan, I just tested your updated patch set 15 for the first review comment
> in comment #18 about the option being disabled for projects using Java 6 or
> earlier, and it is still not handled.
> 
> With a Java 5 project, the dialog doesn't show the new option at all and
> clicking OK still creates the methods using Objects methods resulting in
> compile errors.
> 
> Moving this to 4.8.

Interesting. When I tested this locally, including running all tests on GenerateHashCodeEqualsOperation, it seemed to work as desired, but now that I check, I get a different issue - with compliance level >= 1.7, I get the new option in the dialog but the resulting methods don't use Objects methods when checked.

I'll check again.
Comment 21 Ivan Konstantinov CLA 2017-06-19 16:08:27 EDT
Hi,
Patch is ready for review.
Ivan
Comment 22 Dani Megert CLA 2017-09-18 04:38:41 EDT
(In reply to Ivan Konstantinov from comment #21)
> Hi,
> Patch is ready for review.
> Ivan

Sorry, we are currently very busy getting Java 9 and JUnit 5 support out. Please ping again if we haven't look at this until January.
Comment 23 Mickael Istria CLA 2017-09-18 04:56:38 EDT
(In reply to Dani Megert from comment #22)
> Sorry, we are currently very busy getting Java 9 and JUnit 5 support out.
> Please ping again if we haven't look at this until January.

Putting M5 as deadline according to this comment. If someone feels able to work on this earlier and can help in getting it merged sooner, please change target version according to your availability.
Comment 24 Noopur Gupta CLA 2018-02-07 09:56:58 EST
Copying the comment from Gerrit:
Ivan, can you please rebase this change manually and confirm if all the earlier review comments are handled and the patch is ready for review?

Please request again for review when the patch is ready. 

Also, any help with an initial review will be appreciated.
Comment 25 Till Brychcy CLA 2018-02-23 13:25:55 EST
(In reply to Noopur Gupta from comment #24)
> Copying the comment from Gerrit:
> Ivan, can you please rebase this change manually and confirm if all the
> earlier review comments are handled and the patch is ready for review?
> 
> Please request again for review when the patch is ready. 
> 
> Also, any help with an initial review will be appreciated.

I'll have a look.
Comment 26 Till Brychcy CLA 2018-02-23 16:22:10 EST
- primitives (like int) should not be compared with Object.equals, this causes autoboxing
- mixing Objects.deepEquals(array, other.array) and Arrays.hashcode(array) for the same object is wrong, as Object[], Serializable[] and Cloneable[] can contain other arrays (the old code uses Arrays.equals(array) together with Arrays.hashcode(array) for these classes, which is at least consistent)
- the old code generates:
	if (getClass() != obj.getClass())
           return false;
  but the new code:
        if (getClass() == obj.getClass()) {
	...
	}
  this is inconsistent and also leads to some duplicated code.
- "java 7+" should probably be "1.7 or higher" to be consistent with other dialogs
- I think if would be more consistent if the checkbox is always present, but disabled for older java, but this is less important
Comment 27 Lars Vogel CLA 2018-02-27 04:01:51 EST
Ivan, are you still available to work on this patch? Sorry for the frequent delays in reviews but I think Till is really to act fast on any new fix you can provide.

If you lost interest in this contribution, please let us know.
Comment 28 Sarika Sinha CLA 2018-03-01 03:37:59 EST
Moving it to M7.
Comment 29 Lars Vogel CLA 2018-03-19 10:30:53 EDT
(In reply to Till Brychcy from comment #26)

I contact Ivan also via email and did not get a reply, I assume Ivan lost interest for this patch. Till, as you did already a review, could you maybe finish this patch?
Comment 30 Pierre-Yves Bigourdan CLA 2018-07-31 13:57:00 EDT
Hello,

I'm new to the Eclipse JDT UI project and to Gerrit, but I'm keen on helping out to get this feature added to Eclipse. I'll look into addressing the review comments listed by Till in the coming days/weeks.
Comment 31 Till Brychcy CLA 2018-08-01 04:49:30 EDT
(In reply to Pierre-Yves B. from comment #30)
> Hello,
> 
> I'm new to the Eclipse JDT UI project and to Gerrit, but I'm keen on helping
> out to get this feature added to Eclipse. I'll look into addressing the
> review comments listed by Till in the coming days/weeks.

Good to hear. Assigning to you.
Comment 32 Pierre-Yves Bigourdan CLA 2018-08-04 12:45:57 EDT
I'm pretty much done with the development work, but I'm having trouble submitting a new patch. I tried committing using the existing change ID (	
I1b7258d69f3925b77b2f72f017afc64da7a0cac0), but the following message is displayed: "You must be a committer to push on behalf of others.", as Ivan initially submitted the Gerrit Change. I'm guessing we want to keep things under the same Gerrit Change, how should I proceed from this point onwards?
Comment 33 Till Brychcy CLA 2018-08-04 13:02:47 EDT
make sure you are set as author but add an also-by header for Ivan.
If you still cannot push, use a fresh change Id.
Comment 34 Pierre-Yves Bigourdan CLA 2018-08-04 17:11:04 EDT
Okay, that solved the issue.

Till, I have hopefully addressed your five bullet points above. I have also added quite a few new unit tests and have refactored parts of the code written by Ivan to reduce duplication and tidy things up a little.

Object[], Serializable[] and Cloneable[] are now compared with deepEquals/deepHashCode, and in order to stay consistent and avoid duplicating very similar pieces of code, this change covers the non Java 7 version of the generator as well.
Comment 35 Dani Megert CLA 2018-08-06 06:43:05 EDT
Till, can you do the review?
Comment 36 Till Brychcy CLA 2018-08-06 07:14:08 EDT
(In reply to Dani Megert from comment #35)
> Till, can you do the review?

OK
Comment 37 Till Brychcy CLA 2018-08-06 13:09:12 EDT
(In reply to Pierre-Yves B. from comment #34)
> Okay, that solved the issue.
> 
> Till, I have hopefully addressed your five bullet points above. I have also
> added quite a few new unit tests and have refactored parts of the code
> written by Ivan to reduce duplication and tidy things up a little.
> 
> Object[], Serializable[] and Cloneable[] are now compared with
> deepEquals/deepHashCode, and in order to stay consistent and avoid
> duplicating very similar pieces of code, this change covers the non Java 7
> version of the generator as well.

Thanks, this looks good now.

I'd only like to suggest a small improvement: use "getErasure" in "needsDeepMethod", so the deep methods are also used in the presence of type variables, e.g.:

   class X <T, S extends Serializable, N extends Number> {
        T[]ts; // should use deep methods
	S[]ss; // should use deep methods
        N[]ns; // should not use deep methods
    }
Comment 38 Pierre-Yves Bigourdan CLA 2018-08-07 14:08:15 EDT
Thanks for reviewing Till. Good spot on the type variables, this is now covered by a test and should be fixed.

Another minor bug was taken care of, we were importing "java.util.Objects" even if the class only contained arrays. Whilst I was at it I refactored some of the code around the hashCode generation which was responsible for that import.

The CI build seems to have failed, but unless I'm missing something, it isn't related to my latest changes.
Comment 39 Till Brychcy CLA 2018-08-07 15:00:20 EDT
@Dani or @Lars, The Genie says the contribution is more than 1000 lines now and a CQ is needed. Can one of you please manage that?
Comment 40 Till Brychcy CLA 2018-08-07 15:00:40 EDT
(In reply to Pierre-Yves B. from comment #38)
> Thanks for reviewing Till. Good spot on the type variables, this is now
> covered by a test and should be fixed.
> 
> Another minor bug was taken care of, we were importing "java.util.Objects"
> even if the class only contained arrays. Whilst I was at it I refactored
> some of the code around the hashCode generation which was responsible for
> that import.
Thanks.

> 
> The CI build seems to have failed, but unless I'm missing something, it
> isn't related to my latest changes.
Yes, that was bug 537756
Comment 41 Till Brychcy CLA 2018-08-07 17:53:49 EDT
(In reply to Till Brychcy from comment #39)
> @Dani or @Lars, The Genie says the contribution is more than 1000 lines now
> and a CQ is needed. Can one of you please manage that?

(I've replied to the Genie on the Gerrit as requested - not sure what else needs to be done.)
Comment 42 Dani Megert CLA 2018-08-08 03:53:05 EDT
(In reply to Till Brychcy from comment #39)
> @Dani or @Lars, The Genie says the contribution is more than 1000 lines now
> and a CQ is needed. Can one of you please manage that?

The person who looks at the code should also file the CQ. I did not look at the change, but if a bigger part is just code refactoring, you could separate that from the real fix.
Comment 43 Till Brychcy CLA 2018-08-08 03:53:46 EDT
(In reply to Dani Megert from comment #42)
> (In reply to Till Brychcy from comment #39)
> > @Dani or @Lars, The Genie says the contribution is more than 1000 lines now
> > and a CQ is needed. Can one of you please manage that?
> 
> The person who looks at the code should also file the CQ. I did not look at
> the change, but if a bigger part is just code refactoring, you could
> separate that from the real fix.

I cannot, Genie doesn't let me.
Comment 44 Till Brychcy CLA 2018-08-08 03:55:51 EDT
BTW: If creating the CQ is a lot of work, we could either save some lines in the test code (current state is 1015, so 16 lines to be saved) or actually we could split it into two patches: Ivan's unfinished contribution and Pierre-Yves's completion.
Comment 45 Dani Megert CLA 2018-08-08 04:03:36 EDT
(In reply to Till Brychcy from comment #43)
> (In reply to Dani Megert from comment #42)
> > (In reply to Till Brychcy from comment #39)
> > > @Dani or @Lars, The Genie says the contribution is more than 1000 lines now
> > > and a CQ is needed. Can one of you please manage that?
> > 
> > The person who looks at the code should also file the CQ. I did not look at
> > the change, but if a bigger part is just code refactoring, you could
> > separate that from the real fix.
> 
> I cannot, Genie doesn't let me.

You are a committer on JDT, so, that should work. How did you try to create it? What does it say?

Usually you have to go to the project on the portal, e.g.
https://projects.eclipse.org/projects/eclipse.jdt
then click on 'Create a Contribution Questionnai...' (you have to be logged in).
Comment 46 Till Brychcy CLA 2018-08-08 04:12:04 EDT
> Usually you have to go to the project on the portal, e.g.
> https://projects.eclipse.org/projects/eclipse.jdt
> then click on 'Create a Contribution Questionnai...' (you have to be logged
> in).

I tried by replying to the Genie on the Gerrit as it suggested. It says:

> Received CQ creation request but reviewer is not a committer on
> this project. A project committer must comment genie:cq to trigger
> CQ creation.


Probably this didn't get updated when jdt projects were merged?
Comment 47 Till Brychcy CLA 2018-08-08 04:13:26 EDT
Dani, is creating the CQ a lot of work? (I've never done it.)
Do you recomment getting the patch size below 1000 lines instead?
Comment 48 Dani Megert CLA 2018-08-08 04:15:28 EDT
(In reply to Till Brychcy from comment #47)
> Dani, is creating the CQ a lot of work? (I've never done it.)
> Do you recomment getting the patch size below 1000 lines instead?

Not for you, but for the IP team. Also, if I recall correctly, we are already past the CQ deadline for 4.9.
Comment 49 Till Brychcy CLA 2018-08-08 04:19:16 EDT
(In reply to Dani Megert from comment #48)
> (In reply to Till Brychcy from comment #47)
> > Do you recomment getting the patch size below 1000 lines instead?
> 
> Not for you, but for the IP team. Also, if I recall correctly, we are
> already past the CQ deadline for 4.9.

I'm interpreting that as a yes (and I meant for everybody, not only for me).
Comment 50 Pierre-Yves Bigourdan CLA 2018-08-08 04:34:28 EDT
I'll trim down the contribution in the evening. There's some repetition in the tests, we can easily make them slightly slimmer.
Comment 51 Till Brychcy CLA 2018-08-08 04:47:59 EDT
(In reply to Pierre-Yves B. from comment #50)
> I'll trim down the contribution in the evening. There's some repetition in
> the tests, we can easily make them slightly slimmer.

Thanks. There are some changes in the import order that can be avoided and many old tests are changed to have a "false"-parameter added. Maybe you could add just another overload of runOperation that provides that extra false-argument, then the old tests don't have to be changed.
Comment 52 Till Brychcy CLA 2018-08-08 04:57:20 EDT
(In reply to Till Brychcy from comment #46)
> I tried by replying to the Genie on the Gerrit as it suggested. It says:
> [...]

I've created bug 537783 for this.
Comment 53 Pierre-Yves Bigourdan CLA 2018-08-08 13:26:10 EDT
Down to 996 new lines of code, Genie should now be happier!
Comment 55 Till Brychcy CLA 2018-08-08 14:59:05 EDT
(In reply to Eclipse Genie from comment #54)
> Gerrit change https://git.eclipse.org/r/81158 was merged to [master].
> Commit:
> http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/commit/
> ?id=f543cd6d9e9f81013404c079cb4b18cc0601ad44

Released for 4.9M3

One thing remains: Can you please provide an entry for the "New & Noteworthy"-page?

The git repository is git://git.eclipse.org/gitroot/www.eclipse.org/eclipse/news.git and the entry needs to be added to 4.9/jdt.html

Please note instructions.html especially w.r.t. the image width and html validation.
Comment 56 Till Brychcy CLA 2018-08-09 03:41:46 EDT
Note the latest integration build which already contains this can be downloaded from http://download.eclipse.org/eclipse/downloads/
Comment 57 Pierre-Yves Bigourdan CLA 2018-08-09 04:43:36 EDT
Awesome, thanks Till!

I will work on the "New & Noteworthy" entry.
Comment 58 Eclipse Genie CLA 2018-08-09 14:41:50 EDT
New Gerrit change created: https://git.eclipse.org/r/127262
Comment 60 Till Brychcy CLA 2018-08-09 16:44:05 EDT
(In reply to Eclipse Genie from comment #59)
> Gerrit change https://git.eclipse.org/r/127262 was merged to [master].
> Commit:
> http://git.eclipse.org/c/www.eclipse.org/eclipse/news.git/commit/
> ?id=ad8d4511ea2c2e7df23dad14efa7cfb6f6df6f26

I've corrected the placement of the "..." and added a .txt file corresponding to the image. I'm not sure if a new section was really necessary (wouldn't have felt wrong in "Java Views and Dialogs" to me), but I've committed it like this for now.

You can already look at it at https://www.eclipse.org/eclipse/news/4.9/jdt.php#JavaCodeGeneration

Thanks a lot Pierre-Yves and Ivan!
Comment 61 Pierre-Yves Bigourdan CLA 2018-08-09 17:03:28 EDT
Thanks for your quick reviews and feedback Till, this was an interesting piece of work and it will hopefully prove useful to many users!
Comment 62 Kalyan Prasad Tatavarthi CLA 2018-08-21 02:58:22 EDT
Verified by build I20180820-0800
Comment 63 Dani Megert CLA 2018-08-25 10:25:01 EDT
The new label has no mnemonic. Filed bug 538273 to get this fixed.