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.Collection ; 16 import java.util.List ; 17 18 import org.eclipse.core.runtime.Assert; 19 import org.eclipse.core.runtime.IProgressMonitor; 20 import org.eclipse.core.runtime.SubProgressMonitor; 21 22 import org.eclipse.core.resources.IResource; 23 24 import org.eclipse.jdt.core.ICompilationUnit; 25 import org.eclipse.jdt.core.IMethod; 26 import org.eclipse.jdt.core.IType; 27 import org.eclipse.jdt.core.ITypeHierarchy; 28 import org.eclipse.jdt.core.JavaModelException; 29 import org.eclipse.jdt.core.WorkingCopyOwner; 30 import org.eclipse.jdt.core.dom.AST; 31 import org.eclipse.jdt.core.dom.ASTNode; 32 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 33 import org.eclipse.jdt.core.dom.Block; 34 import org.eclipse.jdt.core.dom.ClassInstanceCreation; 35 import org.eclipse.jdt.core.dom.CompilationUnit; 36 import org.eclipse.jdt.core.dom.MethodDeclaration; 37 import org.eclipse.jdt.core.dom.ParameterizedType; 38 import org.eclipse.jdt.core.dom.SuperConstructorInvocation; 39 import org.eclipse.jdt.core.dom.Type; 40 import org.eclipse.jdt.core.search.IJavaSearchConstants; 41 import org.eclipse.jdt.core.search.IJavaSearchScope; 42 import org.eclipse.jdt.core.search.SearchEngine; 43 import org.eclipse.jdt.core.search.SearchMatch; 44 import org.eclipse.jdt.core.search.SearchPattern; 45 46 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 47 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; 48 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine; 49 import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; 50 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil; 51 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 52 import org.eclipse.jdt.internal.corext.util.JdtFlags; 53 import org.eclipse.jdt.internal.corext.util.SearchUtils; 54 55 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 56 57 60 class ConstructorReferenceFinder { 61 private final IType fType; 62 private final IMethod[] fConstructors; 63 64 private ConstructorReferenceFinder(IType type) throws JavaModelException{ 65 fConstructors= JavaElementUtil.getAllConstructors(type); 66 fType= type; 67 } 68 69 private ConstructorReferenceFinder(IMethod constructor){ 70 fConstructors= new IMethod[]{constructor}; 71 fType= constructor.getDeclaringType(); 72 } 73 74 public static SearchResultGroup[] getConstructorReferences(IType type, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException{ 75 return new ConstructorReferenceFinder(type).getConstructorReferences(pm, null, IJavaSearchConstants.REFERENCES, status); 76 } 77 78 public static SearchResultGroup[] getConstructorReferences(IType type, WorkingCopyOwner owner, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException{ 79 return new ConstructorReferenceFinder(type).getConstructorReferences(pm, owner, IJavaSearchConstants.REFERENCES, status); 80 } 81 82 public static SearchResultGroup[] getConstructorOccurrences(IMethod constructor, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException{ 83 Assert.isTrue(constructor.isConstructor()); 84 return new ConstructorReferenceFinder(constructor).getConstructorReferences(pm, null, IJavaSearchConstants.ALL_OCCURRENCES, status); 85 } 86 87 private SearchResultGroup[] getConstructorReferences(IProgressMonitor pm, WorkingCopyOwner owner, int limitTo, RefactoringStatus status) throws JavaModelException{ 88 IJavaSearchScope scope= createSearchScope(); 89 SearchPattern pattern= RefactoringSearchEngine.createOrPattern(fConstructors, limitTo); 90 if (pattern == null){ 91 if (fConstructors.length != 0) 92 return new SearchResultGroup[0]; 93 return getImplicitConstructorReferences(pm, owner, status); 94 } 95 return removeUnrealReferences(RefactoringSearchEngine.search(pattern, owner, scope, pm, status)); 96 } 97 98 private SearchResultGroup[] removeUnrealReferences(SearchResultGroup[] groups) { 100 List result= new ArrayList (groups.length); 101 for (int i= 0; i < groups.length; i++) { 102 SearchResultGroup group= groups[i]; 103 ICompilationUnit cu= group.getCompilationUnit(); 104 if (cu == null) 105 continue; 106 CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(cu, false); 107 SearchMatch[] allSearchResults= group.getSearchResults(); 108 List realConstructorReferences= new ArrayList (Arrays.asList(allSearchResults)); 109 for (int j= 0; j < allSearchResults.length; j++) { 110 SearchMatch searchResult= allSearchResults[j]; 111 if (! isRealConstructorReferenceNode(ASTNodeSearchUtil.getAstNode(searchResult, cuNode))) 112 realConstructorReferences.remove(searchResult); 113 } 114 if (! realConstructorReferences.isEmpty()) 115 result.add(new SearchResultGroup(group.getResource(), (SearchMatch[]) realConstructorReferences.toArray(new SearchMatch[realConstructorReferences.size()]))); 116 } 117 return (SearchResultGroup[]) result.toArray(new SearchResultGroup[result.size()]); 118 } 119 120 private boolean isRealConstructorReferenceNode(ASTNode node){ 122 String typeName= fConstructors[0].getDeclaringType().getElementName(); 123 if (node.getParent() instanceof AbstractTypeDeclaration 124 && ((AbstractTypeDeclaration) node.getParent()).getNameProperty().equals(node.getLocationInParent())) { 125 return false; 132 } 133 if (node.getParent() instanceof MethodDeclaration 134 && MethodDeclaration.NAME_PROPERTY.equals(node.getLocationInParent())) { 135 MethodDeclaration md= (MethodDeclaration)node.getParent(); 136 if (md.isConstructor() && ! md.getName().getIdentifier().equals(typeName)) { 137 return false; 146 } 147 } 148 return true; 149 } 150 151 private IJavaSearchScope createSearchScope() throws JavaModelException{ 152 if (fConstructors.length == 0) 153 return RefactoringScopeFactory.create(fType); 154 return RefactoringScopeFactory.create(getMostVisibleConstructor()); 155 } 156 157 private IMethod getMostVisibleConstructor() throws JavaModelException { 158 Assert.isTrue(fConstructors.length > 0); 159 IMethod candidate= fConstructors[0]; 160 int visibility= JdtFlags.getVisibilityCode(fConstructors[0]); 161 for (int i= 1; i < fConstructors.length; i++) { 162 IMethod constructor= fConstructors[i]; 163 if (JdtFlags.isHigherVisibility(JdtFlags.getVisibilityCode(constructor), visibility)) 164 candidate= constructor; 165 } 166 return candidate; 167 } 168 169 private SearchResultGroup[] getImplicitConstructorReferences(IProgressMonitor pm, WorkingCopyOwner owner, RefactoringStatus status) throws JavaModelException { 170 pm.beginTask("", 2); List searchMatches= new ArrayList (); 172 searchMatches.addAll(getImplicitConstructorReferencesFromHierarchy(owner, new SubProgressMonitor(pm, 1))); 173 searchMatches.addAll(getImplicitConstructorReferencesInClassCreations(owner, new SubProgressMonitor(pm, 1), status)); 174 pm.done(); 175 return RefactoringSearchEngine.groupByCu((SearchMatch[]) searchMatches.toArray(new SearchMatch[searchMatches.size()]), status); 176 } 177 178 private List getImplicitConstructorReferencesInClassCreations(WorkingCopyOwner owner, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException { 180 SearchPattern pattern= SearchPattern.createPattern(fType, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE); 182 IJavaSearchScope scope= RefactoringScopeFactory.create(fType); 183 SearchResultGroup[] refs= RefactoringSearchEngine.search(pattern, owner, scope, pm, status); 184 List result= new ArrayList (); 185 for (int i= 0; i < refs.length; i++) { 186 SearchResultGroup group= refs[i]; 187 ICompilationUnit cu= group.getCompilationUnit(); 188 if (cu == null) 189 continue; 190 CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(cu, false); 191 SearchMatch[] results= group.getSearchResults(); 192 for (int j= 0; j < results.length; j++) { 193 SearchMatch searchResult= results[j]; 194 ASTNode node= ASTNodeSearchUtil.getAstNode(searchResult, cuNode); 195 if (isImplicitConstructorReferenceNodeInClassCreations(node)) 196 result.add(searchResult); 197 } 198 } 199 return result; 200 } 201 202 public static boolean isImplicitConstructorReferenceNodeInClassCreations(ASTNode node) { 203 if (node instanceof Type) { 204 final ASTNode parent= node.getParent(); 205 if (parent instanceof ClassInstanceCreation) { 206 return (node.equals(((ClassInstanceCreation) parent).getType())); 207 } else if (parent instanceof ParameterizedType) { 208 final ASTNode grandParent= parent.getParent(); 209 if (grandParent instanceof ClassInstanceCreation) { 210 final ParameterizedType type= (ParameterizedType) ((ClassInstanceCreation) grandParent).getType(); 211 return (node.equals(type.getType())); 212 } 213 } 214 } 215 return false; 216 } 217 218 private List getImplicitConstructorReferencesFromHierarchy(WorkingCopyOwner owner, IProgressMonitor pm) throws JavaModelException{ 220 IType[] subTypes= getNonBinarySubtypes(owner, fType, pm); 221 List result= new ArrayList (subTypes.length); 222 for (int i= 0; i < subTypes.length; i++) { 223 result.addAll(getAllSuperConstructorInvocations(subTypes[i])); 224 } 225 return result; 226 } 227 228 private static IType[] getNonBinarySubtypes(WorkingCopyOwner owner, IType type, IProgressMonitor monitor) throws JavaModelException{ 229 ITypeHierarchy hierarchy= null; 230 if (owner == null) 231 hierarchy= type.newTypeHierarchy(monitor); 232 else 233 hierarchy= type.newSupertypeHierarchy(owner, monitor); 234 IType[] subTypes= hierarchy.getAllSubtypes(type); 235 List result= new ArrayList (subTypes.length); 236 for (int i= 0; i < subTypes.length; i++) { 237 if (! subTypes[i].isBinary()) { 238 result.add(subTypes[i]); 239 } 240 } 241 return (IType[]) result.toArray(new IType[result.size()]); 242 } 243 244 private static Collection getAllSuperConstructorInvocations(IType type) throws JavaModelException { 246 IMethod[] constructors= JavaElementUtil.getAllConstructors(type); 247 CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(type.getCompilationUnit(), false); 248 List result= new ArrayList (constructors.length); 249 for (int i= 0; i < constructors.length; i++) { 250 ASTNode superCall= getSuperConstructorCallNode(constructors[i], cuNode); 251 if (superCall != null) 252 result.add(createSearchResult(superCall, constructors[i])); 253 } 254 return result; 255 } 256 257 private static SearchMatch createSearchResult(ASTNode superCall, IMethod constructor) { 258 int start= superCall.getStartPosition(); 259 int end= ASTNodes.getInclusiveEnd(superCall); IResource resource= constructor.getResource(); 261 return new SearchMatch(constructor, SearchMatch.A_ACCURATE, start, end - start, 262 SearchEngine.getDefaultSearchParticipant(), resource); 263 } 264 265 private static SuperConstructorInvocation getSuperConstructorCallNode(IMethod constructor, CompilationUnit cuNode) throws JavaModelException { 266 Assert.isTrue(constructor.isConstructor()); 267 MethodDeclaration constructorNode= ASTNodeSearchUtil.getMethodDeclarationNode(constructor, cuNode); 268 Assert.isTrue(constructorNode.isConstructor()); 269 Block body= constructorNode.getBody(); 270 Assert.isNotNull(body); 271 List statements= body.statements(); 272 if (! statements.isEmpty() && statements.get(0) instanceof SuperConstructorInvocation) 273 return (SuperConstructorInvocation)statements.get(0); 274 return null; 275 } 276 } 277 | Popular Tags |