1 19 package org.netbeans.modules.refactoring.experimental.plugins; 20 21 import java.text.MessageFormat ; 22 import java.util.*; 23 import org.netbeans.jmi.javamodel.*; 24 import org.netbeans.jmi.javamodel.ClassDefinition; 25 import org.netbeans.jmi.javamodel.LocalVariable; 26 import org.netbeans.modules.javacore.internalapi.JavaModelUtil; 27 import org.netbeans.modules.javacore.internalapi.ProgressListener; 28 import org.netbeans.modules.javacore.internalapi.JavaMetamodel; 29 import org.netbeans.modules.refactoring.api.*; 30 import org.openide.filesystems.FileObject; 31 import org.openide.text.PositionBounds; 32 import org.openide.util.NbBundle; 33 import org.netbeans.modules.refactoring.spi.RefactoringElementsBag; 34 import org.netbeans.modules.refactoring.plugins.*; 35 import org.netbeans.modules.refactoring.experimental.IntroduceVariableRefactoring; 36 import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImpl; 37 38 42 public class IntroduceVariableRefactoringPlugin extends JavaRefactoringPlugin implements ProgressListener { 43 private Expression expression; 44 private String variableName; 45 private Type variableType; 46 private boolean replaceAll; 47 private boolean declareFinal; 48 private BehavioralFeature enclosingMethod = null; 49 private Set localVariables = null; 50 51 private IntroduceVariableRefactoring refactoring; 52 53 public IntroduceVariableRefactoringPlugin(IntroduceVariableRefactoring introduce) { 54 this.refactoring = introduce; 55 expression = introduce.getExpression(); 56 } 57 58 public Problem checkParameters() { 59 return setParameters( 60 refactoring.getVariableName(), 61 refactoring.getVariableType(), 62 refactoring.isReplaceAll(), 63 refactoring.isFinal() 64 ); 65 } 66 67 public Problem fastCheckParameters() { 68 String name = refactoring.getVariableName(); 69 if (name == null || name.length() == 0) { 70 return new Problem(true, getString("ERR_EmptyIdentifier")); 71 } 72 if (!org.openide.util.Utilities.isJavaIdentifier(name)) { 73 String msg = new MessageFormat (NbBundle.getMessage(RenameRefactoring.class, "ERR_InvalidIdentifier")).format(new Object [] {name}); return new Problem(true, msg); 75 } 76 return null; 77 } 78 79 public Problem preCheck() { 80 fireProgressListenerStart(refactoring.PRE_CHECK, 2); 81 Problem problem = null; 82 try { 83 if (expression == null || ((expression instanceof ElementReference) && ((ElementReference) expression).getElement() instanceof PrimitiveType)) { 84 problem = new Problem(true, getString("ERR_ExpressionNotSelected")); 85 fireProgressListenerStep(); 86 } else { 87 BehavioralFeature method = getMethod(); 88 fireProgressListenerStep(); 89 if (method == null) { 90 problem = new Problem(true, getString("ERR_NotInBehavioralFeature")); 91 } else { 92 Object comp = expression.refImmediateComposite(); 93 if ((comp instanceof ExpressionStatement) || 94 (!(comp instanceof Expression) && expression instanceof TypeReference) || 95 (comp instanceof NewClassExpression) || (comp instanceof NewArrayExpression)) { 96 problem = new Problem(true, getString("ERR_CannotReplaceExpression")); 97 } 98 } 99 } 100 fireProgressListenerStep(); 101 } finally { 102 fireProgressListenerStop(); 103 } 104 return problem; 105 } 106 107 private Problem checkParameters(String name, Type type, boolean replaceAll, boolean isFinal) { 108 collectLocalVariables(); 109 if (localVariables.contains(name)) { 110 String msg = new MessageFormat (getString("ERR_NameClashes")).format(new Object [] {name}); 111 return new Problem(true, msg); 112 } 113 return null; 114 } 115 116 private Problem setParameters(String name, Type type, boolean replaceAll, boolean isFinal) { 117 fireProgressListenerStart(refactoring.PARAMETERS_CHECK, 1); 118 try { 119 fireProgressListenerStep(); 120 121 variableName = name; 122 variableType = type; 123 this.replaceAll = replaceAll; 124 declareFinal = isFinal; 125 126 Problem result = checkParameters(name, type, replaceAll, isFinal); 127 return result; 128 } finally { 129 fireProgressListenerStop(); 130 } 131 } 132 133 public Problem prepare(RefactoringElementsBag elements) { 134 JavaModelPackage modelPackage = (JavaModelPackage) expression.refOutermostPackage(); 135 IntroduceVariableElement elem = new IntroduceVariableElement(expression, variableName, variableType, declareFinal); 136 elements.add(refactoring, elem); 137 if (refactoring.isReplaceAll()) { 138 BehavioralFeature method = getMethod(); 139 collectOccurrences(elements, method, refactoring.getVariableName()); 140 } else { 141 ReplaceExpressionElement replaceElem = new ReplaceExpressionElement(expression, refactoring.getVariableName()); 142 elements.add(refactoring, replaceElem); 143 } 144 return null; 145 } 146 147 149 private BehavioralFeature getMethod() { 150 if (enclosingMethod == null) { 151 Element elem = expression; 152 while (!(elem instanceof BehavioralFeature) && (elem != null)) { 153 elem = (Element)elem.refImmediateComposite(); 154 } 155 enclosingMethod = (BehavioralFeature)elem; 156 } 157 return enclosingMethod; 158 } 159 160 private void collectLocalVariables() { 161 localVariables = new HashSet(); 162 BehavioralFeature method = getMethod(); 163 if (method != null) { 164 collectLocalVariables(localVariables, method); 165 } 166 } 167 168 private void collectLocalVariables(Set localVars, Element elem) { 169 if (elem instanceof LocalVariable) { 176 LocalVariable localVar = (LocalVariable) elem; 177 localVars.add(localVar.getName()); 178 InitialValue initValue = localVar.getInitialValue(); 179 if (initValue != null) { 180 collectLocalVariables(localVars, initValue); 181 } 182 } else { 183 for (Iterator iter = elem.getChildren().iterator(); iter.hasNext(); ) { 184 collectLocalVariables(localVars, (Element)iter.next()); 185 } 186 } 187 } 188 189 private void collectOccurrences(RefactoringElementsBag elements, Element root, String name) { 190 for (Iterator iter = root.getChildren().iterator(); iter.hasNext(); ) { 191 Element elem = (Element) iter.next(); 192 if (elem instanceof Expression) { 193 findMatchingExpressions(elements, (Expression) elem, name); 194 } else if (!(elem instanceof ClassDefinition)) { 195 collectOccurrences(elements, elem, name); 196 } 197 } } 199 200 private void findMatchingExpressions(RefactoringElementsBag elements, Expression root, String name) { 201 if (compareExpressions(root, expression)) { 203 ReplaceExpressionElement replaceElem = new ReplaceExpressionElement(root, name); 204 elements.add(refactoring, replaceElem); 205 return; 206 } 207 for (Iterator iter = root.getChildren().iterator(); iter.hasNext(); ) { 208 Element elem = (Element) iter.next(); 209 if (elem instanceof Expression) { 210 findMatchingExpressions(elements, (Expression) elem, name); 211 } else { 212 return; 213 } 214 } } 216 217 public static boolean compareExpressions(Expression expr_1, Expression expr_2) { 218 if (expr_1 == null) { 219 return expr_2 == null; 220 } 221 if (expr_2 == null) { 222 return false; } 224 if (expr_1.getClass() != expr_2.getClass()) { 225 return false; 226 } 227 if (expr_1 instanceof NullLiteral) { 228 return true; 229 } else if (expr_1 instanceof BooleanLiteral) { 230 return ((BooleanLiteral) expr_1).isValue() == ((BooleanLiteral) expr_2).isValue(); 231 } else if (expr_1 instanceof StringLiteral) { 232 return ((StringLiteral) expr_1).getValue().equals(((StringLiteral) expr_2).getValue()); 233 } else if (expr_1 instanceof IntLiteral) { 234 return ((IntLiteral) expr_1).getValue() == ((IntLiteral) expr_2).getValue(); 235 } else if (expr_1 instanceof DoubleLiteral) { 236 return ((DoubleLiteral) expr_1).getValue() == ((DoubleLiteral) expr_2).getValue(); 237 } else if (expr_1 instanceof LongLiteral) { 238 return ((LongLiteral) expr_1).getValue() == ((LongLiteral) expr_2).getValue(); 239 } else if (expr_1 instanceof CharLiteral) { 240 return ((CharLiteral) expr_1).getValue() == ((CharLiteral) expr_2).getValue(); 241 } else if (expr_1 instanceof FloatLiteral) { 242 return ((FloatLiteral) expr_1).getValue() == ((FloatLiteral) expr_2).getValue(); 243 } else if (expr_1 instanceof MultipartId) { 244 NamedElement elem_1 = ((MultipartId) expr_1).getElement(); 245 NamedElement elem_2 = ((MultipartId) expr_2).getElement(); 246 if (!(elem_1 instanceof UnresolvedClass)) { 247 return elem_1 == elem_2; 248 } 249 if (!(elem_2 instanceof UnresolvedClass)) { 250 return false; 251 } 252 return elem_1.getName().equals(elem_2.getName()); 253 } else if (expr_1 instanceof ArrayReference) { 254 if (((ArrayReference) expr_1).getDimCount() != ((ArrayReference) expr_2).getDimCount()) { 255 return false; 256 } 257 NamedElement elem_1 = ((TypeReference) expr_1).getElement(); 258 NamedElement elem_2 = ((TypeReference) expr_2).getElement(); 259 if (!(elem_1 instanceof UnresolvedClass)) { 260 return elem_1 == elem_2; 261 } 262 if (!(elem_2 instanceof UnresolvedClass)) { 263 return false; 264 } 265 return elem_1.getName().equals(elem_2.getName()); 266 } else if (expr_1 instanceof PrefixExpression) { 267 Operator op_1 = ((PrefixExpression) expr_1).getOperator(); 268 Operator op_2 = ((PrefixExpression) expr_2).getOperator(); 269 if (!op_1.equals(op_2)) { 270 return false; 271 } 272 } else if (expr_1 instanceof InfixExpression) { 273 Operator op_1 = ((InfixExpression) expr_1).getOperator(); 274 Operator op_2 = ((InfixExpression) expr_2).getOperator(); 275 if (!op_1.equals(op_2)) { 276 return false; 277 } 278 } else if (expr_1 instanceof MethodInvocation) { 279 String name_1 = ((MethodInvocation) expr_1).getName(); 280 String name_2 = ((MethodInvocation) expr_2).getName(); 281 if (!name_1.equals(name_2)) { 282 return false; 283 } 284 } else if (expr_1 instanceof VariableAccess) { 285 return ((VariableAccess) expr_1).getName().equals(((VariableAccess) expr_2).getName()); 286 } 287 List list_1 = expr_1.getChildren(); 288 List list_2 = expr_2.getChildren(); 289 if (list_1.size() != list_2.size()) { 290 return false; 291 } 292 Iterator iter_1 = list_1.iterator(); 293 Iterator iter_2 = list_2.iterator(); 294 while (iter_1.hasNext()) { 295 if (!compareExpressions((Expression) iter_1.next(), (Expression) iter_2.next())) { 296 return false; 297 } 298 } 299 return true; 300 } 301 302 private static final String getString(String key) { 303 return NbBundle.getMessage(IntroduceVariableRefactoringPlugin.class, key); 304 } 305 306 public void start(org.netbeans.modules.javacore.internalapi.ProgressEvent event) { 307 fireProgressListenerStart(event.getOperationType(), event.getCount()); 308 } 309 310 public void step(org.netbeans.modules.javacore.internalapi.ProgressEvent event) { 311 fireProgressListenerStep(); 312 } 313 314 public void stop(org.netbeans.modules.javacore.internalapi.ProgressEvent event) { 315 fireProgressListenerStop(); 316 } 317 318 private class IntroduceVariableElement extends SimpleRefactoringElementImpl { 320 321 private final String text; 322 private PositionBounds bounds = null; 323 324 private Expression initialExpr; 325 private String name; 326 private Type type; 327 private boolean isFinal; 328 329 public IntroduceVariableElement(Expression expr, String name, Type type, boolean isFinal) { 330 initialExpr = expr; 331 this.name = name; 332 this.type = type; 333 this.isFinal = isFinal; 334 text = MessageFormat.format(getString("TXT_IntroduceVariable"), new Object [] {name}); 335 } 336 337 private BehavioralFeature getMethod() { 338 Element elem = initialExpr; 339 while (!(elem instanceof BehavioralFeature) && (elem != null)) { 340 elem = (Element)elem.refImmediateComposite(); 341 } 342 return (BehavioralFeature)elem; 343 } 344 345 public String getDisplayText() { 346 return text; 347 } 348 349 public Element getJavaElement() { 350 return JavaModelUtil.getDeclaringFeature(initialExpr); 351 } 352 353 public PositionBounds getPosition() { 354 if (bounds == null) { 355 bounds = JavaMetamodel.getManager().getElementPosition(initialExpr); 356 } 357 return null; 358 } 359 360 public String getText() { 361 return getDisplayText(); 362 } 363 364 public void performChange() { 365 BehavioralFeature method = getMethod(); 366 if (method == null) { 367 return; 368 } 369 JavaModelPackage modelPackage = (JavaModelPackage) method.refOutermostPackage(); 370 LocalVarDeclarationClass localVarDeclProxy = modelPackage.getLocalVarDeclaration(); 371 TypeReference typeRef = typeToTypeReference(modelPackage, type); 372 LocalVariableClass localVarProxy = modelPackage.getLocalVariable(); 373 InitialValue initValue = (InitialValue)initialExpr.duplicate(); 374 LocalVariable localVar = localVarProxy.createLocalVariable(name, null, isFinal, typeRef, 0, initValue, null); 375 List varList = new ArrayList(); 376 varList.add(localVar); 377 LocalVarDeclaration localVarDecl = localVarDeclProxy.createLocalVarDeclaration(isFinal, typeRef, varList); 378 method.getBody().getStatements().add(0, localVarDecl); 379 } 380 381 public FileObject getParentFile() { 382 Resource res = getMethod().getResource(); 383 return JavaMetamodel.getManager().getFileObject(res); 384 } 385 386 private TypeReference typeToTypeReference(JavaModelPackage modelPackage, Type type) { 387 if (type instanceof Array) { 388 ArrayReferenceClass arrayProxy = modelPackage.getArrayReference(); 389 int dims = 0; 390 Type elemType = type; 391 while (elemType instanceof Array) { 392 dims++; 393 elemType = ((Array) elemType).getType(); 394 } 395 String name = elemType instanceof JavaClass ? ((JavaClass) elemType).getSimpleName() : elemType.getName(); 396 MultipartId id = modelPackage.getMultipartId().createMultipartId(name, null, null); 397 return arrayProxy.createArrayReference(null, id, dims); 398 } else { 399 MultipartIdClass idProxy = modelPackage.getMultipartId(); 400 String name = type instanceof JavaClass ? ((JavaClass) type).getSimpleName() : type.getName(); 401 return idProxy.createMultipartId(name, null, null); 402 } 403 } 404 405 } 407 private class ReplaceExpressionElement extends SimpleRefactoringElementImpl { 409 410 private final String text; 411 private PositionBounds bounds = null; 412 private Resource res = null; 413 private Expression expression; 414 private String localVarName; 415 416 public ReplaceExpressionElement(Expression expression, String localVarName) { 417 this.expression = expression; 418 this.localVarName = localVarName; 419 text = MessageFormat.format(getString("TXT_ReplaceExpression"), new Object [] {localVarName}); 420 } 421 422 public String getDisplayText() { 423 return text; 424 } 425 426 public Element getJavaElement() { 427 return JavaModelUtil.getDeclaringFeature(expression); 428 } 429 430 public PositionBounds getPosition() { 431 if (bounds == null) { 432 bounds = JavaMetamodel.getManager().getElementPosition(expression); 433 } 434 return bounds; 435 } 436 437 public String getText() { 438 return getDisplayText(); 439 } 440 441 public void performChange() { 442 JavaModelPackage modelPackage = (JavaModelPackage) expression.refOutermostPackage(); 443 VariableAccessClass proxy = modelPackage.getVariableAccess(); 444 VariableAccess varAccess = proxy.createVariableAccess(localVarName, null, false); 445 Element comp = (Element) expression.refImmediateComposite(); 446 comp.replaceChild(expression, varAccess); 447 } 448 449 public FileObject getParentFile() { 450 return JavaMetamodel.getManager().getFileObject(expression.getResource()); 451 } 452 453 } 455 } 456 | Popular Tags |