Bug 165434 - [Structure Viewers] Reconcile structure upon document changes
Summary: [Structure Viewers] Reconcile structure upon document changes
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.3   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: 3.5 M7   Edit
Assignee: Tomasz Zarna CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 260865
  Show dependency tree
 
Reported: 2006-11-22 05:36 EST by Dani Megert CLA
Modified: 2009-04-29 06:15 EDT (History)
3 users (show)

See Also:


Attachments
Example code (3.63 KB, patch)
2008-10-06 09:55 EDT, Dani Megert CLA
no flags Details | Diff
Example code (updated) (3.33 KB, patch)
2009-03-31 09:28 EDT, Tomasz Zarna CLA
no flags Details | Diff
Patch v01 (6.55 KB, patch)
2009-04-02 11:21 EDT, Tomasz Zarna CLA
no flags Details | Diff
mylyn/context/zip (743 bytes, application/octet-stream)
2009-04-02 11:21 EDT, Tomasz Zarna CLA
no flags Details
Patch v02 (6.71 KB, patch)
2009-04-03 07:13 EDT, Tomasz Zarna CLA
no flags Details | Diff
Patch v03 (7.34 KB, patch)
2009-04-15 06:17 EDT, Tomasz Zarna CLA
no flags Details | Diff
Improved fix (8.63 KB, patch)
2009-04-17 09:05 EDT, Dani Megert CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dani Megert CLA 2006-11-22 05:36:23 EST
I20061121-1845

I often get confused when using the compare views by the stale information in the structure comparison which only updates on safe. I'd like to have the option that the structure compare updates when the content changes, e.g. when I move a change from right to left or the other way around.
Comment 1 Michael Valenta CLA 2006-11-24 10:42:46 EST
This is something I have been considering but I suspect it is not trivial given the current shape of things. How does it work for the Java Outline view. Is the complete tree regenerated when changes occur or is there a delta mechanism. Do you think it would it be possible to reuse the mechanism in the context of Compare?
Comment 2 Dani Megert CLA 2006-11-24 10:55:05 EST
There is a delta mechanism but most of the time we refresh the whole view. I think as a start to try out it would be good enough to
1. use StandardJavaElementContentProvider as content provider
2. register a delta listener to JavaCore (similar to JavaOutlinePage's 
   ElementChangedListener) which refreshes the view.
Comment 3 Michael Valenta CLA 2006-11-24 11:11:56 EST
Thanks for the pointer. Compare currently uses a different mechanism for the content but it may be possible to just use the JavaCore delta mechanism. Does the JavaCore mechanism fire deltas when there are changes in the file buffer?
Comment 4 Dani Megert CLA 2006-11-27 03:56:39 EST
>Does the JavaCore mechanism fire deltas when there are changes in the file 
>buffer?
Only if there is a reconciler which triggeres ICompilationUnit.reconcile(...) like the Java editor does.
Comment 5 Michael Valenta CLA 2006-12-18 09:22:23 EST
I would like to look into this during M5, if I can find the time.
Comment 6 Michael Valenta CLA 2007-01-22 14:22:13 EST
I've given this some thought and to do this efficiently, we need some mechanism that traces the structure of the content being compared and can recognize when it has changed. Or, to put it another way, we do not want to blindly recalculate the structure every time the content changes. This is especially relevant given that the Java editor is already calculating the structure of a file. Ideally, the same mechanism would be used for both the Java editor and the Compare editor. When a structure change in one side of the comparison was detected, a recalculation of the structure viewer content could be triggered.

Given that there is a delta mechanism involved, I am hesitant to proceed at defining a general mechanism to support auto-reconciling. However, since JDT defines it's own subclass of StructureDiffViewer, it may be possible to implement a JDT specific solution that requires minimal change (and possibly even no change) to Compare.

Given this, I am deferring this feature. However, I am willing to help out on the Compare side if someone from JDT wanted to work on a JDT specific solution.
Comment 7 Dani Megert CLA 2008-10-06 09:55:23 EDT
Created attachment 114308 [details]
Example code

