Bug 275805 - creating a non-primary working copy causes typeHierarchyChanged event
Summary: creating a non-primary working copy causes typeHierarchyChanged event
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.4.2   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 3.6 M4   Edit
Assignee: Satyam Kandula CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-05-12 03:19 EDT by Stuart CLA
Modified: 2009-12-08 04:41 EST (History)
7 users (show)

See Also:
Olivier_Thomann: review+


Attachments
workbench screenshot (98.17 KB, image/png)
2009-05-12 19:11 EDT, Stuart CLA
no flags Details
Simple plugin that reproduces the problem reported in this bug (2.06 KB, application/x-gzip)
2009-06-04 13:19 EDT, Miguel Mendez CLA
no flags Details
Sample project to use in repro steps (563 bytes, application/x-gzip)
2009-06-15 11:10 EDT, Miguel Mendez CLA
no flags Details
Proposed Patch (2.99 KB, patch)
2009-09-14 06:17 EDT, Satyam Kandula CLA
daniel_megert: review-
Details | Diff
Proposed patch (4.59 KB, patch)
2009-09-29 06:00 EDT, Satyam Kandula CLA
Olivier_Thomann: iplog+
Olivier_Thomann: review+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Stuart CLA 2009-05-12 03:19:07 EDT
Build ID: M20090211-1700

Steps To Reproduce:
1. Open some class/interface in the Hierarchy view (F4).
2. Open a descendant/implementor of that class/interface in an editor window. (It does not matter whether the descendant is opened from the Hierarchy view.)
3. Invoke content assist by typing [.] or [ctrl+space]

Expected behaviour: Content assist appears as normal.
Actual behaviour: Content assist appears briefly, but then disappears.

More information:
It is still possible to select the first content assist result if you hit [enter] quickly enough.

The incorrect behaviour ends when the Hierarchy view is hidden, closed, or set to some type unrelated to the open file, or when editing an unrelated file.

The incorrect behaviour sometimes appears when the current file's type is the one whose hierarchy is shown, but this is less consistent.
Comment 1 Dani Megert CLA 2009-05-12 03:56:08 EDT
I cannot reproduce this using Eclipse SDK 3.4.2:
http://download.eclipse.org/eclipse/downloads/drops/R-3.4.2-200902111700/index.php
Can you attach a step-by-step test case using above build?

If not, please try to figure out which additional plug-in might cause this.

Does code assist work if the Hierarchy view is closed?
Please attach a picture of your workbench.
Comment 2 Markus Keller CLA 2009-05-12 04:32:35 EDT
Could also be a "focus follows mouse" problem (e.g. bug 59639).
Comment 3 Stuart CLA 2009-05-12 19:11:57 EDT
Created attachment 135477 [details]
workbench screenshot
Comment 4 Stuart CLA 2009-05-12 19:20:27 EDT
I have managed to reproduce this in a clean workspace/project. Exact steps:

1. Create a new Java Project
2. Create a new interface
3. Create a new class that implements that interface
4. Open the class for editing
5. Select the name of the interface in the editor window and hit [F4] to bring up its hierarchy
6. Place the cursor in the body of the class source file and hit [ctrl+space]

I am using "java-6-sun-1.6.0.13", running on Ubuntu 9.04 (though I can also reproduce on 8.10).

This bug does not appear to be related to focus-follows-mouse, because it occurs regardless of where my mouse is located (even if over another app).

I am using the Java EE bundled download (Linux 32-bit); the only other plug-ins I have installed are "Google Plugin for Eclipse 3.4" and "Google Web Toolkit SDK 1.6.4".

Content assist works fine if the Hierarchy view is closed, or if its tab is not in the foreground. It also works fine if the type selected in the type whose hierarchy is displayed is unrelated to the type currently being edited.

