1 13 package org.eclipse.jdt.internal.corext.refactoring.sef; 14 15 import java.util.ArrayList ; 16 import java.util.List ; 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 61 class AccessAnalyzer extends ASTVisitor { 62 63 private ICompilationUnit fCUnit; 64 private IVariableBinding fFieldBinding; 65 private ITypeBinding fDeclaringClassBinding; 66 private String fGetter; 67 private String fSetter; 68 private ASTRewrite fRewriter; 69 private ImportRewrite fImportRewriter; 70 private List 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 READ_ACCESS= RefactoringCoreMessages.SelfEncapsulateField_AccessAnalyzer_encapsulate_read_access; 81 private static final String WRITE_ACCESS= RefactoringCoreMessages.SelfEncapsulateField_AccessAnalyzer_encapsulate_write_access; 82 private static final String PREFIX_ACCESS= RefactoringCoreMessages.SelfEncapsulateField_AccessAnalyzer_encapsulate_prefix_access; 83 private static final String 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 (); 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 } 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 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 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 arguments= invocation.arguments(); 137 if (node.getOperator() == Assignment.Operator.ASSIGN) { 138 arguments.add(fRewriter.createCopyTarget(node.getRightHandSide())); 139 } else { 140 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), 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 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 (!fRemoveStaticImport) 229 return; 230 231 ITypeBinding type= fFieldBinding.getDeclaringClass(); 232 String fieldName= fFieldBinding.getName(); 233 String typeName= type.getQualifiedName(); 234 if (fRemoveStaticImport) { 235 fImportRewriter.removeStaticImport(typeName + "." + fieldName); } 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 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)) { argument.setOperator(InfixExpression.Operator.PLUS); 301 } else if ("--".equals(operator)) { argument.setOperator(InfixExpression.Operator.MINUS); 303 } else { 304 Assert.isTrue(false, "Should not happen"); } 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")); 313 fReferencingGetter= true; 314 fReferencingSetter= true; 315 316 return invocation; 317 } 318 319 private TextEditGroup createGroupDescription(String name) { 320 TextEditGroup result= new TextEditGroup(name); 321 fGroupDescriptions.add(result); 322 return result; 323 } 324 } 325 326 | Popular Tags |