Bug 357450 - Class folder in Java project have refresh problem
Summary: Class folder in Java project have refresh problem
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.8   Edit
Hardware: All All
: P3 major (vote)
Target Milestone: 4.3 M5   Edit
Assignee: Noopur Gupta CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-09-13 04:10 EDT by Yann Andenmatten CLA
Modified: 2014-05-15 02:55 EDT (History)
5 users (show)

See Also:


Attachments
screenshot 1 (136.46 KB, image/png)
2011-09-13 04:10 EDT, Yann Andenmatten CLA
no flags Details
screenshot 2 (137.14 KB, image/png)
2011-09-13 04:13 EDT, Yann Andenmatten CLA
no flags Details
screenshot 3 (125.88 KB, image/png)
2011-09-13 04:13 EDT, Yann Andenmatten CLA
no flags Details
screenshot 4 (137.19 KB, image/png)
2011-09-13 04:14 EDT, Yann Andenmatten CLA
no flags Details
Patch (1.92 KB, patch)
2013-01-10 07:09 EST, Noopur Gupta CLA
daniel_megert: review-
Details | Diff
Patch (1.97 KB, patch)
2013-01-14 04:39 EST, Noopur Gupta CLA
daniel_megert: review+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Yann Andenmatten CLA 2011-09-13 04:10:13 EDT
Build Identifier: 20110615-0604

If you rename a file that is contained in a class folder, the file get renamed but the Package Explorer still shows the old name. Doing a refresh (F5) solve the issue.

Note: this issue also exists in both
Version: Indigo Release Build id: 20110615-0604
Version: Helios Service Release 2 Build id: 20110218-0911

Reproducible: Always

Steps to Reproduce:
1. Create a java project (i.e. test)
2. Create a folder at the root of the project (i.e. classFolder)
3. Edit the Java Build Path
4. In the Libraries tab, click Add Class Folder...
5. Select the folder created in step 2 (i.e. classFolder)
6. In the Package Explorer create a file (i.e. Right click > New > File > test.txt)
7. (BUG) The file is shown in test/Referenced Libararies/classFolder, BUT NOT in test/classFolder. (see screenshot1.png)
8. (WORKAROUND) Do a refresh on the test/classFolder. The file appears. (see screenshot2.png)
9. Rename the file in the test/classFolder. (i.e. Right click > Refactor > Rename...)  (see screenshot3.png)
10. (BUG) The UI doesn't get refreshed. (see screenshot3.png)
11. (WORKAROUND) Do a refresh on the test/classFolder. The file appears. (see screenshot4.png)
Comment 1 Yann Andenmatten CLA 2011-09-13 04:10:59 EDT
Created attachment 203221 [details]
screenshot 1
Comment 2 Yann Andenmatten CLA 2011-09-13 04:13:23 EDT
Created attachment 203222 [details]
screenshot 2
Comment 3 Yann Andenmatten CLA 2011-09-13 04:13:52 EDT
Created attachment 203223 [details]
screenshot 3
Comment 4 Yann Andenmatten CLA 2011-09-13 04:14:11 EDT
Created attachment 203224 [details]
screenshot 4
Comment 5 Ayushman Jain CLA 2012-02-07 00:40:17 EST
*** Bug 370619 has been marked as a duplicate of this bug. ***
Comment 6 Andrew Eisenberg CLA 2012-02-07 18:03:16 EST
I have been looking into Bug 370619, which may or may not be the same cause as this bug.  Initial exploration is showing that org.eclipse.jdt.ui.actions.RefreshAction.WrappedWorkbenchRefreshAction.getSelectedResources() always returns an empty list when an eternal class folder is selected.

The reason for this is that inside the method org.eclipse.ui.actions.SelectionListenerAction.computeResources(), Object resource = ((IAdaptable) next).getAdapter(IResource.class); is called (line 126).  The problem is that an external class folder is of type ExternalPackageFragmentRoot and this will always return null when getAdapter is called with IResource as an argument.  See org.eclipse.jdt.internal.core.Openable.getResource() for why this returns null.

So essentially, calling Refresh on an external class folder or anything contained in it is a no-op.

An ExternalPackageFragmentRoot instance does have a resource field.  I wonder if this could/should be refreshed during a refresh operation.
Comment 7 Andrew Eisenberg CLA 2012-02-07 18:19:23 EST
As I suspected, the bug described here is different from the one I raised in Bug 370619.

Following the instructions, since "classFolder" is not an external resource, in the Java model, it is represented as a PackageFragmentRoot, and therefore when calling getResource() on it, the underlying IFolder is correctly returned.

The problem described in this bug does indeed appear to be a UI bug in the Package Explorer.  When crating/deleting/renamning resources in classFolder in the package explorer, these changes are immediately reflected in the Navigator view.

The problem appears to only occur with the second folder in the package explorer.
Comment 8 Dani Megert CLA 2012-02-08 06:45:21 EST
This is a bug in org.eclipse.jdt.internal.ui.packageview.PackageExplorerContentProvider
Comment 9 Noopur Gupta CLA 2013-01-10 07:09:36 EST
Created attachment 225429 [details]
Patch

