1 11 package org.eclipse.jdt.internal.corext.refactoring.structure; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import org.eclipse.text.edits.ReplaceEdit; 23 import org.eclipse.text.edits.TextEdit; 24 25 import org.eclipse.core.runtime.CoreException; 26 import org.eclipse.core.runtime.IProgressMonitor; 27 import org.eclipse.core.runtime.OperationCanceledException; 28 import org.eclipse.core.runtime.SubProgressMonitor; 29 30 import org.eclipse.jdt.core.ICompilationUnit; 31 import org.eclipse.jdt.core.IField; 32 import org.eclipse.jdt.core.IJavaElement; 33 import org.eclipse.jdt.core.IJavaProject; 34 import org.eclipse.jdt.core.IMember; 35 import org.eclipse.jdt.core.IMethod; 36 import org.eclipse.jdt.core.ISourceRange; 37 import org.eclipse.jdt.core.IType; 38 import org.eclipse.jdt.core.IWorkingCopy; 39 import org.eclipse.jdt.core.JavaModelException; 40 import org.eclipse.jdt.core.ToolFactory; 41 import org.eclipse.jdt.core.WorkingCopyOwner; 42 import org.eclipse.jdt.core.compiler.IProblem; 43 import org.eclipse.jdt.core.compiler.IScanner; 44 import org.eclipse.jdt.core.compiler.ITerminalSymbols; 45 import org.eclipse.jdt.core.dom.ASTNode; 46 import org.eclipse.jdt.core.dom.ArrayAccess; 47 import org.eclipse.jdt.core.dom.ArrayCreation; 48 import org.eclipse.jdt.core.dom.ArrayType; 49 import org.eclipse.jdt.core.dom.CompilationUnit; 50 import org.eclipse.jdt.core.dom.Expression; 51 import org.eclipse.jdt.core.dom.FieldDeclaration; 52 import org.eclipse.jdt.core.dom.IBinding; 53 import org.eclipse.jdt.core.dom.IMethodBinding; 54 import org.eclipse.jdt.core.dom.ITypeBinding; 55 import org.eclipse.jdt.core.dom.IVariableBinding; 56 import org.eclipse.jdt.core.dom.MethodDeclaration; 57 import org.eclipse.jdt.core.dom.Type; 58 import org.eclipse.jdt.core.dom.TypeDeclaration; 59 import org.eclipse.jdt.core.dom.VariableDeclaration; 60 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 61 import org.eclipse.jdt.core.search.IJavaSearchConstants; 62 import org.eclipse.jdt.core.search.IJavaSearchScope; 63 import org.eclipse.jdt.core.search.SearchPattern; 64 65 import org.eclipse.jface.text.Document; 66 67 import org.eclipse.jdt.internal.corext.Assert; 68 import org.eclipse.jdt.internal.corext.SourceRange; 69 import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; 70 import org.eclipse.jdt.internal.corext.codemanipulation.ImportRewrite; 71 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 72 import org.eclipse.jdt.internal.corext.dom.Bindings; 73 import org.eclipse.jdt.internal.corext.dom.TokenScanner; 74 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; 75 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine; 76 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; 77 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext; 78 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility; 79 import org.eclipse.jdt.internal.corext.refactoring.rename.RefactoringScopeFactory; 80 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ASTCreator; 81 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange; 82 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompositeOrTypeConstraint; 83 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintCollector; 84 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintOperator; 85 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariable; 86 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariableFactory; 87 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.DeclaringTypeVariable; 88 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ExpressionVariable; 89 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.FullConstraintCreator; 90 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ITypeConstraint; 91 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ParameterTypeVariable; 92 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.RawBindingVariable; 93 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ReturnTypeVariable; 94 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.SimpleTypeConstraint; 95 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeBindings; 96 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeConstraintFactory; 97 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeVariable; 98 import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; 99 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 100 import org.eclipse.jdt.internal.corext.util.WorkingCopyUtil; 101 102 import org.eclipse.jdt.internal.ui.JavaPlugin; 103 104 import org.eclipse.jdt.ui.JavaUI; 105 106 import org.eclipse.ltk.core.refactoring.DocumentChange; 107 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 108 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; 109 import org.eclipse.ltk.core.refactoring.TextChange; 110 111 class ExtractInterfaceUtil { 112 113 private final ICompilationUnit fInputTypeWorkingCopy; 114 private final ICompilationUnit fSupertypeWorkingCopy; private final WorkingCopyOwner fWorkingCopyOwner; 116 private static ICompilationUnit fCu; 117 private final IType fInputType; 118 119 private ExtractInterfaceUtil(ICompilationUnit inputTypeWorkingCopy, ICompilationUnit supertypeWorkingCopy, WorkingCopyOwner workingCopyOwner, IType inputType){ 120 Assert.isNotNull(inputTypeWorkingCopy); 121 fSupertypeWorkingCopy= supertypeWorkingCopy; 122 fInputTypeWorkingCopy= inputTypeWorkingCopy; 123 fWorkingCopyOwner= workingCopyOwner; 124 fInputType= inputType; 125 } 126 127 private static ConstraintVariable[] getAllOfType(ITypeConstraint[] constraints, ITypeBinding binding){ 128 Set result= new HashSet (); 129 ITypeBinding typeBinding= binding; 130 for (int i= 0; i < constraints.length; i++) { 131 ITypeConstraint constraint= constraints[i]; 132 if (constraint.isSimpleTypeConstraint()){ 133 SimpleTypeConstraint simple= (SimpleTypeConstraint)constraint; 134 if (simple.getLeft().isEqualBinding(typeBinding)) 135 result.add(simple.getLeft()); 136 if (simple.getRight().isEqualBinding(typeBinding)) 137 result.add(simple.getRight()); 138 139 if (simple.getRight().getBinding() != null && simple.getRight().getBinding().isArray() && Bindings.equals(simple.getRight().getBinding().getElementType(), typeBinding)) 140 result.add(simple.getRight()); 141 if (simple.getLeft().getBinding() != null && simple.getLeft().getBinding().isArray() && Bindings.equals(simple.getLeft().getBinding().getElementType(), typeBinding)) 142 result.add(simple.getLeft()); 143 144 } else { 145 CompositeOrTypeConstraint cotc= (CompositeOrTypeConstraint)constraint; 146 result.addAll(Arrays.asList(getAllOfType(cotc.getConstraints(), binding))); 147 } 148 } 149 return (ConstraintVariable[]) result.toArray(new ConstraintVariable[result.size()]); 150 } 151 152 private ConstraintVariable[] getUpdatableVariables(ITypeBinding inputTypeBinding, IType theType, IType theSupertype, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException{ 153 ITypeBinding interfaceBinding= getSuperTypeBinding(inputTypeBinding, theSupertype); 154 ICompilationUnit[] referringCus= getCusToParse(theType, theSupertype, pm, status); 155 checkCompileErrors(referringCus, status); 156 if (status.hasFatalError()) 157 return new ConstraintVariable[0]; 158 ITypeConstraint[] constraints= getConstraints(referringCus); 159 return getUpdatableVariables(constraints, inputTypeBinding, interfaceBinding); 160 } 161 162 private void checkCompileErrors(ICompilationUnit[] referringCus, RefactoringStatus status) throws JavaModelException { 163 for (int i= 0; i < referringCus.length; i++) { 164 ICompilationUnit unit= referringCus[i]; 165 String source= unit.getSource(); 166 CompilationUnit cuNode= getAST(unit); 167 IProblem[] problems= ASTNodes.getProblems(cuNode, ASTNodes.INCLUDE_ALL_PARENTS, ASTNodes.ERROR); 168 for (int j= 0; j < problems.length; j++) { 169 IProblem problem= problems[j]; 170 if (problem.isError()) { 171 RefactoringStatusContext context= new JavaStringStatusContext(source, new SourceRange(problem)); 172 status.addFatalError(problem.getMessage(), context); 173 } 174 } 175 } 176 } 177 178 private static ITypeBinding getSuperTypeBinding(ITypeBinding typeBinding, IType superType) { 179 Set setOfAll= TypeBindings.getSuperTypes(typeBinding); 180 181 setOfAll.add(ASTCreator.createAST(fCu, null).getAST().resolveWellKnownType("java.lang.Object")); 184 185 ITypeBinding[] all= (ITypeBinding[]) setOfAll.toArray(new ITypeBinding[setOfAll.size()]); 186 for (int i= 0; i < all.length; i++) { 187 ITypeBinding superTypeBinding= all[i]; 188 if (isBindingForType(superTypeBinding, superType)) 189 return superTypeBinding; 190 } 191 return null; 192 } 193 194 private static boolean isBindingForType(ITypeBinding typeBinding, IType type) { 195 if (! typeBinding.getName().equals(type.getElementName())) 196 return false; 197 if (typeBinding.getPackage().isUnnamed() != type.getPackageFragment().isDefaultPackage()) 199 return false; 200 if (! typeBinding.getPackage().isUnnamed() && !type.getPackageFragment().isDefaultPackage()){ 201 if (! typeBinding.getPackage().getName().equals(type.getPackageFragment().getElementName())) 202 return false; 203 } 204 return true; 205 } 206 207 public static CompilationUnitRange[] updateReferences(TextChangeManager manager, IType inputType, IType supertypeToUse, WorkingCopyOwner workingCopyOwner, boolean updateInputTypeCu, IProgressMonitor pm, RefactoringStatus status, CodeGenerationSettings settings) throws CoreException{ 208 ICompilationUnit typeWorkingCopy= inputType.getCompilationUnit(); 209 fCu= typeWorkingCopy; 210 ExtractInterfaceUtil inst= new ExtractInterfaceUtil(typeWorkingCopy, supertypeToUse.getCompilationUnit(), workingCopyOwner, inputType); 211 ITypeBinding inputTypeBinding= getTypeBinding(inputType, workingCopyOwner); 212 ConstraintVariable[] updatableVars= inst.getUpdatableVariables(inputTypeBinding, inputType, supertypeToUse, pm, status); 213 if (status.hasFatalError()) 214 return new CompilationUnitRange[0]; 215 String typeName= inputType.getElementName(); 216 CompilationUnitRange[] ranges= inst.getCompilationUnitRanges(updatableVars, inputType, inputTypeBinding); 217 Set cus= new HashSet (); 218 Map cuToImportType= new HashMap (); 219 for (int i= 0; i < ranges.length; i++) { 220 if (pm.isCanceled()) 221 throw new OperationCanceledException(); 222 CompilationUnitRange range= ranges[i]; 223 ICompilationUnit cu= range.getCompilationUnit(); 224 if (updateInputTypeCu || ! cu.equals(typeWorkingCopy)){ 225 TextChange change= getTextChange(manager, cu); 226 if (!cus.contains(cu)) { 227 cus.add(cu); 228 ImportRewrite importRewrite= new ImportRewrite(cu); 229 cuToImportType.put(cu, importRewrite.addImport(supertypeToUse.getFullyQualifiedName())); 230 TextEdit importEdit= importRewrite.createEdit(new Document(cu.getSource())); 231 TextChangeCompatibility.addTextEdit( 232 change, 233 RefactoringCoreMessages.getString("ExtractInterfaceUtil.update_imports"), importEdit); } 235 TextChangeCompatibility.addTextEdit(change, 236 RefactoringCoreMessages.getString("ExtractInterfaceUtil.update_reference"), createTypeUpdateEdit(range.getSourceRange(), typeName, (String )cuToImportType.get(cu))); 238 } 239 } 240 return ranges; 241 } 242 243 public static TextChange getTextChange(TextChangeManager manager, ICompilationUnit cu) throws CoreException { 244 if (manager.containsChangesIn(cu) || cu.getResource().exists()) 246 return manager.get(cu); 247 DocumentChange result= new DocumentChange(cu.getElementName(), new Document(cu.getSource())); 248 manager.manage(cu, result); 249 return result; 250 } 251 252 private static TextEdit createTypeUpdateEdit(ISourceRange sourceRange, String className, String interfaceName) { 253 int offset= sourceRange.getOffset() + sourceRange.getLength() - className.length(); 254 return new ReplaceEdit(offset, className.length(), interfaceName); 255 } 256 257 private static ConstraintVariable[] getUpdatableVariables(ITypeConstraint[] constraints, ITypeBinding classBinding, ITypeBinding interfaceBinding){ 258 Set allVariablesOfType= new HashSet (Arrays.asList(getAllOfType(constraints, classBinding))); 259 Set badVariables= new HashSet (); 260 Set badConstraints= new HashSet (); 261 ConstraintVariable[] initialBad= getInitialBad(allVariablesOfType, badVariables, badConstraints, constraints, interfaceBinding); 262 if (initialBad == null || initialBad.length == 0) return (ConstraintVariable[]) allVariablesOfType.toArray(new ConstraintVariable[allVariablesOfType.size()]); 264 badVariables.addAll(Arrays.asList(initialBad)); 265 boolean repeat= false; 266 do{ 267 int sizeOfBad= badVariables.size(); 269 for (int i= 0; i < constraints.length; i++) { 270 ITypeConstraint constraint= constraints[i]; 271 if(! constraint.isSimpleTypeConstraint()) 272 continue; 273 SimpleTypeConstraint con= (SimpleTypeConstraint)constraint; 274 ConstraintVariable left= con.getLeft(); 275 ConstraintVariable right= con.getRight(); 276 if (allVariablesOfType.contains(left) && badVariables.contains(right) && ! badVariables.contains(left)) 277 badVariables.add(left); 278 if (con.isEqualsConstraint() || con.isDefinesConstraint()){ 279 if (allVariablesOfType.contains(right) && badVariables.contains(left) && ! badVariables.contains(right)) 280 badVariables.add(right); 281 } 282 } 283 repeat= sizeOfBad < badVariables.size(); 284 } while(repeat); 285 Set updatable= new HashSet (allVariablesOfType); 286 updatable.removeAll(badVariables); 287 return (ConstraintVariable[]) updatable.toArray(new ConstraintVariable[updatable.size()]); 288 } 289 290 private static ConstraintVariable[] getInitialBad(Set setOfAll, Set badVariables, Set badConstraints, ITypeConstraint[] constraints, ITypeBinding interfaceBinding){ 291 ConstraintVariable interfaceVariable= new RawBindingVariable(interfaceBinding); 292 for (int i= 0; i < constraints.length; i++) { 293 ITypeConstraint constraint= constraints[i]; 294 if (constraint.isSimpleTypeConstraint()){ 295 SimpleTypeConstraint simple= (SimpleTypeConstraint)constraint; 296 if (simple.isSubtypeConstraint() && canAddLeftSideToInitialBadSet(simple, setOfAll, interfaceVariable)) { 297 badVariables.add(simple.getLeft()); 298 badConstraints.add(simple); 299 } 300 } else if (constraint instanceof CompositeOrTypeConstraint){ 301 ITypeConstraint[] subConstraints= ((CompositeOrTypeConstraint)constraint).getConstraints(); 302 if (canAddLeftSideToInitialBadSet(subConstraints, setOfAll, interfaceVariable)) { 303 badVariables.add(((SimpleTypeConstraint)subConstraints[0]).getLeft()); 304 badConstraints.add(subConstraints[0]); 305 badConstraints.add(constraint); 306 } 307 } 308 } 309 return (ConstraintVariable[]) badVariables.toArray(new ConstraintVariable[badVariables.size()]); 310 } 311 312 private static boolean canAddLeftSideToInitialBadSet(SimpleTypeConstraint sc, Set setOfAll, ConstraintVariable interfaceVariable) { 313 ConstraintVariable left= sc.getLeft(); 314 ConstraintVariable right= sc.getRight(); 315 if (! (left instanceof ExpressionVariable) && ! (left instanceof TypeVariable)) 316 return false; 317 else if (! setOfAll.contains(left)) 318 return false; 319 else if (interfaceVariable.isSubtypeOf(right)) 320 return false; 321 else if (setOfAll.contains(right) && ! (right instanceof DeclaringTypeVariable)) 323 return false; 324 else if (right instanceof DeclaringTypeVariable && right.getBinding() == null) 325 return false; else 327 return true; 328 } 329 330 private static boolean canAddLeftSideToInitialBadSet(ITypeConstraint[] subConstraints, Set setOfAll, ConstraintVariable interfaceVariable) { 331 if (subConstraints.length == 0) 332 return false; 333 if (! allAreSimpleConstraints(subConstraints)) 334 return false; 335 336 SimpleTypeConstraint[] simpleTypeConstraints= toSimpleConstraintArray(subConstraints); 337 if (! allHaveSameLeftSide(simpleTypeConstraints)) 338 return false; 339 340 ConstraintVariable left= (simpleTypeConstraints[0]).getLeft(); 341 if (! (left instanceof ExpressionVariable)) 342 return false; 343 if (! setOfAll.contains(left)) 344 return false; 345 if (rightSideIsSubtypeOf(simpleTypeConstraints, interfaceVariable)) 346 return false; 347 return true; 348 } 349 350 private static boolean rightSideIsSubtypeOf(SimpleTypeConstraint[] simpleTypeConstraints, ConstraintVariable interfaceVariable) { 351 for (int i= 0; i < simpleTypeConstraints.length; i++) { 352 ConstraintVariable right= simpleTypeConstraints[i].getRight(); 353 if (right.isSubtypeOf(interfaceVariable)) 354 return true; 355 } 356 return false; 357 } 358 359 private static SimpleTypeConstraint[] toSimpleConstraintArray(ITypeConstraint[] subConstraints) { 360 List result= Arrays.asList(subConstraints); 361 return (SimpleTypeConstraint[]) result.toArray(new SimpleTypeConstraint[result.size()]); 362 } 363 364 private static boolean allAreSimpleConstraints(ITypeConstraint[] subConstraints) { 365 for (int i= 0; i < subConstraints.length; i++) { 366 if (! subConstraints[i].isSimpleTypeConstraint()) 367 return false; 368 } 369 return true; 370 } 371 372 private static boolean allHaveSameLeftSide(SimpleTypeConstraint[] constraints) { 373 Assert.isTrue(constraints.length > 0); 374 ConstraintVariable first= constraints[0].getLeft(); 375 for (int i= 1; i < constraints.length; i++) { 376 if (! first.equals(constraints[i].getLeft())) 377 return false; 378 } 379 return true; 380 } 381 382 private ITypeConstraint[] getConstraints(ICompilationUnit[] referringCus) { 383 Set result= new HashSet (); 384 ConstraintCollector collector= new ConstraintCollector(new ExtractInterfaceConstraintCreator(fInputType)); 385 386 for (int i= 0; i < referringCus.length; i++) { 387 ICompilationUnit unit= referringCus[i]; 388 getAST(unit).accept(collector); 389 result.addAll(Arrays.asList(collector.getConstraints())); 390 collector.clear(); 391 } 392 return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]); 393 } 394 395 private CompilationUnit getAST(ICompilationUnit unit) { 396 return ASTCreator.createAST(unit, fWorkingCopyOwner); 397 } 398 399 403 private ICompilationUnit[] getCusToParse(IType theType, IType theSupertype, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException{ 404 try{ 405 pm.beginTask("", 2); SearchPattern pattern= SearchPattern.createPattern(theType, IJavaSearchConstants.REFERENCES); 407 IJavaSearchScope scope= RefactoringScopeFactory.create(theType); 408 ICompilationUnit[] workingCopies= getWorkingCopies(theType.getCompilationUnit(), theSupertype.getCompilationUnit()); 409 if (workingCopies.length == 0) 410 workingCopies= null; 411 SearchResultGroup[] typeReferences= RefactoringSearchEngine.search(pattern, scope, new SubProgressMonitor(pm, 1), workingCopies, status); 412 ICompilationUnit[] typeReferencingCus= getCus(typeReferences); 413 ICompilationUnit[] fieldAndMethodReferencingCus= fieldAndMethodReferringCus(theType, typeReferences, workingCopies, new SubProgressMonitor(pm, 1), status); 414 return merge(fieldAndMethodReferencingCus, typeReferencingCus); 415 } finally{ 416 pm.done(); 417 } 418 } 419 420 private ASTNode[] getAstNodes(SearchResultGroup searchResultGroup) { 421 ICompilationUnit cu= searchResultGroup.getCompilationUnit(); 422 if (cu == null) 423 return new ASTNode[0]; 424 CompilationUnit cuNode= getAST(cu); 425 return ASTNodeSearchUtil.getAstNodes(searchResultGroup.getSearchResults(), cuNode); 426 } 427 428 private ICompilationUnit[] fieldAndMethodReferringCus(IType theType, SearchResultGroup[] typeReferences, ICompilationUnit[] wcs, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException { 429 SearchPattern pattern= createPatternForReferencingFieldsAndMethods(typeReferences); 430 if (pattern == null) 431 return new ICompilationUnit[0]; 432 IJavaSearchScope scope= RefactoringScopeFactory.create(theType); 433 ICompilationUnit[] units= RefactoringSearchEngine.findAffectedCompilationUnits(pattern, scope, pm, status); 434 Set result= new HashSet (units.length); 435 for (int i= 0; i < units.length; i++) { 436 result.add(getUnproceededElement(units[i], wcs)); 437 } 438 return (ICompilationUnit[]) result.toArray(new ICompilationUnit[result.size()]); 439 } 440 441 private static ICompilationUnit getUnproceededElement(ICompilationUnit unit, ICompilationUnit[] wcs) { 442 if (wcs == null) 443 return unit; 444 for (int i= 0; i < wcs.length; i++) { 445 if (proceeds(wcs[i], unit)) 446 return wcs[i]; 447 } 448 return unit; 449 } 450 451 private static boolean proceeds(ICompilationUnit wc, ICompilationUnit unit) { 452 return wc.getResource() == null || wc.getResource().equals(unit.getResource()); 453 } 454 455 private SearchPattern createPatternForReferencingFieldsAndMethods(SearchResultGroup[] typeReferences) throws JavaModelException { 456 return RefactoringSearchEngine.createOrPattern(getReferencingFieldsAndMethods(typeReferences), IJavaSearchConstants.ALL_OCCURRENCES); 457 } 458 459 private IMethod[] getReferencingMethods(ASTNode[] typeReferenceNodes) throws JavaModelException { 460 List result= new ArrayList (); 461 for (int i= 0; i < typeReferenceNodes.length; i++) { 462 ASTNode node= typeReferenceNodes[i]; 463 IJavaProject scope= ASTCreator.getCu(node).getJavaProject(); 464 IMethod method= getMethod(node, scope); 465 if (method != null) 466 result.add(method); 467 } 468 return (IMethod[]) result.toArray(new IMethod[result.size()]); 469 } 470 471 private IField[] getReferencingFields(ASTNode[] typeReferenceNodes) throws JavaModelException { 472 List result= new ArrayList (); 473 for (int i= 0; i < typeReferenceNodes.length; i++) { 474 ASTNode node= typeReferenceNodes[i]; 475 IJavaProject scope= ASTCreator.getCu(node).getJavaProject(); 476 result.addAll(Arrays.asList(getFields(node, scope))); 477 } 478 return (IField[]) result.toArray(new IField[result.size()]); 479 } 480 481 private IMember[] getReferencingFieldsAndMethods(SearchResultGroup[] typeReferences) throws JavaModelException { 482 List result= new ArrayList (); 483 for (int i= 0; i < typeReferences.length; i++) { 484 SearchResultGroup group= typeReferences[i]; 485 ASTNode[] typeReferenceNodes= getAstNodes(group); 486 result.addAll(Arrays.asList(getReferencingMethods(typeReferenceNodes))); 487 result.addAll(Arrays.asList(getReferencingFields(typeReferenceNodes))); 488 } 489 return (IMember[]) result.toArray(new IMember[result.size()]); 490 } 491 492 private static IMethod getMethod(ASTNode node, IJavaProject scope) throws JavaModelException { 493 if (node instanceof Type && node.getParent() instanceof MethodDeclaration){ 494 MethodDeclaration declaration= (MethodDeclaration)node.getParent(); 495 IMethodBinding binding= declaration.resolveBinding(); 496 if (binding != null) 497 return Bindings.findMethod(binding, scope); 498 } else if (node instanceof Type && isMethodParameter(node.getParent())){ 499 MethodDeclaration declaration= (MethodDeclaration)node.getParent().getParent(); 500 IMethodBinding binding= declaration.resolveBinding(); 501 if (binding != null) 502 return Bindings.findMethod(binding, scope); 503 } 504 return null; 505 } 506 507 private static boolean isMethodParameter(ASTNode node){ 508 return (node instanceof VariableDeclaration) && 509 (node.getParent() instanceof MethodDeclaration) && 510 ((MethodDeclaration)node.getParent()).parameters().contains(node); 511 } 512 513 private static IField[] getFields(ASTNode node, IJavaProject scope) throws JavaModelException { 514 if (node instanceof Type && node.getParent() instanceof FieldDeclaration){ 515 FieldDeclaration parent= (FieldDeclaration)node.getParent(); 516 if (parent.getType() == node){ 517 List result= new ArrayList (parent.fragments().size()); 518 for (Iterator iter= parent.fragments().iterator(); iter.hasNext();) { 519 VariableDeclarationFragment fragment= (VariableDeclarationFragment) iter.next(); 520 IField field= getField(fragment, scope); 521 if (field != null) 522 result.add(field); 523 } 524 return (IField[]) result.toArray(new IField[result.size()]); 525 } 526 } 527 return new IField[0]; 528 } 529 530 private static IField getField(VariableDeclarationFragment fragment, IJavaProject in) throws JavaModelException { 531 IBinding binding= fragment.getName().resolveBinding(); 532 if (! (binding instanceof IVariableBinding)) 533 return null; 534 IVariableBinding variableBinding= (IVariableBinding)binding; 535 if (! variableBinding.isField()) 536 return null; 537 return Bindings.findField(variableBinding, in); 538 } 539 540 private static ICompilationUnit[] merge(ICompilationUnit[] array1, ICompilationUnit[] array2){ 541 Set result= new HashSet (); 542 result.addAll(Arrays.asList(array1)); 543 result.addAll(Arrays.asList(array2)); 544 return (ICompilationUnit[]) result.toArray(new ICompilationUnit[result.size()]); 545 } 546 547 private static ICompilationUnit[] getCus(SearchResultGroup[] groups) { 548 List result= new ArrayList (groups.length); 549 for (int i= 0; i < groups.length; i++) { 550 SearchResultGroup group= groups[i]; 551 ICompilationUnit cu= group.getCompilationUnit(); 552 if (cu != null) 553 result.add(WorkingCopyUtil.getWorkingCopyIfExists(cu)); 554 } 555 return (ICompilationUnit[]) result.toArray(new ICompilationUnit[result.size()]); 556 } 557 558 private static ICompilationUnit[] getWorkingCopies(ICompilationUnit precedingWC1, ICompilationUnit precedingWC2) { 559 if (JavaPlugin.USE_WORKING_COPY_OWNERS) { 560 ArrayList result= new ArrayList (2); 561 if (precedingWC1 != null && precedingWC1.isWorkingCopy()) { 562 result.add(precedingWC1); 563 } 564 if (precedingWC2 != null && precedingWC2.isWorkingCopy()) { 565 result.add(precedingWC2); 566 } 567 return (ICompilationUnit[]) result.toArray(new ICompilationUnit[result.size()]); 568 } 569 570 571 IWorkingCopy[] copies= JavaUI.getSharedWorkingCopiesOnClasspath(); 573 Set result= new HashSet (copies.length); 574 ICompilationUnit original1= null, original2= null; 575 if (precedingWC1 != null && precedingWC1.isWorkingCopy()) { 576 result.add(precedingWC1); 577 original1= precedingWC1.getPrimary(); 578 } 579 if (precedingWC2 != null && precedingWC2.isWorkingCopy()) { 580 result.add(precedingWC2); 581 original2= precedingWC2.getPrimary(); 582 } 583 for (int i= 0; i < copies.length; i++) { 584 IWorkingCopy copy= copies[i]; 585 if (copy.isWorkingCopy() && copy instanceof ICompilationUnit){ 586 IJavaElement original= copy.getOriginalElement(); 587 if (!original.equals(original1) && !original.equals(original2)) 588 result.add(copy); 589 } 590 } 591 return (ICompilationUnit[]) result.toArray(new ICompilationUnit[result.size()]); 592 } 593 594 private static ITypeBinding getTypeBinding(IType theType, WorkingCopyOwner workingCopyOwner) throws JavaModelException { 595 return getTypeDeclarationNode(theType, workingCopyOwner).resolveBinding(); 596 } 597 598 private static TypeDeclaration getTypeDeclarationNode(IType theType, WorkingCopyOwner workingCopyOwner) throws JavaModelException { 599 return ASTNodeSearchUtil.getTypeDeclarationNode(theType, ASTCreator.createAST(theType.getCompilationUnit(), workingCopyOwner)); 600 } 601 602 private CompilationUnitRange[] getCompilationUnitRanges(ConstraintVariable[] variables, IType inputType, ITypeBinding inputTypeBinding) throws CoreException { 603 Set ranges= new HashSet (); 604 IJavaProject scope= inputType.getJavaProject(); for (int i= 0; i < variables.length; i++) { 606 CompilationUnitRange range= getRange(variables[i], scope, inputTypeBinding); 607 if (range != null) 608 ranges.add(range); 609 } 610 return (CompilationUnitRange[]) ranges.toArray(new CompilationUnitRange[ranges.size()]); 611 } 612 613 private CompilationUnitRange getRange(ConstraintVariable variable, IJavaProject scope, ITypeBinding inputTypeBinding) throws CoreException { 614 if (variable instanceof DeclaringTypeVariable) 615 return null; 616 else if (variable instanceof RawBindingVariable) 617 return null; 618 else if (variable instanceof ParameterTypeVariable) 619 return getRange((ParameterTypeVariable)variable, scope); 620 else if (variable instanceof ReturnTypeVariable) 621 return getRange((ReturnTypeVariable)variable, scope); 622 else if (variable instanceof TypeVariable) 623 return getRange((TypeVariable)variable); 624 else if (variable instanceof ExpressionVariable) 625 return getRange((ExpressionVariable)variable, inputTypeBinding); 626 else return null; 628 } 629 630 private CompilationUnitRange getRange(ExpressionVariable variable, ITypeBinding inputTypeBinding) { 631 if (inputTypeBinding == null) return null; 632 if (variable.getExpressionType() == ASTNode.SIMPLE_NAME || variable.getExpressionType() == ASTNode.QUALIFIED_NAME) { 633 if (Bindings.equals(inputTypeBinding, variable.getExpressionBinding())) 634 return variable.getCompilationUnitRange(); 635 } 636 return null; 637 } 638 639 private CompilationUnitRange getRange(TypeVariable variable) { 640 return variable.getCompilationUnitRange(); 641 } 642 643 private CompilationUnitRange getRange(ReturnTypeVariable variable, IJavaProject scope) throws CoreException { 644 IMethodBinding methodBinding= variable.getMethodBinding(); 645 IMethod method= getMethod(methodBinding, scope); 646 if (method == null) 647 return null; 648 return new CompilationUnitRange(method.getCompilationUnit(), getReturnTypeRange(method)); 649 } 650 651 private CompilationUnitRange getRange(ParameterTypeVariable variable, IJavaProject scope) throws CoreException { 652 IMethodBinding methodBinding= variable.getMethodBinding(); 653 int paramIndex= variable.getParameterIndex(); 654 IMethod method= getMethod(methodBinding, scope); 655 if (method == null) 656 return null; 657 return new CompilationUnitRange(method.getCompilationUnit(), getParameterTypeRange(method, paramIndex)); 658 } 659 660 private static ISourceRange getReturnTypeRange(IMethod method) throws CoreException { 661 IScanner scanner= ToolFactory.createScanner(false, false, false, false); 662 scanner.setSource(method.getSource().toCharArray()); 663 TokenScanner tokenScanner= new TokenScanner(scanner); 664 skipModifiers(tokenScanner); 665 return new SourceRange(method.getSourceRange().getOffset() + tokenScanner.getCurrentStartOffset(), tokenScanner.getCurrentLength()); 666 } 667 668 private static void skipModifiers(TokenScanner scanner) throws CoreException { 669 int token= scanner.readNext(true); 670 while (token != ITerminalSymbols.TokenNameEOF) { 671 if (!TokenScanner.isModifier(token)) 672 return; 673 token= scanner.readNext(true); 674 } 675 } 676 677 private static ISourceRange getParameterTypeRange(IMethod method, int paramIndex) throws CoreException { 678 Assert.isTrue(0 <= paramIndex, "incorrect parameter"); Assert.isTrue(paramIndex < method.getNumberOfParameters(), "too few method parameters"); IScanner scanner= ToolFactory.createScanner(false, false, false, false); 681 scanner.setSource(method.getSource().toCharArray()); 682 TokenScanner tokenScanner= new TokenScanner(scanner); 683 tokenScanner.readToToken(ITerminalSymbols.TokenNameLPAREN); 684 for (int i= 0; i < paramIndex; i++) { 685 tokenScanner.readToToken(ITerminalSymbols.TokenNameCOMMA); 686 } 687 tokenScanner.readNext(true); 688 return new SourceRange(method.getSourceRange().getOffset() + tokenScanner.getCurrentStartOffset(), tokenScanner.getCurrentLength()); 689 } 690 691 private IMethod getMethod(IMethodBinding methodBinding, IJavaProject scope) throws JavaModelException { 692 IMethod method= Bindings.findMethod(methodBinding, scope); 693 IJavaElement e1= JavaModelUtil.findInCompilationUnit(fInputTypeWorkingCopy, method); 694 if (e1 instanceof IMethod){ 695 method= (IMethod) e1; 696 } else if (fSupertypeWorkingCopy != null){ 697 e1= JavaModelUtil.findInCompilationUnit(fSupertypeWorkingCopy, method); 698 if (e1 instanceof IMethod) 699 method= (IMethod) e1; 700 } 701 return method; 702 } 703 704 private static class ExtractInterfaceConstraintCreator extends FullConstraintCreator{ 705 706 public ExtractInterfaceConstraintCreator(final IType inputType){ 707 super(new ConstraintVariableFactory(), new TypeConstraintFactory(){ 708 public boolean filter(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator o){ 709 ITypeBinding v1Binding= v1.getBinding(); 710 ITypeBinding v2Binding= v2.getBinding(); 711 if (v1Binding != null && v2Binding != null){ 712 String inputTypeName= inputType.getFullyQualifiedName(); 713 String v1Name= (!v1Binding.isArray()) ? v1Binding.getQualifiedName() 714 : v1Binding.getElementType().getQualifiedName(); 715 String v2Name= (!v2Binding.isArray()) ? v2Binding.getQualifiedName() 716 : v2Binding.getElementType().getQualifiedName(); 717 if (!v1Name.equals(inputTypeName) && !v2Name.equals(inputTypeName)){ 718 if (PRINT_STATS) fNrFiltered++; 719 return true; 720 } 721 } 722 return super.filter(v1, v2, o); 723 } 724 }); 725 } 726 727 730 public ITypeConstraint[] create(ArrayCreation node) { 731 ConstraintVariable arrayCreationVar= getConstraintVariableFactory().makeExpressionOrTypeVariable(node, getContext()); 732 ConstraintVariable typeVar= getConstraintVariableFactory().makeTypeVariable(node.getType()); 733 ITypeConstraint[] equals= getConstraintFactory().createEqualsConstraint(arrayCreationVar, typeVar); 734 return equals; 735 } 736 737 740 public ITypeConstraint[] create(ArrayAccess node) { 741 Expression expression= node.getArray(); 742 ITypeConstraint[] equals= getConstraintFactory().createEqualsConstraint(getConstraintVariableFactory().makeExpressionOrTypeVariable(node, getContext()), getConstraintVariableFactory().makeExpressionOrTypeVariable(expression, getContext())); 743 return equals; 744 } 745 746 749 public ITypeConstraint[] create(ArrayType node) { 750 ConstraintVariable component= getConstraintVariableFactory().makeTypeVariable(node.getComponentType()); 751 ITypeConstraint[] equals= getConstraintFactory().createEqualsConstraint(getConstraintVariableFactory().makeTypeVariable(node), component); 752 return equals; 753 } 754 } 755 } 756 | Popular Tags |