Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 263935 - [compare] compare holds on to deleted compilation unit
Summary: [compare] compare holds on to deleted compilation unit
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.5   Edit
Hardware: PC Windows XP
: P2 major (vote)
Target Milestone: 3.5 M6   Edit
Assignee: Tomasz Zarna CLA
QA Contact:
URL:
Whiteboard: hasPatch
Keywords:
Depends on:
Blocks:
 
Reported: 2009-02-06 07:40 EST by David Audel CLA
Modified: 2009-03-11 09:52 EDT (History)
2 users (show)

See Also:


Attachments
Patch v01 (1.66 KB, patch)
2009-02-10 08:39 EST, Tomasz Zarna CLA
no flags Details | Diff
mylyn/context/zip (19.75 KB, application/octet-stream)
2009-02-10 08:39 EST, Tomasz Zarna CLA
no flags Details
Proposal v02 (3.91 KB, patch)
2009-02-24 11:54 EST, Tomasz Zarna CLA
no flags Details | Diff
Patch v03 (3.88 KB, patch)
2009-02-26 11:41 EST, Tomasz Zarna CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description David Audel CLA 2009-02-06 07:40:13 EST
build I20090203-1200

1) checkout org.eclipse.jdt.core
2) add a type org.eclipse.jdt.core.ZZZ.java
3) select org.eclipse.jdt.core and synchronize with the repository
4) from the synchronize view open ZZZ.java in compare editor
5) in the synchronize view select ZZZ.java and do 'Override and Update'
6) do ctrl+shift+T and type ZZZ
ZZZ.java appear
7) try to open ZZZ.java
an error window appear

The deleted type is also still visible in the package explorer

The problem does not occur if i do not open ZZZ.java in compare editor.


The problem is caused by a workingcopy of ZZZ.java which was not discarded.
Comment 1 Dani Megert CLA 2009-02-09 05:38:21 EST
>5) in the synchronize view select ZZZ.java and do 'Override and Update'
>6) do ctrl+shift+T and type ZZZ
How long did you wait between these steps? If the update took some time (or was even blocked due to other jobs) then it is expected that the indexer still finds the type but at the time you open it, you get an exception.
Comment 2 David Audel CLA 2009-02-09 05:47:02 EST
I wait more than 60sec and i do nothing before do ctrl+shift+T.
Comment 3 Dani Megert CLA 2009-02-09 05:50:02 EST
And you did not use that type before i.e. it is not in the Open Type history?
Comment 4 Dani Megert CLA 2009-02-09 05:56:46 EST
Does it work if you simply delete the CU?
Comment 5 David Audel CLA 2009-02-09 06:06:06 EST
I did not use that type before. This type is not in the Open Type history.

It work correctly when i delete the CU from the package explorer.
I reproduce the problem only if i open the type in the compare editor.
Comment 6 Dani Megert CLA 2009-02-09 06:53:37 EST
OK, I see the problem: the compare editor does not react on the deletion of the CU and as a result we have a left-over working copy.

1. compare a CU with a previous state
2. delete the CU
==> CU remains in Package Explorer and can no longer be removed.

Either the compare editor needs to be automatically closed or at least the working copy be disposed.

NOTE: a similar leak will happen once we switch to enhanced text compare.
Comment 7 Dani Megert CLA 2009-02-09 08:18:31 EST
This is 'major' as there's no way except restart to get rid of the dangling working copy.

The wrapped editor would handle the close itself but the problem is that org.eclipse.jdt.internal.ui.compare.JavaMergeViewer.CompilationUnitEditorAdapter.getEditorInput() returns 'null.
Comment 8 Tomasz Zarna CLA 2009-02-10 07:00:50 EST
The JavaMergeViewer.CompilationUnitEditorAdapter.getEditorInput() returns null due to the check in JavaMergeViewer.isInputValid(IEditorInput) which verifies if a file editor input is accessible. When deleting a file, the check fails and returns null. Removing the check reveals another problem: in reaction to file deletion the inner editor does close the compare editor[1] as Dani said, but soon after the TextMergeViewer attempts to respond to the same file deletion by refreshing the viewer(s)[2]. This leads to "widget is disposed" exception.