This example code adds a Java element changed listener to the JavaStructureDiffViewer (needs to narrow down the delta but that's easy). This patch reveals two problems:

- the caret/selection can be lost in the merge viewer because the merge viewer also updates once the structure has been updated.
- the compare editor isn't fully made to work off working copies (dirty files). This can be seen just in the beginning when comparing a dirty file with HEAD: it asks to save first.

I guess we could live with this for now. The patch just takes us closer to the final solution.

Markus, what do you think of the patch?
Comment 8 Markus Keller CLA 2008-12-11 12:48:12 EST
Unfortunately, this only works if a Java editor is also open on the edited file. Otherwise, there's no reconciler, and it again only works on save, see comment 4.

And you don't have to asyncExec the call to "contentChanged(null);". The update happens in a background job anyway.
Comment 9 Tomasz Zarna CLA 2009-01-23 03:46:58 EST
Pawel did some work in this area, take a look at bug 261199.
Comment 10 Tomasz Zarna CLA 2009-03-31 09:28:45 EDT
Created attachment 130385 [details]
Example code (updated)
Comment 11 Tomasz Zarna CLA 2009-03-31 11:53:00 EDT
(In reply to comment #8)
> Unfortunately, this only works if a Java editor is also open on the edited file.
> Otherwise, there's no reconciler, and it again only works on save, see comment
> 4.

Markus, please correct me if I'm wrong, but with the introduction of enhanced Java compare (bug 169386) the above statement is no longer valid, which is good news. Am I right? At least, this is the conclusion I came to after applying the updated version of Dani's code.
Comment 12 Markus Keller CLA 2009-03-31 12:53:01 EDT
(In reply to comment #11)
I guess you know that better than me ;-). And if you tried it and it worked without another Java editor, I guess that's all we need.

> And you don't have to asyncExec the call to "contentChanged(null);". The update
> happens in a background job anyway.

This is still an issue in the updated patch.
Comment 13 Tomasz Zarna CLA 2009-04-01 09:03:46 EDT
I've been trying to figure out how to implement the org.eclipse.jdt.internal.ui.compare.JavaStructureDiffViewer.isAffectedBy(ElementChangedEvent) method added by Dani. I have IJavaElement or even IResource retrieved from the delta but I still don't know how should I match it to DiffNodes from the Diff Viewer. If I understood Dani's intention properly, this is required to update content of the viewer only in a response to related ElementChangedEvents.
Comment 14 Dani Megert CLA 2009-04-01 10:39:16 EDT
>If I understood Dani's intention properly, this is required to update
>content of the viewer only in a response to related ElementChangedEvents.
Right, but as Markus said, this only works if a reconciler is installed that triggers the Java model which in return sends out the delta.
Comment 15 Markus Keller CLA 2009-04-02 04:04:50 EDT
(In reply to comment #13)
> I have IJavaElement or even IResource retrieved from the
> delta but I still don't know how should I match it to DiffNodes from the Diff
> Viewer. If I understood Dani's intention properly, this is required to update
> content of the viewer only in a response to related ElementChangedEvents.

To do find out whether the structural diff tree needs to be updated, you would have to implement the diffing a second time (since you never know whether you have to add another node). I think that would be overkill. Just check the delta and refresh the tree when anything has changed in the CU (but not when unrelated elements have changed). See e.g. JavaOutlinePage.ElementChangedListener for how to find out if the delta contains changes in the CU.
Comment 16 Tomasz Zarna CLA 2009-04-02 11:21:09 EDT
Created attachment 130707 [details]
Patch v01

This patch is based on the example code by Dani + some tips from Markus made offline. 

I made two assumptions here:
* decided that a change affects an element if the element from delta equals the one being tested
* instead of just checking if an event affects the viewer I tried to figure out which part/structure of the comparison should be refreshed (changed boolean isAffected to ITypedElement findAffectedElement). 

I'm not sure if this if the later is required though. After little debugging I observed that even when a change to the left side only is made and the left structure is refreshed, an event affecting the right side is fired, which refreshed the right structure as well. Could we get away with passing null to contentChanged without guessing which structure to refresh?
Comment 17 Tomasz Zarna CLA 2009-04-02 11:21:14 EDT
Created attachment 130708 [details]
mylyn/context/zip
Comment 18 Tomasz Zarna CLA 2009-04-03 04:03:48 EDT
(In reply to comment #16)

> * decided that a change affects an element if the element from delta equals the
> one being tested

This works the same way as would returning always true from JavaOutlinePage.ElementChangedListener.isPossibleStructuralChange(IJavaElementDelta) do, if copied to the JavaStructureDiffViewer.
Comment 19 Tomasz Zarna CLA 2009-04-03 06:46:47 EDT
I think I mixed to issues here. Reconciling structure (comment 0) is one thing and outdated node's ranges (bug 260865, comment 5) is a slightly different issue. Fix for this bug *should* contain the isPossibleStructuralChange method as the issue here is about structure only. And it's the fix to bug 260865 that should contain any changes to conditions under which structures (including nodes) have to be refreshed (like in comment 18). 
Comment 20 Tomasz Zarna CLA 2009-04-03 07:13:34 EDT
Created attachment 130820 [details]
Patch v02

See comment 19.
Comment 21 Tomasz Zarna CLA 2009-04-06 10:17:35 EDT
The proposed fix requires changes in JDT/UI not Platform/Compare.
Comment 22 Tomasz Zarna CLA 2009-04-07 07:16:09 EDT
Dani, do you have time to take a look at the updated patch? I've heard you're the editor/reconcile master so I should ping you ;)
Comment 23 Dani Megert CLA 2009-04-14 10:11:20 EDT
Looks not too bad. Three things:

1) it looks like you only refresh one side (the first you find). Shouldn't you
   refresh all matches, e.g. in case where you have changes to the left and the 
   right side in the delta?

2) it has too many find* methods which aren't obvious to distinguish. I would e.g.
   rename findElement to findElementDelta.

3) calling JavaStructureDiffViewer.findElement(IJavaElement, IJavaElementDelta) 
   for read-only elements (e.g. if input comes from history) could be avoided.
