Bug 547052 - [save actions] final is sometimes added when source doesn't compile
Summary: [save actions] final is sometimes added when source doesn't compile
Status: ASSIGNED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.12   Edit
Hardware: PC Linux
: P3 normal with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: JDT-UI-Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords: helpwanted
Depends on:
Blocks:
 
Reported: 2019-05-07 10:55 EDT by Simeon Andreev CLA
Modified: 2023-04-26 21:17 EDT (History)
4 users (show)

See Also:


Attachments
Example project to reproduce the problem with. See reproduction steps in bug description. (3.29 KB, application/zip)
2019-05-07 10:55 EDT, Simeon Andreev CLA
no flags Details
Video showing the problem with the reproduction steps from the bug description. (429.17 KB, video/mp4)
2019-05-07 10:55 EDT, Simeon Andreev CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Simeon Andreev CLA 2019-05-07 10:55:01 EDT
Created attachment 278522 [details]
Example project to reproduce the problem with. See reproduction steps in bug description.

To reproduce:

1. Import project from attached archive "ExampleProject.zip".
2. Open type "somewhere.SomeClass" in a Java editor.
3. Delete line 11 in this source (the closing bracket of method "unfinishedMethod").
4. Save the source file.
5. Observe that member "x" is now final.

See also video "final_variable_save_action_breaks_code.mp4" for the reproduction steps.

I have observed this with various states of uncompiling code, it makes work with this action annoying. I would change some source, save it while it has compile errors and suddenly all members would be final. Once the code I'm adding compiles, the members remain final, so I have to undo what the save action did.

I don't observe this without the unfinished "if (true) {" statement in the snippet:

public class SomeClass {

	private int x = 2;
	

	public void unfinishedMethod() {
		if (true) {
		x = 1;
	}
}


It would be great if the save action which adds "final" triggers only if the source has no compile problems. I don't think the action makes much sense for a source which is incomplete (i.e. code with errors).
Comment 1 Simeon Andreev CLA 2019-05-07 10:55:27 EDT
Created attachment 278523 [details]
Video showing the problem with the reproduction steps from the bug description.
Comment 2 Stephan Herrmann CLA 2019-05-07 11:19:04 EDT
This could possibly be an intrinsic limitation of this particular save action. In the presence of syntax errors, you are at the mercy of syntax recovery, which in the case of unbalanced braces is a lot of guess work.

OTOH, it seems that even in the broken case find references works for 'x', yes?

I don't know off-hand if resolving x is sufficient to detect the write access, or whether flow-analysis is actually involved?
Comment 3 Simeon Andreev CLA 2019-05-07 11:51:43 EDT
> OTOH, it seems that even in the broken case find references works for 'x', yes?

Yes, the reference to x is found before the bracket is removed, while the bracket is removed but the file is not saved, and after the save.
Comment 4 Eclipse Genie CLA 2021-04-28 02:41:02 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 5 Petr Janeček CLA 2021-04-28 03:23:25 EDT
The exact reproduction with `unfinishedMethod()` no longer causes the problem. I have tried a few more complex attempts and could not reproduce this anymore. If anybody has a reproducer that works today, please share.
Comment 6 Eclipse Genie CLA 2023-04-21 09:43:08 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 7 Petr Janeček CLA 2023-04-21 15:10:17 EDT
This is still a thing. The origial repro still works, and some others, too. The following:

```java
public class Playground {

	private int x = 2;

	public void unfinishedMethod() {
		if (true) {
			x = 1;
	

}
```

when saved, adds the `final`. But also this:

```java
public class Playground {

	private int x = 2;

	public void unfinishedMethod() {
		Maknskasjasnhajksn
		x = 1;
	}

}
```

Should we report this to https://github.com/eclipse-jdt/eclipse.jdt.core/, somewhere else, or is this place still OK for reports?
Comment 8 Simeon Andreev CLA 2023-04-21 15:17:11 EDT
It will have to be reported at the GitHub JDT repos, yes. I'm not sure if it should be reported at core or UI though.
Comment 9 Jeff Johnston CLA 2023-04-26 21:17:10 EDT
(In reply to Petr Janeček from comment #7)
> This is still a thing. The origial repro still works, and some others, too.
> The following:
> 
> ```java
> public class Playground {
> 
> 	private int x = 2;
> 
> 	public void unfinishedMethod() {
> 		if (true) {
> 			x = 1;
> 	
> 
> }
> ```
> 
> when saved, adds the `final`. But also this:
> 
> ```java
> public class Playground {
> 
> 	private int x = 2;
> 
> 	public void unfinishedMethod() {
> 		Maknskasjasnhajksn
> 		x = 1;
> 	}
> 
> }
> ```
> 
> Should we report this to https://github.com/eclipse-jdt/eclipse.jdt.core/,
> somewhere else, or is this place still OK for reports?

I am only able to reproduce this by setting Java -> Editor -> Save Actions and to have Additional Actions specified and selecting Code Style -> Variable Declarations "Use modifier final where possible" and "Private fields" selected.

Now, the reason this doesn't kick in when the file is complete is that the field cannot be made final knowing that x is reassigned.  With the code error, the cleanup is likely not able to find the "x = 1" assignment or confirm the binding of x to the private field.  Without discovering the conflict, it is performing the save action requested and making the field final.