If the types are related, content assist remains broken even when the Hierarchy view is set to "Show the Supertype Hierarchy" and the currently-edited type is therefore not shown in the Hierarchy view.
Comment 5 Stuart CLA 2009-05-12 19:29:16 EDT
I just tried reproducing the bug myself on http://download.eclipse.org/eclipse/downloads/drops/R-3.4.2-200902111700/index.php without success. I will try installing plugins and see where that gets me.
Comment 6 Stuart CLA 2009-05-12 19:40:16 EDT
OK, the problem reappears when I install "Google Web Toolkit SDK 1.6.4" from http://dl.google.com/eclipse/plugin/3.4 , which presumably makes it a plugin bug.
Comment 7 Stuart CLA 2009-05-12 19:47:21 EDT
Cross-reported at http://code.google.com/p/google-web-toolkit/issues/detail?id=3650 .
Comment 8 Dani Megert CLA 2009-05-13 02:47:22 EDT
Thanks for your investigation.
Comment 9 Miguel Mendez CLA 2009-05-22 16:08:12 EDT
We've looked at this on the Google Plugin for Eclipse side.  The following code below reproduces the problem reported.  If we remove the call to getWorkingCopy in the snippet below the problem goes away.  Can anyone shed some light on what is going on?  Is it not legal to get a working copy from a completion proposal computer?

  public List computeCompletionProposals(
      ContentAssistInvocationContext context, IProgressMonitor monitor) {
    if (!(context instanceof JavaContentAssistInvocationContext)) {
      // Not in a java content assist content
      return NO_PROPOSALS;
    }

    try {
      JavaContentAssistInvocationContext jcaic = (JavaContentAssistInvocationContext) context;
      ICompilationUnit compilationUnit = jcaic.getCompilationUnit().getWorkingCopy(
          monitor);
    } catch (JavaModelException e) {
      // Ignored 
    }
    return NO_PROPOSALS;
  }
Comment 10 Dani Megert CLA 2009-05-25 04:54:49 EDT
> Is it not legal to get a working copy from a completion proposal computer?
It's legal. Are you sure you want to create a non-shared working copy instead of just working with the current compilation unit?

>Can anyone shed some light on what is going on? 
Not sure. The call triggers a Java model delta which could be cause for the problem we see. Could you attach a small test plug-in that allows us to see/reproduce the problem?
Comment 11 Miguel Mendez CLA 2009-06-04 13:19:13 EDT
Created attachment 138315 [details]
Simple plugin that reproduces the problem reported in this bug

I've attached a simple plugin that reproduces the problem.  The reason for asking for a working copy is that the the compilation unit received by the completion proposal computer is not always as up-to-date as the editor's content.  Asking for a working copy guarantees that we get an ICompilationUnit that shows the latest changes.
Comment 12 Miguel Mendez CLA 2009-06-11 11:08:16 EDT
BTW, I don't think that this is resolved given that there is a trivial stand-alone plugin can reproduce the problem.
Comment 13 Dani Megert CLA 2009-06-12 02:11:52 EDT
Yes, I plan to look at the example soon. Note however, that content assist should not reconcile as this is an expensive operation. Also JDT does not do this for exactly that reason.
Comment 14 Markus Keller CLA 2009-06-12 05:02:24 EDT
.
Comment 15 Dani Megert CLA 2009-06-15 09:20:25 EDT
Miguel, maybe I am missing some steps but using 3.5 RC4 SDK:
http://download.eclipse.org/eclipse/downloads/drops/S-3.5RC4-200906051444/index.php
+ your plug-in I am not able to reproduce the problem.

Can you please provide the steps (based on 3.5 RC4) that allow you to see the problem? Thanks.
Comment 16 Miguel Mendez CLA 2009-06-15 11:10:28 EDT
Created attachment 139179 [details]
Sample project to use in repro steps
Comment 17 Miguel Mendez CLA 2009-06-15 11:14:46 EDT
I was able to reproduce the problem on Mac OS X 10.5.7, using eclipse-SDK-3.5RC4-macosx-cocoa.tar.gz.  Here's the version information reported by that eclipse version:

Eclipse SDK

Version: 3.5.0
Build id: I20090605-1444
Comment 18 Dani Megert CLA 2009-06-15 11:18:37 EDT
Originally this bug was reported against Linux and I cannot reproduce there or on my WindowsXP box. Are you 100% sure you have plain Eclipse SDK, no Mylyn, no J2EE etc?
Comment 19 Miguel Mendez CLA 2009-06-15 11:39:12 EDT
I was just able to reproduce the problem on my Windows XP SP2 box.  I used the standard eclipse SDK 3.5 RC4 from http://download.eclipse.org/eclipse/downloads/drops/S-3.5RC4-200906051444/index.php.

To reproduce the problem:
1) Download the eclipse for OSX or Windows from http://download.eclipse.org/eclipse/downloads/drops/S-3.5RC4-200906051444/index.php and expand 
it.  (All tests are done against this version without adding any plugins.)

2) Launch the newly expanded eclipse install.

