1 11 package org.eclipse.jdt.internal.corext.refactoring.structure; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Map ; 18 19 import org.eclipse.text.edits.TextEdit; 20 21 import org.eclipse.core.runtime.Assert; 22 import org.eclipse.core.runtime.CoreException; 23 import org.eclipse.core.runtime.IProgressMonitor; 24 import org.eclipse.core.runtime.IStatus; 25 import org.eclipse.core.runtime.OperationCanceledException; 26 import org.eclipse.core.runtime.Status; 27 28 import org.eclipse.jface.text.BadLocationException; 29 import org.eclipse.jface.text.Document; 30 31 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 32 import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments; 33 34 import org.eclipse.jdt.core.ICompilationUnit; 35 import org.eclipse.jdt.core.IJavaElement; 36 import org.eclipse.jdt.core.IJavaProject; 37 import org.eclipse.jdt.core.IMethod; 38 import org.eclipse.jdt.core.IPackageFragment; 39 import org.eclipse.jdt.core.IPackageFragmentRoot; 40 import org.eclipse.jdt.core.JavaModelException; 41 import org.eclipse.jdt.core.NamingConventions; 42 import org.eclipse.jdt.core.ToolFactory; 43 import org.eclipse.jdt.core.compiler.IProblem; 44 import org.eclipse.jdt.core.compiler.IScanner; 45 import org.eclipse.jdt.core.compiler.ITerminalSymbols; 46 import org.eclipse.jdt.core.compiler.InvalidInputException; 47 import org.eclipse.jdt.core.dom.AST; 48 import org.eclipse.jdt.core.dom.ASTNode; 49 import org.eclipse.jdt.core.dom.ASTVisitor; 50 import org.eclipse.jdt.core.dom.ArrayCreation; 51 import org.eclipse.jdt.core.dom.ArrayInitializer; 52 import org.eclipse.jdt.core.dom.ArrayType; 53 import org.eclipse.jdt.core.dom.Block; 54 import org.eclipse.jdt.core.dom.ClassInstanceCreation; 55 import org.eclipse.jdt.core.dom.CompilationUnit; 56 import org.eclipse.jdt.core.dom.Expression; 57 import org.eclipse.jdt.core.dom.ExpressionStatement; 58 import org.eclipse.jdt.core.dom.FieldAccess; 59 import org.eclipse.jdt.core.dom.IBinding; 60 import org.eclipse.jdt.core.dom.IMethodBinding; 61 import org.eclipse.jdt.core.dom.ITypeBinding; 62 import org.eclipse.jdt.core.dom.IVariableBinding; 63 import org.eclipse.jdt.core.dom.Javadoc; 64 import org.eclipse.jdt.core.dom.Message; 65 import org.eclipse.jdt.core.dom.MethodDeclaration; 66 import org.eclipse.jdt.core.dom.Name; 67 import org.eclipse.jdt.core.dom.NullLiteral; 68 import org.eclipse.jdt.core.dom.QualifiedName; 69 import org.eclipse.jdt.core.dom.SimpleName; 70 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 71 import org.eclipse.jdt.core.dom.SuperFieldAccess; 72 import org.eclipse.jdt.core.dom.Type; 73 import org.eclipse.jdt.core.dom.TypeDeclaration; 74 import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; 75 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 76 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; 77 import org.eclipse.jdt.core.dom.rewrite.ListRewrite; 78 79 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 80 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 81 import org.eclipse.jdt.internal.corext.dom.NodeFinder; 82 import org.eclipse.jdt.internal.corext.dom.TokenScanner; 83 import org.eclipse.jdt.internal.corext.dom.TypeBindingVisitor; 84 import org.eclipse.jdt.internal.corext.refactoring.Checks; 85 import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo; 86 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 87 import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker.IProblemVerifier; 88 import org.eclipse.jdt.internal.corext.refactoring.changes.CreateCompilationUnitChange; 89 import org.eclipse.jdt.internal.corext.refactoring.changes.CreatePackageChange; 90 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; 91 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 92 import org.eclipse.jdt.internal.corext.util.Messages; 93 94 import org.eclipse.jdt.ui.CodeGeneration; 95 96 import org.eclipse.jdt.internal.ui.JavaPlugin; 97 import org.eclipse.jdt.internal.ui.text.correction.ASTResolving; 98 99 public class IntroduceParameterObjectRefactoring extends ChangeSignatureRefactoring { 100 101 private final class ParameterObjectCreator implements IDefaultValueAdvisor { 102 public Expression createDefaultExpression(List invocationArguments, ParameterInfo addedInfo, List parameterInfos, 103 MethodDeclaration enclosingMethod, boolean isRecursive, CompilationUnitRewrite cuRewrite) { 104 final AST ast= cuRewrite.getAST(); 105 final ASTRewrite rewrite= cuRewrite.getASTRewrite(); 106 if (isRecursive && canReuseParameterObject(invocationArguments, addedInfo, parameterInfos, enclosingMethod)) { 107 return ast.newSimpleName(addedInfo.getNewName()); 108 } 109 ClassInstanceCreation classCreation= ast.newClassInstanceCreation(); 110 111 int startPosition= enclosingMethod != null ? enclosingMethod.getStartPosition() : cuRewrite.getRoot().getStartPosition(); 112 classCreation.setType(fParameterObjectFactory.createType(fCreateAsTopLevel, cuRewrite, startPosition)); 113 List constructorArguments= classCreation.arguments(); 114 for (Iterator iter= parameterInfos.iterator(); iter.hasNext();) { 115 ParameterInfo pi= (ParameterInfo) iter.next(); 116 if (isValidField(pi)) { 117 if (pi.isOldVarargs()) { 118 boolean isLastParameter= !iter.hasNext(); 119 constructorArguments.addAll(computeVarargs(invocationArguments, pi, isLastParameter, cuRewrite)); 120 } else { 121 Expression exp= (Expression) invocationArguments.get(pi.getOldIndex()); 122 importNodeTypes(exp, cuRewrite); 123 constructorArguments.add(moveNode(exp, rewrite)); 124 } 125 } 126 } 127 return classCreation; 128 } 129 130 public Type createType(String newTypeName, int startPosition, CompilationUnitRewrite cuRewrite) { 131 return fParameterObjectFactory.createType(fCreateAsTopLevel, cuRewrite, startPosition); 132 } 133 134 private boolean canReuseParameterObject(List invocationArguments, ParameterInfo addedInfo, List parameterInfos, 135 MethodDeclaration enclosingMethod) { 136 Assert.isNotNull(enclosingMethod); 137 List parameters= enclosingMethod.parameters(); 138 for (Iterator iter= parameterInfos.iterator(); iter.hasNext();) { 139 ParameterInfo pi= (ParameterInfo) iter.next(); 140 if (isValidField(pi)) { 141 if (!pi.isInlined()) 142 return false; 143 ASTNode node= (ASTNode) invocationArguments.get(pi.getOldIndex()); 144 if (!isParameter(pi, node, parameters, addedInfo.getNewName())) { 145 return false; 146 } 147 } 148 } 149 return true; 150 } 151 152 private List computeVarargs(List invocationArguments, ParameterInfo varArgPI, boolean isLastParameter, CompilationUnitRewrite cuRewrite) { 153 boolean isEmptyVarArg= varArgPI.getOldIndex() >= invocationArguments.size(); 154 ASTRewrite rewrite= cuRewrite.getASTRewrite(); 155 AST ast= cuRewrite.getAST(); 156 ASTNode lastNode= isEmptyVarArg ? null : (ASTNode) invocationArguments.get(varArgPI.getOldIndex()); 157 List constructorArguments= new ArrayList (); 158 if (lastNode instanceof ArrayCreation) { 159 ArrayCreation creation= (ArrayCreation) lastNode; 160 ITypeBinding arrayType= creation.resolveTypeBinding(); 161 if (arrayType != null && arrayType.isAssignmentCompatible(varArgPI.getNewTypeBinding())) { 162 constructorArguments.add(moveNode(creation, rewrite)); 163 return constructorArguments; 164 } 165 } 166 if (isLastParameter) { 167 for (int i= varArgPI.getOldIndex(); i < invocationArguments.size(); i++) { 169 ASTNode node= (ASTNode) invocationArguments.get(i); 170 importNodeTypes(node, cuRewrite); 171 constructorArguments.add(moveNode(node, rewrite)); 172 } 173 } else { if (lastNode instanceof NullLiteral) { 175 NullLiteral nullLiteral= (NullLiteral) lastNode; 176 constructorArguments.add(moveNode(nullLiteral, rewrite)); 177 } else { 178 ArrayCreation creation= ast.newArrayCreation(); 179 creation.setType((ArrayType) importBinding(varArgPI.getNewTypeBinding(), cuRewrite)); 180 ArrayInitializer initializer= ast.newArrayInitializer(); 181 List expressions= initializer.expressions(); 182 for (int i= varArgPI.getOldIndex(); i < invocationArguments.size(); i++) { 183 ASTNode node= (ASTNode) invocationArguments.get(i); 184 importNodeTypes(node, cuRewrite); 185 expressions.add(moveNode(node, rewrite)); 186 } 187 if (expressions.isEmpty()) 188 creation.dimensions().add(ast.newNumberLiteral("0")); else 190 creation.setInitializer(initializer); 191 constructorArguments.add(creation); 192 } 193 } 194 return constructorArguments; 195 } 196 197 public Type importBinding(ITypeBinding newTypeBinding, CompilationUnitRewrite cuRewrite) { 198 Type type= cuRewrite.getImportRewrite().addImport(newTypeBinding, cuRewrite.getAST()); 199 cuRewrite.getImportRemover().registerAddedImports(type); 200 return type; 201 } 202 203 private void importNodeTypes(ASTNode node, final CompilationUnitRewrite cuRewrite) { 204 ASTResolving.visitAllBindings(node, new TypeBindingVisitor() { 205 public boolean visit(ITypeBinding nodeBinding) { 206 importBinding(nodeBinding, cuRewrite); 207 return false; 208 } 209 }); 210 } 211 } 212 213 private boolean isParameter(ParameterInfo pi, ASTNode node, List enclosingMethodParameters, String qualifier) { 214 if (node instanceof Name) { 215 Name name= (Name) node; 216 IVariableBinding binding= ASTNodes.getVariableBinding(name); 217 if (binding != null && binding.isParameter()) { 218 return binding.getName().equals(getNameInScope(pi, enclosingMethodParameters)); 219 } else { 220 if (node instanceof QualifiedName) { 221 QualifiedName qn= (QualifiedName) node; 222 return qn.getFullyQualifiedName().equals(JavaModelUtil.concatenateName(qualifier, getNameInScope(pi, enclosingMethodParameters))); 223 } 224 } 225 } 226 return false; 227 } 228 229 private final class RewriteParameterBody extends BodyUpdater { 230 private boolean fParameterClassCreated= false; 231 232 public void updateBody(MethodDeclaration methodDeclaration, CompilationUnitRewrite cuRewrite, RefactoringStatus result) throws CoreException { 233 fParameterObjectFactory.createType(fCreateAsTopLevel, cuRewrite, methodDeclaration.getStartPosition()); 235 if (cuRewrite.getCu().equals(fCompilationUnit) && !fParameterClassCreated) { 236 createParameterClass(methodDeclaration, cuRewrite); 237 fParameterClassCreated= true; 238 } 239 Block body= methodDeclaration.getBody(); 240 final List parameters= methodDeclaration.parameters(); 241 if (body != null) { final ASTRewrite rewriter= cuRewrite.getASTRewrite(); 243 ListRewrite bodyStatements= rewriter.getListRewrite(body, Block.STATEMENTS_PROPERTY); 244 List managedParams= getParameterInfos(); 245 for (Iterator iter= managedParams.iterator(); iter.hasNext();) { 246 final ParameterInfo pi= (ParameterInfo) iter.next(); 247 if (isValidField(pi)) { 248 if (isReadOnly(pi, body, parameters, null)) { 249 body.accept(new ASTVisitor(false) { 250 251 public boolean visit(SimpleName node) { 252 updateSimpleName(rewriter, pi, node, parameters); 253 return false; 254 } 255 256 }); 257 pi.setInlined(true); 258 } else { 259 ExpressionStatement initializer= fParameterObjectFactory.createInitializer(pi, getParameterName(), cuRewrite); 260 bodyStatements.insertFirst(initializer, null); 261 } 262 } 263 } 264 } 265 266 267 } 268 269 private void updateSimpleName(ASTRewrite rewriter, ParameterInfo pi, SimpleName node, List enclosingParameters) { 270 AST ast= rewriter.getAST(); 271 IBinding binding= node.resolveBinding(); 272 Expression replacementNode= fParameterObjectFactory.createFieldReadAccess(pi, getParameterName(), ast); 273 if (binding instanceof IVariableBinding) { 274 IVariableBinding variable= (IVariableBinding) binding; 275 if (variable.isParameter() && variable.getName().equals(getNameInScope(pi, enclosingParameters))) { 276 rewriter.replace(node, replacementNode, null); 277 } 278 } else { 279 ASTNode parent= node.getParent(); 280 if (! (parent instanceof QualifiedName || parent instanceof FieldAccess || parent instanceof SuperFieldAccess)) { 281 if (node.getIdentifier().equals(getNameInScope(pi, enclosingParameters))) { 282 rewriter.replace(node, replacementNode, null); 283 } 284 } 285 } 286 } 287 288 private boolean isReadOnly(final ParameterInfo pi, Block block, final List enclosingMethodParameters, final String qualifier) { 289 class NotWrittenDetector extends ASTVisitor { 290 boolean notWritten= true; 291 292 public boolean visit(SimpleName node) { 293 if (isParameter(pi, node, enclosingMethodParameters, qualifier) && ASTResolving.isWriteAccess(node)) 294 notWritten= false; 295 return false; 296 } 297 298 public boolean visit(SuperFieldAccess node) { 299 return false; 300 } 301 } 302 NotWrittenDetector visitor= new NotWrittenDetector(); 303 block.accept(visitor); 304 return visitor.notWritten; 305 } 306 307 public boolean needsParameterUsedCheck() { 308 return false; 309 } 310 311 } 312 313 private static final String PARAMETER_CLASS_APPENDIX= "Parameter"; 315 private static final String DEFAULT_PARAMETER_OBJECT_NAME= "parameterObject"; 317 private MethodDeclaration fMethodDeclaration; 318 319 private ICompilationUnit fCompilationUnit; 320 321 private int fOffset; 322 323 private int fLength; 324 325 private ParameterObjectFactory fParameterObjectFactory; 326 327 private boolean fCreateAsTopLevel= true; 328 329 private ParameterInfo fParameterObjectReference; 330 331 public IntroduceParameterObjectRefactoring(IMethod method) throws JavaModelException { 332 super(method); 333 Assert.isNotNull(method); 334 initializeFields(method); 335 setBodyUpdater(new RewriteParameterBody()); 336 setDefaultValueAdvisor(new ParameterObjectCreator()); 337 List parameterInfos= getParameterInfos(); 338 for (Iterator iter= parameterInfos.iterator(); iter.hasNext();) { 339 ParameterInfo pi= (ParameterInfo) iter.next(); 340 if (!pi.isAdded()) { 341 pi.setCreateField(true); 342 pi.setNewName(getFieldName(pi)); 343 } 344 } 345 } 346 347 private void initializeFields(IMethod method) throws JavaModelException { 348 fCompilationUnit= method.getCompilationUnit(); 349 Assert.isNotNull(fCompilationUnit); 350 fOffset= method.getNameRange().getOffset(); 351 fLength= method.getNameRange().getLength(); 352 fParameterObjectFactory= new ParameterObjectFactory(fCompilationUnit); 353 String methodName= method.getElementName(); 354 String className= String.valueOf(Character.toUpperCase(methodName.charAt(0))); 355 if (methodName.length() > 1) 356 className+= methodName.substring(1); 357 className+= PARAMETER_CLASS_APPENDIX; 358 fParameterObjectReference= ParameterInfo.createInfoForAddedParameter(className, DEFAULT_PARAMETER_OBJECT_NAME); 359 fParameterObjectFactory.setClassName(className); 360 fParameterObjectFactory.setPackage(method.getDeclaringType().getPackageFragment().getElementName()); 361 updateReferenceType(); 362 } 363 364 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { 365 RefactoringStatus status= new RefactoringStatus(); 366 status.merge(fParameterObjectFactory.checkConditions()); 367 status.merge(Checks.checkIdentifier(getParameterName())); 368 if (status.hasFatalError()) 369 return status; 370 status.merge(super.checkFinalConditions(pm)); 371 return status; 372 } 373 374 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { 375 RefactoringStatus status= new RefactoringStatus(); 376 status.merge(super.checkInitialConditions(pm)); 377 status.merge(Checks.checkAvailability(fCompilationUnit)); 378 if (status.hasFatalError()) 379 return status; 380 CompilationUnit astRoot= getBaseCuRewrite().getRoot(); 381 ASTNode selectedNode= NodeFinder.perform(astRoot, fOffset, fLength); 382 if (selectedNode == null) { 383 return mappingErrorFound(status, selectedNode); 384 } 385 fMethodDeclaration= (MethodDeclaration) ASTNodes.getParent(selectedNode, MethodDeclaration.class); 386 if (fMethodDeclaration == null) { 387 return mappingErrorFound(status, selectedNode); 388 } 389 IMethodBinding resolveBinding= fMethodDeclaration.resolveBinding(); 390 if (resolveBinding == null) { 391 if (!processCompilerError(status, selectedNode)) 392 status.addFatalError(RefactoringCoreMessages.SelfEncapsulateField_type_not_resolveable); 393 return status; 394 } 395 396 ITypeBinding declaringClass= resolveBinding.getDeclaringClass(); 397 if (fParameterObjectFactory.getPackage() == null) 398 fParameterObjectFactory.setPackage(declaringClass.getPackage().getName()); 399 if (fParameterObjectFactory.getEnclosingType() == null) 400 fParameterObjectFactory.setEnclosingType(declaringClass.getQualifiedName()); 401 402 List parameterInfos= super.getParameterInfos(); 403 if (!parameterInfos.contains(fParameterObjectReference)) { 404 parameterInfos.add(0, fParameterObjectReference); 405 } 406 Map bindingMap= new HashMap (); 407 for (Iterator iter= fMethodDeclaration.parameters().iterator(); iter.hasNext();) { 408 SingleVariableDeclaration sdv= (SingleVariableDeclaration) iter.next(); 409 bindingMap.put(sdv.getName().getIdentifier(), sdv.resolveBinding()); 410 } 411 for (Iterator iter= parameterInfos.iterator(); iter.hasNext();) { 412 ParameterInfo pi= (ParameterInfo) iter.next(); 413 if (pi != fParameterObjectReference) 414 pi.setOldBinding((IVariableBinding) bindingMap.get(pi.getOldName())); 415 } 416 fParameterObjectFactory.setVariables(parameterInfos); 417 return status; 418 } 419 420 protected IProblemVerifier doGetProblemVerifier() { 421 return new IProblemVerifier() { 422 423 public boolean isError(IProblem problem, ASTNode node) { 424 if (node instanceof Type) { 425 Type type= (Type) node; 426 if (problem.getID() == IProblem.UndefinedType && getClassName().equals(ASTNodes.getTypeName(type))) { 427 return false; 428 } 429 } 430 if (node instanceof Name) { 431 Name name= (Name) node; 432 if (problem.getID() == IProblem.ImportNotFound && getPackage().indexOf(name.getFullyQualifiedName()) != -1) 433 return false; 434 } 435 return true; 436 } 437 438 }; 439 } 440 441 public String getClassName() { 442 return fParameterObjectFactory.getClassName(); 443 } 444 445 public ITypeBinding getContainingClass() { 446 return fMethodDeclaration.resolveBinding().getDeclaringClass(); 447 } 448 449 private String getMappingErrorMessage() { 450 return Messages.format(RefactoringCoreMessages.IntroduceParameterObjectRefactoring_cannotalanyzemethod_mappingerror, new String [] {}); 451 } 452 453 public String getFieldName(ParameterInfo element) { 454 String paramName= element.getOldName(); 455 IJavaProject javaProject= fCompilationUnit.getJavaProject(); 456 String stripped= NamingConventions.removePrefixAndSuffixForArgumentName(javaProject, paramName); 457 int dim= element.getNewTypeBinding() != null ? element.getNewTypeBinding().getDimensions() : 0; 458 return StubUtility.getVariableNameSuggestions(StubUtility.INSTANCE_FIELD, javaProject, stripped, dim, null, true)[0]; 459 } 460 461 462 public String getName() { 463 return RefactoringCoreMessages.IntroduceParameterObjectRefactoring_refactoring_name; 464 } 465 466 protected String doGetRefactoringChangeName() { 467 return getName(); 468 } 469 470 public String getParameterName() { 471 return fParameterObjectReference.getNewName(); 472 } 473 474 public RefactoringStatus initialize(RefactoringArguments arguments) { 475 RefactoringStatus refactoringStatus= new RefactoringStatus(); 476 refactoringStatus.merge(super.initialize(arguments)); 477 return refactoringStatus; 478 } 479 480 public boolean isCreateGetter() { 481 return fParameterObjectFactory.isCreateGetter(); 482 } 483 484 public boolean isCreateSetter() { 485 return fParameterObjectFactory.isCreateSetter(); 486 } 487 488 public boolean isCreateAsTopLevel() { 489 return fCreateAsTopLevel; 490 } 491 492 498 private boolean isValidField(ParameterInfo pi) { 499 return pi.isCreateField() & !pi.isAdded(); 500 } 501 502 private RefactoringStatus mappingErrorFound(RefactoringStatus result, ASTNode node) { 503 if (node != null && (node.getFlags() & ASTNode.MALFORMED) != 0 && processCompilerError(result, node)) 504 return result; 505 result.addFatalError(getMappingErrorMessage()); 506 return result; 507 } 508 509 public void moveFieldDown(ParameterInfo selected) { 510 fParameterObjectFactory.moveDown(selected); 511 } 512 513 public void moveFieldUp(ParameterInfo selected) { 514 fParameterObjectFactory.moveUp(selected); 515 } 516 517 private boolean processCompilerError(RefactoringStatus result, ASTNode node) { 518 Message[] messages= ASTNodes.getMessages(node, ASTNodes.INCLUDE_ALL_PARENTS); 519 if (messages.length == 0) 520 return false; 521 result.addFatalError(Messages.format(RefactoringCoreMessages.IntroduceParameterObjectRefactoring_cannotanalysemethod_compilererror, 522 new String [] { messages[0].getMessage() })); 523 return true; 524 } 525 526 public void setClassName(String className) { 527 fParameterObjectFactory.setClassName(className); 528 updateReferenceType(); 529 } 530 531 private void updateReferenceType() { 532 if (fCreateAsTopLevel) 533 fParameterObjectReference.setNewTypeName(JavaModelUtil.concatenateName(fParameterObjectFactory.getPackage(), fParameterObjectFactory 534 .getClassName())); 535 else 536 fParameterObjectReference.setNewTypeName(JavaModelUtil.concatenateName(fParameterObjectFactory.getEnclosingType(), 537 fParameterObjectFactory.getClassName())); 538 } 539 540 public void setCreateComments(boolean selection) { 541 fParameterObjectFactory.setCreateComments(selection); 542 } 543 544 public void setCreateGetter(boolean createGetter) { 545 fParameterObjectFactory.setCreateGetter(createGetter); 546 } 547 548 public void setCreateSetter(boolean createSetter) { 549 fParameterObjectFactory.setCreateSetter(createSetter); 550 } 551 552 public void setPackageName(String packageName) { 553 fParameterObjectFactory.setPackage(packageName); 554 updateReferenceType(); 555 } 556 557 public void setParameterName(String paramName) { 558 this.fParameterObjectReference.setNewName(paramName); 559 } 560 561 public void setCreateAsTopLevel(boolean topLevel) { 562 this.fCreateAsTopLevel= topLevel; 563 updateReferenceType(); 564 } 565 566 public void updateParameterPosition() { 567 fParameterObjectFactory.updateParameterPosition(fParameterObjectReference); 568 } 569 570 private void createParameterClass(MethodDeclaration methodDeclaration, CompilationUnitRewrite cuRewrite) throws CoreException { 571 if (fCreateAsTopLevel) { 572 IJavaProject javaProject= fCompilationUnit.getJavaProject(); 573 IPackageFragment packageFragment= getPackageFragmentRoot().getPackageFragment(fParameterObjectFactory.getPackage()); 574 if (!packageFragment.exists()) { 575 fOtherChanges.add(new CreatePackageChange(packageFragment)); 576 } 577 578 ICompilationUnit unit= packageFragment.getCompilationUnit(fParameterObjectFactory.getClassName() + ".java"); Assert.isTrue(!unit.exists()); 580 createTopLevelParameterObject(javaProject, unit); 581 } else { 582 ASTRewrite rewriter= cuRewrite.getASTRewrite(); 583 TypeDeclaration enclosingType= (TypeDeclaration) methodDeclaration.getParent(); 584 ListRewrite bodyRewrite= rewriter.getListRewrite(enclosingType, TypeDeclaration.BODY_DECLARATIONS_PROPERTY); 585 TypeDeclaration classDeclaration= fParameterObjectFactory.createClassDeclaration(fCompilationUnit, enclosingType.getName() 586 .getFullyQualifiedName(), cuRewrite); 587 classDeclaration.modifiers().add(rewriter.getAST().newModifier(ModifierKeyword.PUBLIC_KEYWORD)); 588 classDeclaration.modifiers().add(rewriter.getAST().newModifier(ModifierKeyword.STATIC_KEYWORD)); 589 bodyRewrite.insertBefore(classDeclaration, methodDeclaration, null); 590 } 591 } 592 593 private void createTopLevelParameterObject(IJavaProject javaProject, ICompilationUnit unit) throws JavaModelException, CoreException { 594 ICompilationUnit workingCopy= unit.getWorkingCopy(null); 595 596 try { 597 String lineDelimiter= StubUtility.getLineDelimiterUsed(javaProject); 599 String fileComment= getFileComment(workingCopy, lineDelimiter); 600 String typeComment= getTypeComment(workingCopy, lineDelimiter); 601 String content= CodeGeneration.getCompilationUnitContent(workingCopy, fileComment, typeComment, 602 "class " + getClassName() + "{}", lineDelimiter); workingCopy.getBuffer().setContents(content); 604 605 CompilationUnitRewrite cuRewrite= new CompilationUnitRewrite(workingCopy); 606 ASTRewrite rewriter= cuRewrite.getASTRewrite(); 607 CompilationUnit root= cuRewrite.getRoot(); 608 AST ast= cuRewrite.getAST(); 609 ImportRewrite importRewrite= cuRewrite.getImportRewrite(); 610 611 ListRewrite types= rewriter.getListRewrite(root, CompilationUnit.TYPES_PROPERTY); 613 ASTNode dummyType= (ASTNode) types.getOriginalList().get(0); 614 String newTypeName= JavaModelUtil.concatenateName(fParameterObjectFactory.getPackage(), fParameterObjectFactory.getClassName()); 615 TypeDeclaration classDeclaration= fParameterObjectFactory.createClassDeclaration(workingCopy, newTypeName, cuRewrite); 616 classDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); 617 Javadoc javadoc= (Javadoc) dummyType.getStructuralProperty(TypeDeclaration.JAVADOC_PROPERTY); 618 rewriter.set(classDeclaration, TypeDeclaration.JAVADOC_PROPERTY, javadoc, null); 619 types.replace(dummyType, classDeclaration, null); 620 621 String charset= ResourceUtil.getFile(fCompilationUnit).getCharset(false); 625 Document document= new Document(content); 626 try { 627 rewriter.rewriteAST().apply(document); 628 TextEdit rewriteImports= importRewrite.rewriteImports(null); 629 rewriteImports.apply(document); 630 } catch (BadLocationException e) { 631 throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), 632 RefactoringCoreMessages.IntroduceParameterObjectRefactoring_parameter_object_creation_error, e)); 633 } 634 String docContent= document.get(); 635 CreateCompilationUnitChange compilationUnitChange= new CreateCompilationUnitChange(unit, docContent, charset); 636 fOtherChanges.add(compilationUnitChange); 637 } finally { 638 workingCopy.discardWorkingCopy(); 639 } 640 } 641 642 public IPackageFragmentRoot getPackageFragmentRoot() { 643 return (IPackageFragmentRoot) fCompilationUnit.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); 644 } 645 646 protected String getFileComment(ICompilationUnit parentCU, String lineDelimiter) throws CoreException { 647 if (fParameterObjectFactory.isCreateComments()) { 648 return CodeGeneration.getFileComment(parentCU, lineDelimiter); 649 } 650 return null; 651 652 } 653 654 protected String getTypeComment(ICompilationUnit parentCU, String lineDelimiter) throws CoreException { 655 if (fParameterObjectFactory.isCreateComments()) { 656 StringBuffer typeName= new StringBuffer (); 657 typeName.append(fParameterObjectFactory.getClassName()); 658 String [] typeParamNames= new String [0]; 659 String comment= CodeGeneration.getTypeComment(parentCU, typeName.toString(), typeParamNames, lineDelimiter); 660 if (comment != null && isValidComment(comment)) { 661 return comment; 662 } 663 } 664 return null; 665 } 666 667 private boolean isValidComment(String template) { 668 IScanner scanner= ToolFactory.createScanner(true, false, false, false); 669 scanner.setSource(template.toCharArray()); 670 try { 671 int next= scanner.getNextToken(); 672 while (TokenScanner.isComment(next)) { 673 next= scanner.getNextToken(); 674 } 675 return next == ITerminalSymbols.TokenNameEOF; 676 } catch (InvalidInputException e) { 677 } 678 return false; 679 } 680 681 public String getPackage() { 682 return fParameterObjectFactory.getPackage(); 683 } 684 685 public void setPackage(String typeQualifier) { 686 fParameterObjectFactory.setPackage(typeQualifier); 687 } 688 689 public ICompilationUnit getCompilationUnit() { 690 return fCompilationUnit; 691 } 692 693 private String getNameInScope(ParameterInfo pi, List enclosingMethodParameters) { 694 Assert.isNotNull(enclosingMethodParameters); 695 boolean emptyVararg= pi.getOldIndex() >= enclosingMethodParameters.size(); 696 if (!emptyVararg) { 697 SingleVariableDeclaration svd= (SingleVariableDeclaration) enclosingMethodParameters.get(pi.getOldIndex()); 698 return svd.getName().getIdentifier(); 699 } 700 return null; 701 } 702 703 public String getNewTypeName() { 704 return fParameterObjectReference.getNewTypeName(); 705 } 706 707 } 708 | Popular Tags |