Community
Participate
Working Groups
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)
Created attachment 203221 [details] screenshot 1
Created attachment 203222 [details] screenshot 2
Created attachment 203223 [details] screenshot 3
Created attachment 203224 [details] screenshot 4
*** Bug 370619 has been marked as a duplicate of this bug. ***
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.
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.
This is a bug in org.eclipse.jdt.internal.ui.packageview.PackageExplorerContentProvider
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 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);
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.
(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.
Created attachment 225553 [details] Patch Updated patch after review comments.
(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 && ...
(In reply to comment #14) Thanks Dani. I will also attach the test class soon.
(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.
Verifying in Build ID : I20130128-2000
This caused a major performance regression (see bug 411636).