3) Expand the attached sample plugin that demonstrates the problem.

4) Import the plugin in to a clean workspace.

5) Expand the Foo sample project attached.

6) Right click on the plugin project imported in step 4 and select Debug As > Eclipse Application.

7) In the debug workspace, import he sample project from step 5.

8) Using the package explorer, select IFoo and hit F4.

9) Double click on the CFoo subtype in the resulting hierarchy view to edit the class.

10) In the body of the CFoo class, type CTRL+SPACE to trigger the completion proposals.

Expected Results:
The list of completions proposal appears in the editor.

Actual Results:
The completion proposals appear, but are immediately dismissed before a user can act on them.

It is important to point out that this only happens when the hierarchy view is active.

(In reply to comment #18)
> Originally this bug was reported against Linux and I cannot reproduce there or
> on my WindowsXP box. Are you 100% sure you have plain Eclipse SDK, no Mylyn, no
> J2EE etc?
> 

Comment 20 Dani Megert CLA 2009-06-15 11:50:50 EDT
Can reproduce now.
Comment 21 Miguel Mendez CLA 2009-06-15 11:55:45 EDT
(In reply to comment #20)
> Can reproduce now.
> 

Good to know.  Let us know if there is anything that we can do to help.
Comment 22 Dani Megert CLA 2009-06-16 03:56:16 EDT
There are several issues here:
1) Creating a non-primary working copy instead of just reconciling the CU using:
	cu.reconcile(
		ICompilationUnit.NO_AST,
		false /* don't force problem detection */,
		null /* use primary owner */,
		null /* no progress monitor */);
   ==> if you change your code that way, it will work for you.

2) Creating a new non-primary working is interpreted by JDT Core as
   a type hierarchy change, which I think is wrong: it should ignore deltas from
   working copies with different owner than the current type hierarchy has. Code
   is in TypeHierarchy.isAffectedByOpenable(IJavaElementDelta, IJavaElement, int).

3) The type hierarchy UI is not updated in the background, changing this would 
   also fix this bug, see bug 30881 for details.

4) Because the type hierarchy is not updated in the background it uses the
   workbench as the progress monitor. This causes the focus to be shifted to the
   progress status bar item while the operation is running - which of course
   closes the completion proposal pop-up. This behavior will not change, see
   bug 73422 and bug 167675.


Moving to JDT Core to investigate 2).
Comment 23 Olivier Thomann CLA 2009-06-16 10:14:31 EDT
Srikanth, please investigate.
Comment 24 Miguel Mendez CLA 2009-06-17 13:28:18 EDT
Thanks, your suggestion to use resolve does avoid the type hierarchy problem.

(In reply to comment #22)
> There are several issues here:
> 1) Creating a non-primary working copy instead of just reconciling the CU
> using:
>         cu.reconcile(
>                 ICompilationUnit.NO_AST,
>                 false /* don't force problem detection */,
>                 null /* use primary owner */,
>                 null /* no progress monitor */);
>    ==> if you change your code that way, it will work for you.
> 
> 2) Creating a new non-primary working is interpreted by JDT Core as
>    a type hierarchy change, which I think is wrong: it should ignore deltas
> from
>    working copies with different owner than the current type hierarchy has.
> Code
>    is in TypeHierarchy.isAffectedByOpenable(IJavaElementDelta, IJavaElement,
> int).
> 
> 3) The type hierarchy UI is not updated in the background, changing this would 
>    also fix this bug, see bug 30881 for details.
> 
> 4) Because the type hierarchy is not updated in the background it uses the
>    workbench as the progress monitor. This causes the focus to be shifted to
> the
>    progress status bar item while the operation is running - which of course
>    closes the completion proposal pop-up. This behavior will not change, see
>    bug 73422 and bug 167675.
> 
> 
> Moving to JDT Core to investigate 2).
> 

Comment 25 Srikanth Sankaran CLA 2009-08-25 02:59:56 EDT
Satyam, thanks for investigating this.
Comment 26 Satyam Kandula CLA 2009-09-14 06:17:44 EDT
Created attachment 147090 [details]
Proposed Patch

Olivier,
Can you review this patch? 

Creating the working copy should generate a delta but that delta should not create an hierarchy change event. Hence, in the fix I tried to stop the "ADDED" event arising from a non-primary CU. 
However, there are still some open questions:
1. Should the working copy owners  be compared before getting the event triggered?
2. Currently that piece of code doesn't seem to compare the working copy owners for triggering that events -- Is it that we shouldn't be bothered about the owners?
Comment 27 Olivier Thomann CLA 2009-09-14 12:07:48 EDT
Hi,