[1] org.eclipse.ui.texteditor.AbstractTextEditor.close(boolean)
[2] org.eclipse.compare.contentmergeviewer.TextMergeViewer.ContributorInfo.resetDocument(), the checkState() method returns true, the "widget is disposed" exception(s) is thrown a little bit later, ie the editor close[1] happens in the meantime
Comment 9 Tomasz Zarna CLA 2009-02-10 08:39:28 EST
Created attachment 125238 [details]
Patch v01

The patch contains two changes:
* the JavaMergeViewer.isInputValid(IEditorInput) check now returns true even for a deleted file. I haven't observed any harmful side effects so far.
* the first change allow us to close the wrapped editor on a file deletion. However the fix disconnects the editor input from the working copy manager instead of closing the editor.

Comments are welcome.
Comment 10 Tomasz Zarna CLA 2009-02-10 08:39:39 EST
Created attachment 125239 [details]
mylyn/context/zip
Comment 11 Dani Megert CLA 2009-02-24 09:31:51 EST
The fix does not work. Most likely because the fDocumentKey which is used to return the input is set to 'null' in TextMergeViewer.ContributorInfo.disconnect().

If the compare editor wants to stay open then we must avoid to run into the CU editors close() method in order to avoid widgetDisposed errors like you already described in comment 8 and handle the issue either by overriding TextMergeViewer.updateContent(Object, Object, Object) or by opening up TextMergeViewer.disconnect(ContributorInfo) and override it in JTMV.
Comment 12 Tomasz Zarna CLA 2009-02-24 11:54:37 EST
Created attachment 126574 [details]
Proposal v02

The change in ConentMergeViewer prevents "widget is disposed" errors.

For the JavaMergeViewer part I tried make more use of natural life-cycle of CU editor, that's why I didn't followed Dani suggestions from comment 11 and stick to the editor input (removed getEditorInput from CUEA). The fix works pretty good for the case from comment 0, since Compare Editor closes itself here, because there are no diffs when we decide to override and update an outgoing addition (both sides become empty). Closing CE disposes nested CU editors as well so there seems to be no dangling CUs left.

However there is at least one scenario where it doesn't work:

1. Share a project
2. Edit a CU file
3. Sync with HEAD
4. Open Compare Editor for the outgoing change
5. Delete the file from Package Explorer
=> Sometimes NPE is thrown from OperationHistoryActionHandler.java:123, undo won't work after that
6a. Click on the CE
=> NPE(s) will be thrown, missing document provider
6b. Restore the file from repository and open it
=> The change you made in 2 will be there. This worries me the most, did I miss something in my own implementation of close(boolean)?

I guess overridding close(boolean) method is not a bad idea, but the question is what should I put there? Or is this completely wrong?
Comment 13 Markus Keller CLA 2009-02-24 12:27:37 EST
> 5. Delete the file from Package Explorer
> => Sometimes NPE is thrown from OperationHistoryActionHandler.java:123, undo
> won't work after that

That's bug 258679 (but that should only affect the undo stack).
Comment 14 Tomasz Zarna CLA 2009-02-26 11:28:36 EST
> 6b. Restore the file from repository and open it
> => The change you made in 2 will be there.

I've just checked it on 3.4 and 3.5M3 (prior enhanced-Java-compare changes) and it works the same there, so it's not a regression, but still an issue imo => bug 266339.
Comment 15 Tomasz Zarna CLA 2009-02-26 11:41:49 EST
Created attachment 126869 [details]
Patch v03

> 6a. Click on the CE
> => NPE(s) will be thrown, missing document provider

Disposing the document provider was a silly thing to do.
Comment 16 Tomasz Zarna CLA 2009-03-09 11:39:36 EDT
(In reply to comment #12)
> Proposal v02
> The change in ContentMergeViewer prevents "widget is disposed" errors.

This has been addressed in bug 221583.
Comment 17 Dani Megert CLA 2009-03-09 13:31:01 EDT
Committed JDT part to HEAD with one minor change: in close(boolean save) I call
	getDocumentProvider().disconnect(getEditorInput());
Comment 18 Dani Megert CLA 2009-03-11 09:52:21 EDT
Verified in I20090311-0100.