Community
Participate
Working Groups
Version: 3.2.0 RC2 Build id: I20060428-1315 Given are the following example classes: ClassA.java: public class ClassA { static ClassB instanceOfClassB; } ClassB.java: public class ClassB { static ClassC instanceOfClassC; } ClassC.java: public class ClassC { static ClassD instanceOfClassD; } ClassD.java: public class ClassD { } Example.java: import java.io.*; public class Example { private void testFunction() { ClassA.instanceOfClassB.instanceOfClassC.instanceOfClassD.toString(); } } A 'clean up' of Example.java with 'change all acces through instances' and 'remove unused imports' checked lead's to ClassBClassA.instanceOfClassC.instanceOfClassD.toString(); which renders the code unusable. It should at least lead to ClassB.instanceOfClassC.instanceOfClassD.toString(); or to ClassD.toString(); Best regards Thomas Boeck
Created attachment 40585 [details] Sources leading to the error Sources leading to the error
Move to JDT/UI
Benno, can you investigate?
Created attachment 40921 [details] test case A yet failing test case for CleanUpTest
In short, it looks like that I get a DeleteEdit from the ASTRewrite deleting "ClassA.B" the problem is that this edit has childrens: An insert Edit inserting "ClassA". When mergin two edit trees (as in this case) I'm flattening the trees and the insert edit "ClassA" is moved to the top and has an effect. Spec: 'A delete edit is equivalent to ReplaceEdit(offset, length, "").' So, it should IMHO not contain the insert edit it does. The fix on my side is easy and low risk as long as having childrens in DeleteEdits never makes sense, I will attach a patch. But this seams to be an ASTRewrite bug. I can't tell how often this occures (not very often I guess or it was introduced shortly). Martin, can you have a look at it?
Created attachment 40922 [details] fix in clean up refac
More investigation: Due to Bug 141504 first 'ClassA' is replaced by 'ClassA' with ASTRewrite#replace(SimpleName, SimpleType, TextEditGroup) then on the same ASTRewrite 'ClassA.B' is replaced by 'ClassB' with ASTRewrite#replace(QualifiedName, SimpleType, TextEditGroup) Resulting in replaced: 'ClassA.B' -> 'ClassB' and replaced: 'ClassA' -> 'ClassA' The second replace is a child of the generated DeleteEdit for 'ClassA.B'. This delete edit is generated in org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doTextRemoveAndVisit(int, int, ASTNode, TextEditGroup) where also the call to visit the child node is located. I don't know why the child is visited, maybe we have some optimization possibilities here. But I woulden't wanna touch this for 3.2, there is a better fix...
Another bug is described here: The result should be ClassD.D.toString(); after running the clean up and all previous qualifiers should be removed. Fixing this bug also fixes the ClassBClassA problem.
Ok, let me summarize: Given: import java.io.*; public class E1 { static class ClassA {static ClassB B;} static class ClassB {static ClassC C;} static class ClassC {static ClassD D;} static class ClassD {} public void foo() { ClassA.B.C.D.toString(); } } 1. Source->Clean Up 2. Change all accesses to static through instances 3. Remove unused imports 4. Finish Is: ClassBClassA.C.D.toString(); Should: ClassC.D.toString();
Created attachment 41297 [details] fix After applying this patch the generated result is: ClassB.C.D.toString(); this due to bug 141504
As the scenario is a corner case, I suggest to fix this in 3.2.1.
Created attachment 45660 [details] fix and test
fixed with patch id=45660 > I20060628-1135 for 3.3M1
fixed > I20060628-1135
verified in 20060910-0010
Reopen to fix in 3.2.1
Created attachment 47834 [details] fix and test for 3.2.1
fixed > M20060810-0800 for 3.2.1
verified in 20060830-0800