I don't know that code well enough to validate the change.
Some observations:
1) If the new working copy has a different owner than the one from the current type inside the type hierarchy, no refresh should occur.
But if the owner is the same, I would say that a refresh should occur, otherwise the new working copy is not visible in the type hierarchy.
2) If the current hierarchy has no working owner, creating a new working copy with no working copy owner should trigger a refresh. If the new working copy has a working copy owner, then no refresh should occur.

Daniel, does this look reasonable ?
Comment 28 Olivier Thomann CLA 2009-09-14 13:25:52 EDT
Talking with Jérôme, it appears that a working copy creation should not trigger a refresh.
So the patch seems good enough.
Daniel, do you see a case where the current patch might be a problem ?
Comment 29 Dani Megert CLA 2009-09-17 09:33:07 EDT
The patch is not good as it no longer handles the addition of types for type hierarchies built on top of non-primary CUs. It also doesn't implement Jérôme's suggestion ("working copy creation should not trigger a refresh.") correctly as working copy creation off a primary CU is still handled by the code.

I would suggest a fix along these lines (same place as other code):

	ICompilationUnit focusCU =
	    this.focusType != null ? this.focusType.getCompilationUnit() : null;
	if (focusCU != null && focusCU.getOwner() != cu.getOwner())
		return false;

In addition we could also return in case we get an IJavaElementDelta.F_PRIMARY_WORKING_COPY delta.


Jérôme, what do you think?
Comment 30 Olivier Thomann CLA 2009-09-18 11:07:02 EDT
Satyam, please rework on the patch wrt the last comment from Daniel.
Jérôme, your comment would be welcome.
Comment 31 Satyam Kandula CLA 2009-09-23 03:23:06 EDT
Daniel,
I have tried without luck trying to get a case where we could get an IJavaElementDelta.ADDED delta on a non-primary cu apart from the getWorkingCopy() or reconcile(). I haven't explored the complete case of reconcile. 
However, can you let me know if you know of any testcase where we could run into the case you had mentioned.
Comment 32 Dani Megert CLA 2009-09-23 03:28:47 EDT
Simply create a non-primary CU and add another type to it.
Comment 33 Satyam Kandula CLA 2009-09-23 07:47:14 EDT
Did you mean either of this two?

1. Create a working copy using WorkingCopyOwner#newWorkingCopy and then set the contents accordingly -- Hierarchy doesn't seem to work for External Projects and hence it won't come here. 
 
2. Create an inner class 
#######
aWorkingCopy = getCompilationUnit("P/p/X.java").getWorkingCopy(superCopy.getOwner(), null);
IType type= aWorkingCopy.getType("X");
type.createType("class innerClass implements IX{}", null, true, null);
########
This is not creating an ADDED for a compilation unit. 

If it is not either of these two, can you please elaborate?
Comment 34 Satyam Kandula CLA 2009-09-23 08:08:39 EDT
Even the following code snippet is generating a CHANGE delta 
#########	

IPackageFragment pkg = getPackageFragment("P", "", "p");
CompilationUnit result = new CompilationUnit((PackageFragment) pkg, "X.java", superCopy.getOwner());
result.getWorkingCopy(superCopy.getOwner(), null).getBuffer().setContents(
			"package p;\n" +
			"public class X implements IX{\n" +
			"}"
		);
