KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > structure > ConstructorReferenceFinder


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.structure;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.List JavaDoc;
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 /**
58  * This class is used to find references to constructors.
59  */

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     //XXX this method is a workaround for jdt core bug 27236
99
private SearchResultGroup[] removeUnrealReferences(SearchResultGroup[] groups) {
100         List JavaDoc result= new ArrayList JavaDoc(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 JavaDoc realConstructorReferences= new ArrayList JavaDoc(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     //XXX this method is a workaround for jdt core bug 27236
121
private boolean isRealConstructorReferenceNode(ASTNode node){
122         String JavaDoc typeName= fConstructors[0].getDeclaringType().getElementName();
123         if (node.getParent() instanceof AbstractTypeDeclaration
124                 && ((AbstractTypeDeclaration) node.getParent()).getNameProperty().equals(node.getLocationInParent())) {
125             //Example:
126
// class A{
127
// A(){}
128
// }
129
// class B extends A {}
130
//==> "B" is found as reference to A()
131
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                 //Example:
138
// class A{
139
// A(){}
140
// }
141
// class B extends A{
142
// B(){}
143
// }
144
//==> "B" in "B(){}" is found as reference to A()
145
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); //$NON-NLS-1$
171
List JavaDoc searchMatches= new ArrayList JavaDoc();
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     //List of SearchResults
179
private List JavaDoc getImplicitConstructorReferencesInClassCreations(WorkingCopyOwner owner, IProgressMonitor pm, RefactoringStatus status) throws JavaModelException {
180         //XXX workaround for jdt core bug 23112
181
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 JavaDoc result= new ArrayList JavaDoc();
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     //List of SearchResults
219
private List JavaDoc getImplicitConstructorReferencesFromHierarchy(WorkingCopyOwner owner, IProgressMonitor pm) throws JavaModelException{
220         IType[] subTypes= getNonBinarySubtypes(owner, fType, pm);
221         List JavaDoc result= new ArrayList JavaDoc(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 JavaDoc result= new ArrayList JavaDoc(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     //Collection of SearchResults
245
private static Collection JavaDoc getAllSuperConstructorInvocations(IType type) throws JavaModelException {
246         IMethod[] constructors= JavaElementUtil.getAllConstructors(type);
247         CompilationUnit cuNode= new RefactoringASTParser(AST.JLS3).parse(type.getCompilationUnit(), false);
248         List JavaDoc result= new ArrayList JavaDoc(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); //TODO: why inclusive?
260
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 JavaDoc 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