KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > fix > CodeStyleFix


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.fix;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Hashtable JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.text.edits.TextEditGroup;
19
20 import org.eclipse.core.runtime.CoreException;
21
22 import org.eclipse.jdt.core.IJavaElement;
23 import org.eclipse.jdt.core.IType;
24 import org.eclipse.jdt.core.compiler.IProblem;
25 import org.eclipse.jdt.core.dom.ASTNode;
26 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
27 import org.eclipse.jdt.core.dom.Assignment;
28 import org.eclipse.jdt.core.dom.CompilationUnit;
29 import org.eclipse.jdt.core.dom.Expression;
30 import org.eclipse.jdt.core.dom.FieldAccess;
31 import org.eclipse.jdt.core.dom.IBinding;
32 import org.eclipse.jdt.core.dom.IMethodBinding;
33 import org.eclipse.jdt.core.dom.ITypeBinding;
34 import org.eclipse.jdt.core.dom.IVariableBinding;
35 import org.eclipse.jdt.core.dom.Initializer;
36 import org.eclipse.jdt.core.dom.MethodInvocation;
37 import org.eclipse.jdt.core.dom.Modifier;
38 import org.eclipse.jdt.core.dom.Name;
39 import org.eclipse.jdt.core.dom.QualifiedName;
40 import org.eclipse.jdt.core.dom.SimpleName;
41 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
42 import org.eclipse.jdt.core.dom.SuperFieldAccess;
43 import org.eclipse.jdt.core.dom.SwitchCase;
44 import org.eclipse.jdt.core.dom.ThisExpression;
45 import org.eclipse.jdt.core.dom.Type;
46 import org.eclipse.jdt.core.dom.TypeDeclaration;
47 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
48 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
49 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
50
51 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
52 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
53 import org.eclipse.jdt.internal.corext.dom.Bindings;
54 import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
55 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
56 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
57 import org.eclipse.jdt.internal.corext.util.Messages;
58
59 import org.eclipse.jdt.ui.text.java.IProblemLocation;
60
61 import org.eclipse.jdt.internal.ui.text.correction.ProblemLocation;
62
63 /**
64  * A fix which fixes code style issues.
65  */

