Community
Participate
Working Groups
Build Identifier: 20110916-0149 I'm a bndtools developer. I'm using bndtools https://github.com/njbartlett/bndtools, b49ff4f611f40e39e71f4f5becf3193b115e885d. I've replaced bndtools.core/src/bndtools/refactor/PkgRenameParticipant.java with the attached version of the file. I run this setup of a chackout of https://github.com/fhuberts/jnotify, 62dc918cef67b703a8f58e2cbf16e7888abd3c84. I now rename a package, and ask for a preview. The preview shows the correct changes but the endresult is not correct. I've attached screenshots of the rename procedure, the bnd.bnd file (before the rename) and the bnd.bnd.new file (after the rename) clearly the bnd.bnd.new file does not correspond to the preview. Since my code is not involved after the preview I've concluded that this must be an eclipse bug. Reproducible: Always Steps to Reproduce: 1. see details 2. 3.
Created attachment 205272 [details] the java code generating the changes
Created attachment 205273 [details] package rename, step 1
Created attachment 205274 [details] package rename, step 2
Created attachment 205275 [details] package rename, step 3
Created attachment 205276 [details] package rename, step 4
Created attachment 205277 [details] package rename, step 5
Created attachment 205278 [details] package rename, step 6
Created attachment 205279 [details] bnd.bnd file before rename
Created attachment 205280 [details] bnd.bnd file after rename (corrupted)
> Since my code is not involved after the preview I've concluded that this must > be an eclipse bug. Not sure, as it obviously only happens with your participant. Markus, please take a look.
My system: Fedora 15 x86_64 openjdk 1.6.0.0-59.1.10.3.fc15 Neil Bartlett just indicated that he could not reproduce this bug on Mac OS X Lion. we're currently testing some other platform combinations
Neil probably has the "[x] Rename subpackages" option disabled. I didn't debug it, but I guess the problem is that your RenameParticipant is called multiple times (for each subpackage). Each time, you create a new TextFileChange that targets the same .bnd files. You create your ReplaceEdits based on the original version, which is why it looks correct in the preview. But after the first change has been executed, the content of the file has changed and the other changes are not valid any more. One possible fix is to use RefactoringParticipant#getTextChange(Object) to get an existing TextChange. Then, you can add your edits to that Change.
(In reply to comment #12) > Neil probably has the "[x] Rename subpackages" option disabled. > > I didn't debug it, but I guess the problem is that your RenameParticipant is > called multiple times (for each subpackage). Each time, you create a new > TextFileChange that targets the same .bnd files. You create your ReplaceEdits > based on the original version, which is why it looks correct in the preview. > But after the first change has been executed, the content of the file has > changed and the other changes are not valid any more. > > One possible fix is to use RefactoringParticipant#getTextChange(Object) to get > an existing TextChange. Then, you can add your edits to that Change. Win XP with latest jdk6 (b27) shows the same problem. Will try your hint, but how to go about that? My participant is not reused but a new instance is used every time and I _really_ hate statics
> Will try your hint, but how to go about that? My participant is not reused but > a new instance is used every time and I _really_ hate statics That's the beauty of RefactoringParticipant#getTextChange(Object). The implementation talks to the refactoring processor, and that one knows all changes. See also the Javadoc of RefactoringParticipant#createChange(..). If you wanted to have a shared participant, you can also implement ISharableParticipant. So, you can keep your statics aversion for something else ;-)
Created attachment 205644 [details] the new (working) rename code (In reply to comment #14) > > Will try your hint, but how to go about that? My participant is not reused but > > a new instance is used every time and I _really_ hate statics > > That's the beauty of RefactoringParticipant#getTextChange(Object). The > implementation talks to the refactoring processor, and that one knows all > changes. See also the Javadoc of RefactoringParticipant#createChange(..). Thanks for your help, it works! I have one issue left though: The rename only runs in the project in which the package rename is done, while the package is referenced in bnd files in other projects. How should we make Eclipse run the rename on these projects too? (attached the new source file)
(In reply to comment #15) > The rename only runs in the project in which the package rename is done, while > the package is referenced in bnd files in other projects. > How should we make Eclipse run the rename on these projects too? The Java rename processor finds references in dependent projects as well. Maybe your code should do the same? You are choosing your scope here: pkgFragment.getResource().getProject().accept(visitor, IContainer.NONE);
(In reply to comment #16) > (In reply to comment #15) > > The rename only runs in the project in which the package rename is done, while > > the package is referenced in bnd files in other projects. > > How should we make Eclipse run the rename on these projects too? > > The Java rename processor finds references in dependent projects as well. Maybe > your code should do the same? You are choosing your scope here: > > pkgFragment.getResource().getProject().accept(visitor, IContainer.NONE); cool. many many thanks for the tips! I did: - pkgFragment.getResource().getProject().accept(visitor, IContainer.NONE); + + Set<IProject> visitedProjects = new HashSet<IProject>(); + + IProject containingProject = pkgFragment.getResource().getProject(); + containingProject.accept(visitor, IContainer.NONE); + visitedProjects.add(containingProject); + + for (IProject project : pkgFragment.getResource().getProject().getReferencingProjects()) { + project.accept(visitor, IContainer.NONE); + visitedProjects.add(project); + } + + for (IProject project : pkgFragment.getResource().getProject().getReferencedProjects()) { + if (!visitedProjects.contains(project)) { + project.accept(visitor, IContainer.NONE); + visitedProjects.add(project); + } + }