The class folder shows up at two places, in library container (Referenced Libraries) and as resource at original location. The issue is that only the library container is refreshed and not the original resource.

The patch checks that if the parent of the delta element is library container then the corresponding original resource of the delta element is also refreshed. This is done when either one of the F_CONTENT or F_CHILDREN flag is set i.e. when either a file or a folder is created/deleted/renamed in the class folder.

However, if the original resource is in a different project, the project containing the resource is already being refreshed. Dani, please let me know if a check has to be added to the current patch to refresh the resource only if the projects containing the library container and resource are same i.e.
	
if (parent instanceof LibraryContainer) {
    IResource resource= element.getResource();
    if (resource != null) {
	IJavaProject resourceProject= JavaCore.create(resource.getProject());
	if (element.getJavaProject().equals(resourceProject)) {
	    postRefresh(resource, ORIGINAL, element, runnables);
	}
    }
}
Comment 10 Dani Megert CLA 2013-01-10 12:12:34 EST
Comment on attachment 225429 [details]
Patch

(In reply to comment #9)
> Created attachment 225429 [details] [diff]
> Patch

The patch is almost good but it now does
    postRefresh(parent, PARENT, element, runnables)
in more cases (not only when the flags describe a content but not children change). I would first
- assign: flags & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_CHILDREN))
- test whether != 1
- inside the 'if',test whether == IJavaElementDelta.F_CONTENT and only then do
  the refresh (as it is in master)


> However, if the original resource is in a different project, the project
> containing the resource is already being refreshed.
Good catch!


> Dani, please let me know
> if a check has to be added to the current patch to refresh the resource only
> if the projects containing the library container and resource are same i.e.
> 	
> if (parent instanceof LibraryContainer) {
>     IResource resource= element.getResource();
>     if (resource != null) {
> 	IJavaProject resourceProject= JavaCore.create(resource.getProject());
> 	if (element.getJavaProject().equals(resourceProject)) {
> 	    postRefresh(resource, ORIGINAL, element, runnables);
> 	}
>     }
> }

Yes, we should add this check, but it can be done simpler:
((LibraryContainer) parent).getJavaProject().getResource().equals(resource);
Comment 11 Dani Megert CLA 2013-01-11 05:34:13 EST
Once done with the patch please also add some tests to
'org.eclipse.jdt.ui.tests.packageview'. I suggest you add 'ContentProviderTests6' and add it to the 'PackageExplorerTests' suite.
Comment 12 Noopur Gupta CLA 2013-01-14 04:35:24 EST
(In reply to comment #10)

> - inside the 'if',test whether == IJavaElementDelta.F_CONTENT and only then
> do
>   the refresh (as it is in master)
 
Refresh for the library container, done by: 
postRefresh(parent, PARENT, element, runnables) 
is also required when the flags describe a children but not content change.
Otherwise, on children change, only the resource will be refreshed and not the library container. Hence, modifying to:
int result= flags & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_CHILDREN);
if (result == IJavaElementDelta.F_CONTENT || result == IJavaElementDelta.F_CHILDREN) {...}

 
> Yes, we should add this check, but it can be done simpler:
> ((LibraryContainer) parent).getJavaProject().getResource().equals(resource);
Thanks. I will update that.
Comment 13 Noopur Gupta CLA 2013-01-14 04:39:27 EST
Created attachment 225553 [details]
Patch

Updated patch after review comments.
Comment 14 Dani Megert CLA 2013-01-14 05:19:44 EST
(In reply to comment #12)
> (In reply to comment #10)
> 
> > - inside the 'if',test whether == IJavaElementDelta.F_CONTENT and only then
> > do
> >   the refresh (as it is in master)
>  
> Refresh for the library container, done by: 
> postRefresh(parent, PARENT, element, runnables) 
> is also required when the flags describe a children but not content change.
> Otherwise, on children change, only the resource will be refreshed and not
> the library container. Hence, modifying to:
> int result= flags & (IJavaElementDelta.F_CONTENT |
> IJavaElementDelta.F_CHILDREN);
> if (result == IJavaElementDelta.F_CONTENT || result ==
> IJavaElementDelta.F_CHILDREN) {...}

Yes, correct. Thanks for the final patch Noopur.

Committed your patch with http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/commit/?id=1843abac02e5aa418cf51d7874e53fef99c1ffc2


In 'master' I converted
  if (resource != null) {
    if (...
to
  if (resource != null && ...
Comment 15 Noopur Gupta CLA 2013-01-14 05:24:38 EST
(In reply to comment #14)

Thanks Dani. I will also attach the test class soon.
Comment 16 Dani Megert CLA 2013-01-14 08:52:42 EST
(In reply to comment #15)
> (In reply to comment #14)
> 
> Thanks Dani. I will also attach the test class soon.

I've created a separate bug report for the tests.
Comment 17 Martin Mathew CLA 2013-01-29 02:30:07 EST
Verifying in Build ID : I20130128-2000
Comment 18 Dani Megert CLA 2013-06-26 06:22:17 EDT
This caused a major performance regression (see bug 411636).