KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > sef > AccessAnalyzer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  * jens.lukowski@gmx.de - contributed code to convert prefix and postfix
11  * expressions into a combination of setter and getter calls.
12  *******************************************************************************/

13 package org.eclipse.jdt.internal.corext.refactoring.sef;
14
15 import java.util.ArrayList JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.text.edits.TextEditGroup;
19
20 import org.eclipse.core.runtime.Assert;
21
22 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
23
24 import org.eclipse.jdt.core.Flags;
25 import org.eclipse.jdt.core.ICompilationUnit;
26 import org.eclipse.jdt.core.JavaModelException;
27 import org.eclipse.jdt.core.dom.AST;
28 import org.eclipse.jdt.core.dom.ASTNode;
29 import org.eclipse.jdt.core.dom.ASTVisitor;
30 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
31 import org.eclipse.jdt.core.dom.Assignment;
32 import org.eclipse.jdt.core.dom.CompilationUnit;
33 import org.eclipse.jdt.core.dom.Expression;
34 import org.eclipse.jdt.core.dom.ExpressionStatement;
35 import org.eclipse.jdt.core.dom.FieldAccess;
36 import org.eclipse.jdt.core.dom.IBinding;
37 import org.eclipse.jdt.core.dom.ITypeBinding;
38 import org.eclipse.jdt.core.dom.IVariableBinding;
39 import org.eclipse.jdt.core.dom.ImportDeclaration;
40 import org.eclipse.jdt.core.dom.InfixExpression;
41 import org.eclipse.jdt.core.dom.MethodDeclaration;
42 import org.eclipse.jdt.core.dom.MethodInvocation;
43 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
44 import org.eclipse.jdt.core.dom.PostfixExpression;
45 import org.eclipse.jdt.core.dom.PrefixExpression;
46 import org.eclipse.jdt.core.dom.QualifiedName;
47 import org.eclipse.jdt.core.dom.SimpleName;
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.SourceRange;
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.refactoring.RefactoringCoreMessages;
55 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
56
57 /**
58  * Analyzer to find all references to the field and to determine how to convert
59  * them into setter or getter calls.
60  */