############
Comment 35 Satyam Kandula CLA 2009-09-23 08:25:10 EDT
I could reproduce the test case you are mentioning. Sorry for the confusion.
Comment 36 Satyam Kandula CLA 2009-09-23 09:34:40 EDT
Dani, 
I think you mean the test case in the lines as follows -- Please correct if it is not. 
If the test case is correct, I believe the becomeWorkingCopy() should NOT fire the event and the commitWorkingCopy() should fire the event and in this case, the event is getting fired on the primary CU.
################
public void testNonPrimaryCU() throws CoreException {
	ITypeHierarchy h = null;
	ICompilationUnit superCopy = null;
	ICompilationUnit cu = null;
	
	try 
	{
		createJavaProject("P");
		createFolder("/P/p");
		createFile(
			"/P/p/IX.java",
			"package p;\n" +
			"public interface IX {\n" +
			"}"
		);		
		
		WorkingCopyOwner owner = getWorkingCopyOwner(
				new String ("X.java"),
				new String ("public class X implements IX {}")
			);
		superCopy = getCompilationUnit("/P/p/IX.java").getWorkingCopy(owner, null);
	
		h = superCopy.getType("IX").newTypeHierarchy(null);		
		h.addTypeHierarchyChangedListener(this);
	
		IPackageFragment pkg = getPackageFragment("P", "", "p");
		cu = new CompilationUnit((PackageFragment) pkg, "X.java", owner);
		cu.becomeWorkingCopy(null); 
		assertTrue("Should NOT receive change", !this.changeReceived);
		
		//cu.reconcile(ICompilationUnit.NO_AST, false, owner, null);
		cu.commitWorkingCopy(false/*don't force*/, null/*no progress*/);
		assertTrue("Should receive change", this.changeReceived);
	} finally {
		if (h != null)
			h.removeTypeHierarchyChangedListener(this);
		if (cu != null)
			cu.discardWorkingCopy();
		if (superCopy != null)
			superCopy.discardWorkingCopy();
		deleteProject("P");
	}
}
	

protected WorkingCopyOwner getWorkingCopyOwner(final String name, final String contents) throws JavaModelException {
	WorkingCopyOwner owner = new WorkingCopyOwner() {
		public IBuffer createBuffer(ICompilationUnit wc) {
			IBuffer buffer = super.createBuffer(wc);
			if (!wc.getElementName().equals("X.java"))
				return buffer;
			buffer.setContents(contents);
			return buffer;
		}
	};
	return owner;
}
#############
Comment 37 Dani Megert CLA 2009-09-23 09:46:32 EDT
Sorry I don't have time to dig through that code right now.

Another point is that your patch swallows other ADD events for non-primary working copies of the same owner.

I hope you're not suggesting to touch becomeWorkingCopy() and/or commitWorkingCopy().
Comment 38 Jerome Lanneluc CLA 2009-09-24 07:32:50 EDT
(In reply to comment #29)
> The patch is not good as it no longer handles the addition of types for type
> hierarchies built on top of non-primary CUs. It also doesn't implement Jérôme's
> suggestion ("working copy creation should not trigger a refresh.") correctly as
> working copy creation off a primary CU is still handled by the code.
> 
> I would suggest a fix along these lines (same place as other code):
> 
>     ICompilationUnit focusCU =
>         this.focusType != null ? this.focusType.getCompilationUnit() : null;
>     if (focusCU != null && focusCU.getOwner() != cu.getOwner())
>         return false;
> 
> In addition we could also return in case we get an
> IJavaElementDelta.F_PRIMARY_WORKING_COPY delta.
> 
> 
> Jérôme, what do you think?

This makes perfect sense to me.
Comment 39 Satyam Kandula CLA 2009-09-29 06:00:09 EDT
Created attachment 148309 [details]
Proposed patch

This patch has the following
1. Ignore the event if the owners are different as mentioned by Dani
2. Ignore the ADDED deltas from non-primary CU's. Also put an additional check to make sure that we don't ignore if they are added at the time of reconcile.
3. Added two tests to confirm the both. 
4. For primary CU's we receive the CHANGE delta which is handled cleanly in the subsequent functions. Hence, didn't put any additional check for IJavaElementDelta.F_PRIMARY_WORKING_COPY.
Comment 40 Olivier Thomann CLA 2009-10-20 12:36:35 EDT
I could reproduce the problem from comment 19 without the patch and it worked fine with the patch.
So as far as I can tell, this patch looks reasonable.
All existing model tests passed.
I would release it post M3 so that we have more time to test it.
Daniel, ok for you ?
Comment 41 Dani Megert CLA 2009-10-21 02:55:04 EDT
>I would release it post M3 so that we have more time to test it.
>Daniel, ok for you ?
Yep.
Comment 42 Olivier Thomann CLA 2009-11-03 10:17:38 EST
Released for 3.6M4.
Regression tests added in:
org.eclipse.jdt.core.tests.model.TypeHierarchyNotificationTests#testGetWorkingCopy
org.eclipse.jdt.core.tests.model.TypeHierarchyNotificationTests#testOwner

Thanks, Satyam.
Comment 43 Jay Arthanareeswaran CLA 2009-12-08 04:34:13 EST
Verified for 3.6M4 using build I20091207-1800