66 public class CodeStyleFix extends AbstractFix {
67     
68     private final static class CodeStyleVisitor extends GenericVisitor {
69         
70         private final List JavaDoc/*<IFixRewriteOperation>*/ fResult;
71         private final ImportRewrite fImportRewrite;
72         private final boolean fFindUnqualifiedAccesses;
73         private final boolean fFindUnqualifiedStaticAccesses;
74         private final boolean fFindUnqualifiedMethodAccesses;
75         private final boolean fFindUnqualifiedStaticMethodAccesses;
76         
77         public CodeStyleVisitor(CompilationUnit compilationUnit,
78                 boolean findUnqualifiedAccesses,
79                 boolean findUnqualifiedStaticAccesses,
80                 boolean findUnqualifiedMethodAccesses,
81                 boolean findUnqualifiedStaticMethodAccesses,
82                 List JavaDoc resultingCollection) throws CoreException {
83             
84             fFindUnqualifiedAccesses= findUnqualifiedAccesses;
85             fFindUnqualifiedStaticAccesses= findUnqualifiedStaticAccesses;
86             fFindUnqualifiedMethodAccesses= findUnqualifiedMethodAccesses;
87             fFindUnqualifiedStaticMethodAccesses= findUnqualifiedStaticMethodAccesses;
88             fImportRewrite= StubUtility.createImportRewrite(compilationUnit, true);
89             fResult= resultingCollection;
90         }
91         
92         /**
93          * {@inheritDoc}
94          */

95         public boolean visit(TypeDeclaration node) {
96             if (!fFindUnqualifiedStaticAccesses && !fFindUnqualifiedStaticMethodAccesses && node.isInterface())
97                 return false;
98             
99             return super.visit(node);
100         }
101
102         public boolean visit(QualifiedName node) {
103             if (fFindUnqualifiedAccesses || fFindUnqualifiedStaticAccesses) {
104                 ASTNode simpleName= node;
105                 while (simpleName instanceof QualifiedName) {
106                     simpleName= ((QualifiedName) simpleName).getQualifier();
107                 }
108                 if (simpleName instanceof SimpleName) {
109                     handleSimpleName((SimpleName)simpleName);
110                 }
111             }
112             return false;
113         }
114
115         public boolean visit(SimpleName node) {
116             if (fFindUnqualifiedAccesses || fFindUnqualifiedStaticAccesses) {
117                 handleSimpleName(node);
118             }
119             return false;
120         }
121         
122         /**
123          * {@inheritDoc}
124          */

125         public boolean visit(MethodInvocation node) {
126             if (!fFindUnqualifiedMethodAccesses && !fFindUnqualifiedStaticMethodAccesses)
127                 return true;
128             
129             if (node.getExpression() != null)
130                 return true;
131             
132             IBinding binding= node.getName().resolveBinding();
133             if (!(binding instanceof IMethodBinding))
134                 return true;
135             
136             handleMethod(node.getName(), (IMethodBinding)binding);
137             return true;
138         }
139
140         private void handleSimpleName(SimpleName node) {
141             ASTNode firstExpression= node.getParent();
142             if (firstExpression instanceof FieldAccess) {
143                 while (firstExpression instanceof FieldAccess) {
144                     firstExpression= ((FieldAccess)firstExpression).getExpression();
145                 }
146                 if (!(firstExpression instanceof SimpleName))
147                     return;
148                 
149                 node= (SimpleName)firstExpression;
150             } else if (firstExpression instanceof SuperFieldAccess)
151                 return;
152             
153             StructuralPropertyDescriptor parentDescription= node.getLocationInParent();
154             if (parentDescription == VariableDeclarationFragment.NAME_PROPERTY || parentDescription == SwitchCase.EXPRESSION_PROPERTY)
155                 return;
156             
157             IBinding binding= node.resolveBinding();
158             if (!(binding instanceof IVariableBinding))
159                 return;
160             
161             handleVariable(node, (IVariableBinding) binding);
162         }
163
164         private void handleVariable(SimpleName node, IVariableBinding varbinding) {
165             if (!varbinding.isField())
166                 return;
167             
168             if (varbinding.isEnumConstant())
169                 return;
170
171             ITypeBinding declaringClass= varbinding.getDeclaringClass();
172             if (Modifier.isStatic(varbinding.getModifiers())) {
173                 if (fFindUnqualifiedStaticAccesses) {
174                     Initializer initializer= (Initializer) ASTNodes.getParent(node, Initializer.class);
175                     //Do not qualify assignments to static final fields in static initializers (would result in compile error)
176
StructuralPropertyDescriptor parentDescription= node.getLocationInParent();
177                     if (initializer != null && Modifier.isStatic(initializer.getModifiers())
178                             && Modifier.isFinal(varbinding.getModifiers()) && parentDescription == Assignment.LEFT_HAND_SIDE_PROPERTY)
179                         return;
180                         
181                     //Do not qualify static fields if defined inside an anonymous class
182
if (declaringClass.isAnonymous())
183                         return;
184
185                     fResult.add(new AddStaticQualifierOperation(declaringClass, node));
186                 }
187             } else if (fFindUnqualifiedAccesses){
188                 String JavaDoc qualifier= getNonStaticQualifier(declaringClass, fImportRewrite, node);
189                 if (qualifier == null)
190                     return;
191
192                 fResult.add(new AddThisQualifierOperation(qualifier, node));
193             }
194         }
195
196         private void handleMethod(SimpleName node, IMethodBinding binding) {
197             ITypeBinding declaringClass= binding.getDeclaringClass();
198             if (Modifier.isStatic(binding.getModifiers())) {
199                 if (fFindUnqualifiedStaticMethodAccesses) {
200                     //Do not qualify static fields if defined inside an anonymous class
201
if (declaringClass.isAnonymous())
202                         return;
203
204                     fResult.add(new AddStaticQualifierOperation(declaringClass, node));
205                 }
206             } else {
207                 if (fFindUnqualifiedMethodAccesses) {
208                     String JavaDoc qualifier= getNonStaticQualifier(declaringClass, fImportRewrite, node);
209                     if (qualifier == null)
210                         return;
211
212                     fResult.add(new AddThisQualifierOperation(qualifier, node));
213                 }
214             }
215         }
216     }
217     
218     private static class ThisQualifierVisitor extends GenericVisitor {
219         
220         private final CompilationUnit fCompilationUnit;
221         private final List JavaDoc fOperations;
222         private final boolean fRemoveFieldQualifiers;
223         private final boolean fRemoveMethodQualifiers;
224         
225         public ThisQualifierVisitor(boolean removeFieldQualifiers,
226                                     boolean removeMethodQualifiers,
227                                     CompilationUnit compilationUnit,
228                                     List JavaDoc result) {
229             fRemoveFieldQualifiers= removeFieldQualifiers;
230             fRemoveMethodQualifiers= removeMethodQualifiers;
231             fCompilationUnit= compilationUnit;
232             fOperations= result;
233         }
234         
235         /**
236          * {@inheritDoc}
237          */

238         public boolean visit(final FieldAccess node) {
239             if (!fRemoveFieldQualifiers)
240                 return true;
241             
242             Expression expression= node.getExpression();
243             if (!(expression instanceof ThisExpression))
244                 return true;
245             
246             final SimpleName name= node.getName();
247             if (hasConflict(expression.getStartPosition(), name, ScopeAnalyzer.VARIABLES))
248                 return true;
249             
250             fOperations.add(new AbstractFixRewriteOperation() {
251                 public void rewriteAST(CompilationUnitRewrite cuRewrite, List JavaDoc textEditGroups) throws CoreException {
252                     ASTRewrite rewrite= cuRewrite.getASTRewrite();
253                     
254                     TextEditGroup group= createTextEditGroup(FixMessages.CodeStyleFix_removeThis_groupDescription);
255                     textEditGroups.add(group);
256                     
257                     rewrite.replace(node, rewrite.createCopyTarget(name), group);
258                 }
259             });
260             return super.visit(node);
261         }
262         
263         /**
264          * {@inheritDoc}
265          */

266         public boolean visit(final MethodInvocation node) {
267             if (!fRemoveMethodQualifiers)
268                 return true;
269             
270             Expression expression= node.getExpression();
271             if (!(expression instanceof ThisExpression))
272                 return true;
273             
274             final SimpleName name= node.getName();
275             if (name.resolveBinding() == null)
276                 return true;
277             
278             if (hasConflict(expression.getStartPosition(), name, ScopeAnalyzer.METHODS))
279                 return true;
280             
281             Name qualifier= ((ThisExpression)expression).getQualifier();
282             if (qualifier != null) {
283                 ITypeBinding declaringClass= ((IMethodBinding)name.resolveBinding()).getDeclaringClass();
284                 if (declaringClass == null)
285                     return true;
286                 
287                 ITypeBinding caller= getDeclaringType(node);
288                 if (caller == null)
289                     return true;
290                 
291                 ITypeBinding callee= (ITypeBinding)qualifier.resolveBinding();
292                 if (callee == null)
293                     return true;
294                 
295                 if (callee.isAssignmentCompatible(declaringClass) && caller.isAssignmentCompatible(declaringClass))
296                     return true;
297             }
298             
299             fOperations.add(new AbstractFixRewriteOperation() {
300                 public void rewriteAST(CompilationUnitRewrite cuRewrite, List JavaDoc textEditGroups) throws CoreException {
301                     ASTRewrite rewrite= cuRewrite.getASTRewrite();
302                     
303                     TextEditGroup group= createTextEditGroup(FixMessages.CodeStyleFix_removeThis_groupDescription);
304                     textEditGroups.add(group);
305                     
306                     rewrite.remove(node.getExpression(), group);
307                 }
308             });
309             return super.visit(node);
310         }
311         
312         private ITypeBinding getDeclaringType(MethodInvocation node) {
313             ASTNode p= node;
314             while (p != null) {
315                 p= p.getParent();
316                 if (p instanceof AbstractTypeDeclaration) {
317                     return ((AbstractTypeDeclaration)p).resolveBinding();
318                 }
319             }
320             return null;
321         }
322
323         private boolean hasConflict(int startPosition, SimpleName name, int flag) {
324             ScopeAnalyzer analyzer= new ScopeAnalyzer(fCompilationUnit);
325             IBinding[] declarationsInScope= analyzer.getDeclarationsInScope(startPosition, flag);
326             for (int i= 0; i < declarationsInScope.length; i++) {
327                 IBinding decl= declarationsInScope[i];
328                 if (decl.getName().equals(name.getIdentifier()) && name.resolveBinding() != decl)
329                     return true;
330             }
331             return false;
332         }
333     }
334
335     private final static class AddThisQualifierOperation extends AbstractFixRewriteOperation {
336
337         private final String JavaDoc fQualifier;
338         private final SimpleName fName;
339
340         public AddThisQualifierOperation(String JavaDoc qualifier, SimpleName name) {
341             fQualifier= qualifier;
342             fName= name;
343         }
344         
345         public String JavaDoc getDescription() {
346             return Messages.format(FixMessages.CodeStyleFix_QualifyWithThis_description, new Object JavaDoc[] {fName.getIdentifier(), fQualifier});
347         }
348
349         /* (non-Javadoc)
350          * @see org.eclipse.jdt.internal.corext.fix.AbstractFix.IFixRewriteOperation#rewriteAST(org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite, java.util.List)
351          */

352         public void rewriteAST(CompilationUnitRewrite cuRewrite, List JavaDoc textEditGroups) throws CoreException {
353             ASTRewrite rewrite= cuRewrite.getASTRewrite();
354             TextEditGroup group;
355             if (fName.resolveBinding() instanceof IMethodBinding) {
356                 group= createTextEditGroup(FixMessages.CodeStyleFix_QualifyMethodWithThis_description);
357             } else {
358                 group= createTextEditGroup(FixMessages.CodeStyleFix_QualifyFieldWithThis_description);
359             }
360             textEditGroups.add(group);
361             rewrite.replace(fName, rewrite.createStringPlaceholder(fQualifier + '.' + fName.getIdentifier(), ASTNode.SIMPLE_NAME), group);
362         }
363     }
364     
365     private final static class AddStaticQualifierOperation extends AbstractFixRewriteOperation {
366
367         private final SimpleName fName;
368         private final ITypeBinding fDeclaringClass;
369         
370         public AddStaticQualifierOperation(ITypeBinding declaringClass, SimpleName name) {
371             super();
372             fDeclaringClass= declaringClass;
373             fName= name;
374         }
375
376         /* (non-Javadoc)
377          * @see org.eclipse.jdt.internal.corext.fix.AbstractFix.IFixRewriteOperation#rewriteAST(org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite, java.util.List)
378          */

379         public void rewriteAST(CompilationUnitRewrite cuRewrite, List JavaDoc textEditGroups) throws CoreException {
380             ASTRewrite rewrite= cuRewrite.getASTRewrite();
381             CompilationUnit compilationUnit= cuRewrite.getRoot();
382             importType(fDeclaringClass, fName, cuRewrite.getImportRewrite(), compilationUnit);
383             TextEditGroup group;
384             if (fName.resolveBinding() instanceof IMethodBinding) {
385                 group= createTextEditGroup(FixMessages.CodeStyleFix_QualifyMethodWithDeclClass_description);
386             } else {
387                 group= createTextEditGroup(FixMessages.CodeStyleFix_QualifyFieldWithDeclClass_description);
388             }
389             textEditGroups.add(group);
390             IJavaElement javaElement= fDeclaringClass.getJavaElement();
391             if (javaElement instanceof IType) {
392                 Name qualifierName= compilationUnit.getAST().newName(((IType)javaElement).getElementName());
393                 SimpleName simpleName= (SimpleName)rewrite.createMoveTarget(fName);
394                 QualifiedName qualifiedName= compilationUnit.getAST().newQualifiedName(qualifierName, simpleName);
395                 rewrite.replace(fName, qualifiedName, group);
396             }
397         }
398         
399     }
400     
401     private final static class ToStaticAccessOperation extends AbstractFixRewriteOperation {
402
403         private final ITypeBinding fDeclaringTypeBinding;
404         private final Expression fQualifier;
405
406         public ToStaticAccessOperation(ITypeBinding declaringTypeBinding, Expression qualifier) {
407             super();
408             fDeclaringTypeBinding= declaringTypeBinding;
409             fQualifier= qualifier;
410         }
411         
412         public String JavaDoc getAccessorName() {
413             return fDeclaringTypeBinding.getName();
414         }
415
416         /* (non-Javadoc)
417          * @see org.eclipse.jdt.internal.corext.fix.AbstractFix.IFixRewriteOperation#rewriteAST(org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite, java.util.List)
418          */

419         public void rewriteAST(CompilationUnitRewrite cuRewrite, List JavaDoc textEditGroups) throws CoreException {
420             Type type= importType(fDeclaringTypeBinding, fQualifier, cuRewrite.getImportRewrite(), cuRewrite.getRoot());
421             TextEditGroup group= createTextEditGroup(FixMessages.CodeStyleFix_ChangeAccessUsingDeclaring_description);
422             textEditGroups.add(group);
423             cuRewrite.getASTRewrite().replace(fQualifier, type, group);
424         }
425     }
426     
427     public static CodeStyleFix[] createNonStaticAccessFixes(CompilationUnit compilationUnit, IProblemLocation problem) throws CoreException {
428         if (!isNonStaticAccess(problem))
429             return null;
430         
431         ToStaticAccessOperation operations[]= createToStaticAccessOperations(compilationUnit, problem);
432         if (operations == null)
433             return null;
434
435         String JavaDoc label1= Messages.format(FixMessages.CodeStyleFix_ChangeAccessToStatic_description, operations[0].getAccessorName());
436         CodeStyleFix fix1= new CodeStyleFix(label1, compilationUnit, new IFixRewriteOperation[] {operations[0]});
437
438         if (operations.length > 1) {
439             String JavaDoc label2= Messages.format(FixMessages.CodeStyleFix_ChangeAccessToStaticUsingInstanceType_description, operations[1].getAccessorName());
440             CodeStyleFix fix2= new CodeStyleFix(label2, compilationUnit, new IFixRewriteOperation[] {operations[1]});
441             return new CodeStyleFix[] {fix1, fix2};
442         }
443         return new CodeStyleFix[] {fix1};
444     }
445     
446     public static CodeStyleFix createAddFieldQualifierFix(CompilationUnit compilationUnit, IProblemLocation problem) throws CoreException {
447         if (IProblem.UnqualifiedFieldAccess != problem.getProblemId())
448             return null;
449         
450         AddThisQualifierOperation operation= getUnqualifiedFieldAccessResolveOperation(compilationUnit, problem);
451         if (operation == null)
452             return null;
453
454         String JavaDoc groupName= operation.getDescription();
455         return new CodeStyleFix(groupName, compilationUnit, new IFixRewriteOperation[] {operation});
456     }
457     
458     public static CodeStyleFix createIndirectAccessToStaticFix(CompilationUnit compilationUnit, IProblemLocation problem) throws CoreException {
459         if (!isIndirectStaticAccess(problem))
460             return null;
461         
462         ToStaticAccessOperation operations[]= createToStaticAccessOperations(compilationUnit, problem);
463         if (operations == null)
464             return null;
465
466         String JavaDoc label= Messages.format(FixMessages.CodeStyleFix_ChangeStaticAccess_description, operations[0].getAccessorName());
467         return new CodeStyleFix(label, compilationUnit, new IFixRewriteOperation[] {operations[0]});
468     }
469     
470     public static CodeStyleFix createCleanUp(CompilationUnit compilationUnit,
471             boolean addThisQualifier,
472             boolean changeNonStaticAccessToStatic,
473             boolean qualifyStaticFieldAccess,
474             boolean changeIndirectStaticAccessToDirect,
475             boolean qualifyMethodAccess,
476             boolean qualifyStaticMethodAccess,
477             boolean removeFieldQualifier,
478             boolean removeMethodQualifier) throws CoreException {
479         
480         if (!addThisQualifier && !changeNonStaticAccessToStatic && !qualifyStaticFieldAccess && !changeIndirectStaticAccessToDirect && !qualifyMethodAccess && !qualifyStaticMethodAccess && !removeFieldQualifier && !removeMethodQualifier)
481             return null;
482
483         List JavaDoc/*<IFixRewriteOperation>*/ operations= new ArrayList JavaDoc();
484         if (addThisQualifier || qualifyStaticFieldAccess || qualifyMethodAccess || qualifyStaticMethodAccess) {
485             CodeStyleVisitor codeStyleVisitor= new CodeStyleVisitor(compilationUnit, addThisQualifier, qualifyStaticFieldAccess, qualifyMethodAccess, qualifyStaticMethodAccess, operations);
486             compilationUnit.accept(codeStyleVisitor);
487         }
488         
489         IProblem[] problems= compilationUnit.getProblems();
490         IProblemLocation[] locations= new IProblemLocation[problems.length];
491         for (int i= 0; i < problems.length; i++) {
492             locations[i]= new ProblemLocation(problems[i]);
493         }
494         addToStaticAccessOperations(compilationUnit, locations, changeNonStaticAccessToStatic, changeIndirectStaticAccessToDirect, operations);
495         
496         if (removeFieldQualifier || removeMethodQualifier) {
497             ThisQualifierVisitor visitor= new ThisQualifierVisitor(removeFieldQualifier, removeMethodQualifier, compilationUnit, operations);
498             compilationUnit.accept(visitor);
499         }
500
501         if (operations.isEmpty())
502             return null;
503         
504         IFixRewriteOperation[] operationsArray= (IFixRewriteOperation[])operations.toArray(new IFixRewriteOperation[operations.size()]);
505         return new CodeStyleFix(FixMessages.CodeStyleFix_change_name, compilationUnit, operationsArray);
506     }
507     
508     public static CodeStyleFix createCleanUp(CompilationUnit compilationUnit, IProblemLocation[] problems,
509             boolean addThisQualifier,
510             boolean changeNonStaticAccessToStatic,
511             boolean changeIndirectStaticAccessToDirect) throws CoreException {
512         
513         if (!addThisQualifier && !changeNonStaticAccessToStatic && !changeIndirectStaticAccessToDirect)
514             return null;
515                 
516         List JavaDoc/*<IFixRewriteOperation>*/ operations= new ArrayList JavaDoc();
517         if (addThisQualifier) {
518             for (int i= 0; i < problems.length; i++) {
519                 IProblemLocation problem= problems[i];
520                 if (problem.getProblemId() == IProblem.UnqualifiedFieldAccess) {
521                     AddThisQualifierOperation operation= getUnqualifiedFieldAccessResolveOperation(compilationUnit, problem);
522                     if (operation != null)
523                         operations.add(operation);
524                 }
525             }
526         }
527
528         addToStaticAccessOperations(compilationUnit, problems, changeNonStaticAccessToStatic, changeIndirectStaticAccessToDirect, operations);
529
530         if (operations.isEmpty())
531             return null;
532         
533         IFixRewriteOperation[] operationsArray= (IFixRewriteOperation[])operations.toArray(new IFixRewriteOperation[operations.size()]);
534         return new CodeStyleFix(FixMessages.CodeStyleFix_change_name, compilationUnit, operationsArray);
535     }
536     
537     private static void addToStaticAccessOperations(CompilationUnit compilationUnit, IProblemLocation[] problems, boolean changeNonStaticAccessToStatic, boolean changeIndirectStaticAccessToDirect, List JavaDoc result) {
538         Hashtable JavaDoc nonStaticAccessOps= new Hashtable JavaDoc();
539         if (changeNonStaticAccessToStatic || changeIndirectStaticAccessToDirect) {
540             for (int i= 0; i < problems.length; i++) {
541                 IProblemLocation problem= problems[i];
542                 boolean isNonStaticAccess= changeNonStaticAccessToStatic && isNonStaticAccess(problem);
543                 boolean isIndirectStaticAccess= changeIndirectStaticAccessToDirect && isIndirectStaticAccess(problem);
544                 if (isNonStaticAccess || isIndirectStaticAccess) {
545                     ToStaticAccessOperation[] nonStaticAccessInformation= createToStaticAccessOperations(compilationUnit, problem);
546                     if (nonStaticAccessInformation != null) {
547                         ToStaticAccessOperation op= nonStaticAccessInformation[0];
548                         nonStaticAccessOps.put(op.fQualifier, op);
549                     }
550                 }
551             }
552         }
553         for (Iterator JavaDoc iter= nonStaticAccessOps.values().iterator(); iter.hasNext();) {
554             ToStaticAccessOperation op= (ToStaticAccessOperation)iter.next();
555             if (!nonStaticAccessOps.containsKey(op.fQualifier.getParent()))
556                 result.add(op);
557         }
558     }
559
560     private static boolean isIndirectStaticAccess(IProblemLocation problem) {
561         return (problem.getProblemId() == IProblem.IndirectAccessToStaticField
562                 || problem.getProblemId() == IProblem.IndirectAccessToStaticMethod);
563     }
564     
565     private static boolean isNonStaticAccess(IProblemLocation problem) {
566         return (problem.getProblemId() == IProblem.NonStaticAccessToStaticField
567                 || problem.getProblemId() == IProblem.NonStaticAccessToStaticMethod);
568     }
569     
570     private static ToStaticAccessOperation[] createToStaticAccessOperations(CompilationUnit astRoot, IProblemLocation problem) {
571         ASTNode selectedNode= problem.getCoveringNode(astRoot);
572         if (selectedNode == null) {
573             return null;
574         }
575
576         Expression qualifier= null;
577         IBinding accessBinding= null;
578
579         if (selectedNode instanceof QualifiedName) {
580             QualifiedName name= (QualifiedName) selectedNode;
581             qualifier= name.getQualifier();
582             accessBinding= name.resolveBinding();
583         } else if (selectedNode instanceof SimpleName) {
584             ASTNode parent= selectedNode.getParent();
585             if (parent instanceof FieldAccess) {
586                 FieldAccess fieldAccess= (FieldAccess) parent;
587                 qualifier= fieldAccess.getExpression();
588                 accessBinding= fieldAccess.getName().resolveBinding();
589             } else if (parent instanceof QualifiedName) {
590                 QualifiedName qualifiedName= (QualifiedName) parent;
591                 qualifier= qualifiedName.getQualifier();
592                 accessBinding= qualifiedName.getName().resolveBinding();
593             }
594         } else if (selectedNode instanceof MethodInvocation) {
595             MethodInvocation methodInvocation= (MethodInvocation) selectedNode;
596             qualifier= methodInvocation.getExpression();
597             accessBinding= methodInvocation.getName().resolveBinding();
598         } else if (selectedNode instanceof FieldAccess) {
599             FieldAccess fieldAccess= (FieldAccess) selectedNode;
600             qualifier= fieldAccess.getExpression();
601             accessBinding= fieldAccess.getName().resolveBinding();
602         }
603         
604         if (accessBinding != null && qualifier != null) {
605             ToStaticAccessOperation declaring= null;
606             ITypeBinding declaringTypeBinding= getDeclaringTypeBinding(accessBinding);
607             if (declaringTypeBinding != null) {
608                 declaringTypeBinding= declaringTypeBinding.getTypeDeclaration(); // use generic to avoid any type arguments
609

610                 declaring= new ToStaticAccessOperation(declaringTypeBinding, qualifier);
611             }
612             ToStaticAccessOperation instance= null;
613             ITypeBinding instanceTypeBinding= Bindings.normalizeTypeBinding(qualifier.resolveTypeBinding());
614             if (instanceTypeBinding != null) {
615                 instanceTypeBinding= instanceTypeBinding.getTypeDeclaration(); // use generic to avoid any type arguments
616
if (instanceTypeBinding.getTypeDeclaration() != declaringTypeBinding) {
617                     instance= new ToStaticAccessOperation(instanceTypeBinding, qualifier);
618                 }
619             }
620             if (declaring != null && instance != null) {
621                 return new ToStaticAccessOperation[] {declaring, instance};
622             } else {
623                 return new ToStaticAccessOperation[] {declaring};
624             }
625         }
626         return null;
627     }
628     
629     private static ITypeBinding getDeclaringTypeBinding(IBinding accessBinding) {
630         if (accessBinding instanceof IMethodBinding) {
631             return ((IMethodBinding) accessBinding).getDeclaringClass();
632         } else if (accessBinding instanceof IVariableBinding) {
633             return ((IVariableBinding) accessBinding).getDeclaringClass();
634         }
635         return null;
636     }
637         
638     private static AddThisQualifierOperation getUnqualifiedFieldAccessResolveOperation(CompilationUnit compilationUnit, IProblemLocation problem) throws CoreException {
639         SimpleName name= getName(compilationUnit, problem);
640         if (name == null)
641             return null;
642         
643         IBinding binding= name.resolveBinding();
644         if (binding == null || binding.getKind() != IBinding.VARIABLE)
645             return null;
646         
647         ImportRewrite imports= StubUtility.createImportRewrite(compilationUnit, true);
648         
649         String JavaDoc replacement= getQualifier((IVariableBinding)binding, imports, name);
650         if (replacement == null)
651             return null;
652         
653         return new AddThisQualifierOperation(replacement, name);
654     }
655     
656     private static String JavaDoc getQualifier(IVariableBinding binding, ImportRewrite imports, SimpleName name) {
657         ITypeBinding declaringClass= binding.getDeclaringClass();
658         if (Modifier.isStatic(binding.getModifiers())) {
659             IJavaElement javaElement= declaringClass.getJavaElement();
660             if (javaElement instanceof IType) {
661                 return ((IType)javaElement).getElementName();
662             }
663         } else {
664             return getNonStaticQualifier(declaringClass, imports, name);
665         }
666
667         return null;
668     }
669
670     private static String JavaDoc getNonStaticQualifier(ITypeBinding declaringClass, ImportRewrite imports, SimpleName name) {
671         ITypeBinding parentType= Bindings.getBindingOfParentType(name);
672         ITypeBinding currType= parentType;
673         while (currType != null && !Bindings.isSuperType(declaringClass, currType)) {
674             currType= currType.getDeclaringClass();
675         }
676         if (currType == null) {
677             declaringClass= declaringClass.getTypeDeclaration();
678             currType= parentType;
679             while (currType != null && !Bindings.isSuperType(declaringClass, currType)) {
680                 currType= currType.getDeclaringClass();
681             }
682         }
683         if (currType != parentType) {
684             if (currType == null)
685                 return null;
686             
687             if (currType.isAnonymous())
688                 //If we access a field of a super class of an anonymous class
689
//then we can only qualify with 'this' but not with outer.this
690
//see bug 115277
691
return null;
692             
693             String JavaDoc outer= imports.addImport(currType);
694             return outer + ".this"; //$NON-NLS-1$
695
} else {
696             return "this"; //$NON-NLS-1$
697
}
698     }
699     
700     private static SimpleName getName(CompilationUnit compilationUnit, IProblemLocation problem) {
701         ASTNode selectedNode= problem.getCoveringNode(compilationUnit);
702         
703         while (selectedNode instanceof QualifiedName) {
704             selectedNode= ((QualifiedName) selectedNode).getQualifier();
705         }
706         if (!(selectedNode instanceof SimpleName)) {
707             return null;
708         }
709         return (SimpleName) selectedNode;
710     }
711
712     private CodeStyleFix(String JavaDoc name, CompilationUnit compilationUnit, IFixRewriteOperation[] fixRewriteOperations) {
713         super(name, compilationUnit, fixRewriteOperations);
714     }
715 }
716
Popular Tags