61 class AccessAnalyzer extends ASTVisitor {
62
63     private ICompilationUnit fCUnit;
64     private IVariableBinding fFieldBinding;
65     private ITypeBinding fDeclaringClassBinding;
66     private String JavaDoc fGetter;
67     private String JavaDoc fSetter;
68     private ASTRewrite fRewriter;
69     private ImportRewrite fImportRewriter;
70     private List JavaDoc fGroupDescriptions;
71     private RefactoringStatus fStatus;
72     private boolean fSetterMustReturnValue;
73     private boolean fEncapsulateDeclaringClass;
74     private boolean fIsFieldFinal;
75     
76     private boolean fRemoveStaticImport;
77     private boolean fReferencingGetter;
78     private boolean fReferencingSetter;
79
80     private static final String JavaDoc READ_ACCESS= RefactoringCoreMessages.SelfEncapsulateField_AccessAnalyzer_encapsulate_read_access;
81     private static final String JavaDoc WRITE_ACCESS= RefactoringCoreMessages.SelfEncapsulateField_AccessAnalyzer_encapsulate_write_access;
82     private static final String JavaDoc PREFIX_ACCESS= RefactoringCoreMessages.SelfEncapsulateField_AccessAnalyzer_encapsulate_prefix_access;
83     private static final String JavaDoc POSTFIX_ACCESS= RefactoringCoreMessages.SelfEncapsulateField_AccessAnalyzer_encapsulate_postfix_access;
84         
85     public AccessAnalyzer(SelfEncapsulateFieldRefactoring refactoring, ICompilationUnit unit, IVariableBinding field, ITypeBinding declaringClass, ASTRewrite rewriter, ImportRewrite importRewrite) {
86         Assert.isNotNull(refactoring);
87         Assert.isNotNull(unit);
88         Assert.isNotNull(field);
89         Assert.isNotNull(declaringClass);
90         Assert.isNotNull(rewriter);
91         Assert.isNotNull(importRewrite);
92         fCUnit= unit;
93         fFieldBinding= field.getVariableDeclaration();
94         fDeclaringClassBinding= declaringClass;
95         fRewriter= rewriter;
96         fImportRewriter= importRewrite;
97         fGroupDescriptions= new ArrayList JavaDoc();
98         fGetter= refactoring.getGetterName();
99         fSetter= refactoring.getSetterName();
100         fEncapsulateDeclaringClass= refactoring.getEncapsulateDeclaringClass();
101         try {
102             fIsFieldFinal= Flags.isFinal(refactoring.getField().getFlags());
103         } catch (JavaModelException e) {
104             // assume non final field
105
}
106         fStatus= new RefactoringStatus();
107     }
108
109     public boolean getSetterMustReturnValue() {
110         return fSetterMustReturnValue;
111     }
112
113     public RefactoringStatus getStatus() {
114         return fStatus;
115     }
116     
117     public List JavaDoc getGroupDescriptions() {
118         return fGroupDescriptions;
119     }
120     
121     public boolean visit(Assignment node) {
122         Expression lhs= node.getLeftHandSide();
123         if (!considerBinding(resolveBinding(lhs), lhs))
124             return true;
125             
126         checkParent(node);
127         if (!fIsFieldFinal) {
128             // Write access.
129
AST ast= node.getAST();
130             MethodInvocation invocation= ast.newMethodInvocation();
131             invocation.setName(ast.newSimpleName(fSetter));
132             fReferencingSetter= true;
133             Expression receiver= getReceiver(lhs);
134             if (receiver != null)
135                 invocation.setExpression((Expression)fRewriter.createCopyTarget(receiver));
136             List JavaDoc arguments= invocation.arguments();
137             if (node.getOperator() == Assignment.Operator.ASSIGN) {
138                 arguments.add(fRewriter.createCopyTarget(node.getRightHandSide()));
139             } else {
140                 // This is the compound assignment case: field+= 10;
141
boolean needsParentheses= ASTNodes.needsParentheses(node.getRightHandSide());
142                 InfixExpression exp= ast.newInfixExpression();
143                 exp.setOperator(ASTNodes.convertToInfixOperator(node.getOperator()));
144                 MethodInvocation getter= ast.newMethodInvocation();
145                 getter.setName(ast.newSimpleName(fGetter));
146                 fReferencingGetter= true;
147                 if (receiver != null)
148                     getter.setExpression((Expression)fRewriter.createCopyTarget(receiver));
149                 exp.setLeftOperand(getter);
150                 Expression rhs= (Expression)fRewriter.createCopyTarget(node.getRightHandSide());
151                 if (needsParentheses) {
152                     ParenthesizedExpression p= ast.newParenthesizedExpression();
153                     p.setExpression(rhs);
154                     rhs= p;
155                 }
156                 exp.setRightOperand(rhs);
157                 arguments.add(exp);
158             }
159             fRewriter.replace(node, invocation, createGroupDescription(WRITE_ACCESS));
160         }
161         node.getRightHandSide().accept(this);
162         return false;
163     }
164
165     public boolean visit(SimpleName node) {
166         if (!node.isDeclaration() && considerBinding(node.resolveBinding(), node)) {
167             fReferencingGetter= true;
168             fRewriter.replace(
169                 node,
170                 fRewriter.createStringPlaceholder(fGetter + "()", ASTNode.METHOD_INVOCATION), //$NON-NLS-1$
171
createGroupDescription(READ_ACCESS));
172         }
173         return true;
174     }
175     
176     public boolean visit(ImportDeclaration node) {
177         if (considerBinding(node.resolveBinding(), node)) {
178             fRemoveStaticImport= true;
179         }
180         return false;
181     }
182     
183     public boolean visit(PrefixExpression node) {
184         Expression operand= node.getOperand();
185         if (!considerBinding(resolveBinding(operand), operand))
186             return true;
187         
188         PrefixExpression.Operator operator= node.getOperator();
189         if (operator != PrefixExpression.Operator.INCREMENT && operator != PrefixExpression.Operator.DECREMENT)
190             return true;
191             
192         checkParent(node);
193         
194         fRewriter.replace(node,
195             createInvocation(node.getAST(), node.getOperand(), node.getOperator().toString()),
196             createGroupDescription(PREFIX_ACCESS));
197         return false;
198     }
199     
200     public boolean visit(PostfixExpression node) {
201         Expression operand= node.getOperand();
202         if (!considerBinding(resolveBinding(operand), operand))
203             return true;
204
205         ASTNode parent= node.getParent();
206         if (!(parent instanceof ExpressionStatement)) {
207             fStatus.addError(RefactoringCoreMessages.SelfEncapsulateField_AccessAnalyzer_cannot_convert_postfix_expression,
208                 JavaStatusContext.create(fCUnit, new SourceRange(node)));
209             return false;
210         }
211         fRewriter.replace(node,
212             createInvocation(node.getAST(), node.getOperand(), node.getOperator().toString()),
213             createGroupDescription(POSTFIX_ACCESS));
214         return false;
215     }
216     
217     public boolean visit(MethodDeclaration node) {
218         String JavaDoc name= node.getName().getIdentifier();
219         if (name.equals(fGetter) || name.equals(fSetter))
220             return false;
221         return true;
222     }
223     
224     public void endVisit(CompilationUnit node) {
225         // If we don't had a static import to the field we don't
226
// have to add any, even if we generated a setter or
227
// getter access.
228
if (!fRemoveStaticImport)
229             return;
230         
231         ITypeBinding type= fFieldBinding.getDeclaringClass();
232         String JavaDoc fieldName= fFieldBinding.getName();
233         String JavaDoc typeName= type.getQualifiedName();
234         if (fRemoveStaticImport) {
235             fImportRewriter.removeStaticImport(typeName + "." + fieldName); //$NON-NLS-1$
236
}
237         if (fReferencingGetter) {
238             fImportRewriter.addStaticImport(typeName, fGetter, false);
239         }
240         if (fReferencingSetter) {
241             fImportRewriter.addStaticImport(typeName, fSetter, false);
242         }
243     }
244     
245     private boolean considerBinding(IBinding binding, ASTNode node) {
246         if (!(binding instanceof IVariableBinding))
247             return false;
248         boolean result= Bindings.equals(fFieldBinding, ((IVariableBinding)binding).getVariableDeclaration());
249         if (!result || fEncapsulateDeclaringClass)
250             return result;
251             
252         if (binding instanceof IVariableBinding) {
253             AbstractTypeDeclaration type= (AbstractTypeDeclaration)ASTNodes.getParent(node, AbstractTypeDeclaration.class);
254             if (type != null) {
255                 ITypeBinding declaringType= type.resolveBinding();
256                 return !Bindings.equals(fDeclaringClassBinding, declaringType);
257             }
258         }
259         return true;
260     }
261     
262     private void checkParent(ASTNode node) {
263         ASTNode parent= node.getParent();
264         if (!(parent instanceof ExpressionStatement))
265             fSetterMustReturnValue= true;
266     }
267         
268     private IBinding resolveBinding(Expression expression) {
269         if (expression instanceof SimpleName)
270             return ((SimpleName)expression).resolveBinding();
271         else if (expression instanceof QualifiedName)
272             return ((QualifiedName)expression).resolveBinding();
273         else if (expression instanceof FieldAccess)
274             return ((FieldAccess)expression).getName().resolveBinding();
275         return null;
276     }
277     
278     private Expression getReceiver(Expression expression) {
279         int type= expression.getNodeType();
280         switch(type) {
281             case ASTNode.SIMPLE_NAME:
282                 return null;
283             case ASTNode.QUALIFIED_NAME:
284                 return ((QualifiedName)expression).getQualifier();
285             case ASTNode.FIELD_ACCESS:
286                 return ((FieldAccess)expression).getExpression();
287         }
288         return null;
289     }
290         
291     private MethodInvocation createInvocation(AST ast, Expression operand, String JavaDoc operator) {
292         Expression receiver= getReceiver(operand);
293         MethodInvocation invocation= ast.newMethodInvocation();
294         invocation.setName(ast.newSimpleName(fSetter));
295         if (receiver != null)
296             invocation.setExpression((Expression)fRewriter.createCopyTarget(receiver));
297         InfixExpression argument= ast.newInfixExpression();
298         invocation.arguments().add(argument);
299         if ("++".equals(operator)) { //$NON-NLS-1$
300
argument.setOperator(InfixExpression.Operator.PLUS);
301         } else if ("--".equals(operator)) { //$NON-NLS-1$
302
argument.setOperator(InfixExpression.Operator.MINUS);
303         } else {
304             Assert.isTrue(false, "Should not happen"); //$NON-NLS-1$
305
}
306         MethodInvocation getter= ast.newMethodInvocation();
307         getter.setName(ast.newSimpleName(fGetter));
308         if (receiver != null)
309             getter.setExpression((Expression)fRewriter.createCopyTarget(receiver));
310         argument.setLeftOperand(getter);
311         argument.setRightOperand(ast.newNumberLiteral("1")); //$NON-NLS-1$
312

313         fReferencingGetter= true;
314         fReferencingSetter= true;
315         
316         return invocation;
317     }
318     
319     private TextEditGroup createGroupDescription(String JavaDoc name) {
320         TextEditGroup result= new TextEditGroup(name);
321         fGroupDescriptions.add(result);
322         return result;
323     }
324 }
325
326
Popular Tags