Comment 24 Tomasz Zarna CLA 2009-04-15 05:25:36 EDT
(In reply to comment #23)
> 3) calling JavaStructureDiffViewer.findElement(IJavaElement, IJavaElementDelta)
> for read-only elements (e.g. if input comes from history) could be avoided.

True, before calling findElement(IJavaElement, IJavaElementDelta) I could check if the Java element is null and if it's read only. However, findJavaElement(ITypedElement element) returns null for elements that are not IResourceProviders so I guess this covers revisions. Passing null to findElement(IJavaElement, IJavaElementDelta) will result in returning immediately from the method. Nevertheless I could still check if a Java element is read only and if yes, skip calling findElement(IJavaElement, IJavaElementDelta). Would that be ok with you Dani?

btw, I totally agree with two other things you mentioned.
Comment 25 Dani Megert CLA 2009-04-15 05:40:35 EDT
>Would that be ok with you Dani?
Yep. I just want to avoid querying the delta if not needed.
Comment 26 Tomasz Zarna CLA 2009-04-15 06:17:42 EDT
Created attachment 131906 [details]
Patch v03

Patch updated according to comment 23 by Dani.
Comment 27 Dani Megert CLA 2009-04-17 09:05:50 EDT
Created attachment 132233 [details]
Improved fix

The patch is good except for the isReadOnly(...) check.

Tomasz, here's an updated version of it. Please do a final review.
Comment 28 Tomasz Zarna CLA 2009-04-17 09:30:15 EDT
Looks good and works fine. You're the author of the code anyway ;). Thanks for the update.
Comment 29 Dani Megert CLA 2009-04-17 09:36:25 EDT
Committed to HEAD.
Available in builds > N20090416-2000.
Comment 30 Tomasz Zarna CLA 2009-04-17 10:18:29 EDT
Thanks Dani.
Comment 31 Dani Megert CLA 2009-04-29 06:15:40 EDT
Verified in I20090429-0100.