]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 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.ui.search; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.HashSet; | |
15 | import java.util.List; | |
16 | import java.util.Set; | |
17 | ||
18 | import org.eclipse.jdt.core.dom.ASTNode; | |
19 | import org.eclipse.jdt.core.dom.ASTVisitor; | |
20 | import org.eclipse.jdt.core.dom.Assignment; | |
21 | import org.eclipse.jdt.core.dom.ClassInstanceCreation; | |
22 | import org.eclipse.jdt.core.dom.CompilationUnit; | |
23 | import org.eclipse.jdt.core.dom.Expression; | |
24 | import org.eclipse.jdt.core.dom.FieldAccess; | |
25 | import org.eclipse.jdt.core.dom.FieldDeclaration; | |
26 | import org.eclipse.jdt.core.dom.IBinding; | |
27 | import org.eclipse.jdt.core.dom.IMethodBinding; | |
28 | import org.eclipse.jdt.core.dom.ITypeBinding; | |
29 | import org.eclipse.jdt.core.dom.IVariableBinding; | |
30 | import org.eclipse.jdt.core.dom.ImportDeclaration; | |
31 | import org.eclipse.jdt.core.dom.MethodInvocation; | |
32 | import org.eclipse.jdt.core.dom.Modifier; | |
33 | import org.eclipse.jdt.core.dom.Name; | |
34 | import org.eclipse.jdt.core.dom.NodeFinder; | |
35 | import org.eclipse.jdt.core.dom.ParameterizedType; | |
36 | import org.eclipse.jdt.core.dom.PostfixExpression; | |
37 | import org.eclipse.jdt.core.dom.PrefixExpression; | |
38 | import org.eclipse.jdt.core.dom.PrefixExpression.Operator; | |
39 | import org.eclipse.jdt.core.dom.QualifiedName; | |
40 | import org.eclipse.jdt.core.dom.SimpleName; | |
41 | import org.eclipse.jdt.core.dom.SimpleType; | |
42 | import org.eclipse.jdt.core.dom.SingleVariableDeclaration; | |
43 | import org.eclipse.jdt.core.dom.Type; | |
44 | import org.eclipse.jdt.core.dom.VariableDeclarationFragment; | |
45 | ||
46 | import org.eclipse.jdt.internal.corext.dom.ASTNodes; | |
47 | import org.eclipse.jdt.internal.corext.dom.Bindings; | |
48 | import org.eclipse.jdt.internal.corext.util.Messages; | |
49 | ||
50 | import org.eclipse.jdt.internal.ui.search.IOccurrencesFinder.OccurrenceLocation; | |
51 | import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; | |
52 | ||
53 | public class OccurrencesFinder extends ASTVisitor implements IOccurrencesFinder { | |
54 | ||
55 | public static final String ID= "OccurrencesFinder"; //$NON-NLS-1$ | |
56 | ||
57 | public static final String IS_WRITEACCESS= "writeAccess"; //$NON-NLS-1$ | |
58 | public static final String IS_VARIABLE= "variable"; //$NON-NLS-1$ | |
59 | ||
60 | private CompilationUnit fRoot; | |
61 | private Name fSelectedNode; | |
62 | private IBinding fTarget; | |
63 | ||
64 | private List<OccurrenceLocation> fResult; | |
65 | private Set<Name> fWriteUsages; | |
66 | ||
67 | private boolean fTargetIsStaticMethodImport; | |
68 | ||
69 | private String fReadDescription; | |
70 | private String fWriteDescription; | |
71 | ||
72 | public OccurrencesFinder() { | |
73 | super(true); | |
74 | } | |
75 | ||
76 | public String initialize(CompilationUnit root, int offset, int length) { | |
77 | return initialize(root, NodeFinder.perform(root, offset, length)); | |
78 | } | |
79 | ||
80 | public String initialize(CompilationUnit root, ASTNode node) { | |
81 | if (!(node instanceof Name)) | |
82 | return SearchMessages.OccurrencesFinder_no_element; | |
83 | fRoot= root; | |
84 | fSelectedNode= (Name)node; | |
85 | fTarget= fSelectedNode.resolveBinding(); | |
86 | if (fTarget == null) | |
87 | return SearchMessages.OccurrencesFinder_no_binding; | |
88 | fTarget= getBindingDeclaration(fTarget); | |
89 | ||
90 | fTargetIsStaticMethodImport= isStaticImport(fSelectedNode.getParent()); | |
91 | fReadDescription= Messages.format(SearchMessages.OccurrencesFinder_occurrence_description, BasicElementLabels.getJavaElementName(fTarget.getName())); | |
92 | fWriteDescription= Messages.format(SearchMessages.OccurrencesFinder_occurrence_write_description, BasicElementLabels.getJavaElementName(fTarget.getName())); | |
93 | return null; | |
94 | } | |
95 | ||
96 | private void performSearch() { | |
97 | if (fResult == null) { | |
98 | fResult= new ArrayList<OccurrenceLocation>(); | |
99 | fWriteUsages= new HashSet<Name>(); | |
100 | fRoot.accept(this); | |
101 | } | |
102 | } | |
103 | ||
104 | public OccurrenceLocation[] getOccurrences() { | |
105 | performSearch(); | |
106 | if (fResult.isEmpty()) | |
107 | return null; | |
108 | return fResult.toArray(new OccurrenceLocation[fResult.size()]); | |
109 | } | |
110 | ||
111 | public CompilationUnit getASTRoot() { | |
112 | return fRoot; | |
113 | } | |
114 | ||
115 | /* | |
116 | * @see org.eclipse.jdt.internal.ui.search.IOccurrencesFinder#getJobLabel() | |
117 | */ | |
118 | public String getJobLabel() { | |
119 | return SearchMessages.OccurrencesFinder_searchfor ; | |
120 | } | |
121 | ||
122 | public String getElementName() { | |
123 | if (fSelectedNode != null) { | |
124 | return ASTNodes.asString(fSelectedNode); | |
125 | } | |
126 | return null; | |
127 | } | |
128 | ||
129 | public String getUnformattedPluralLabel() { | |
130 | return SearchMessages.OccurrencesFinder_label_plural; | |
131 | } | |
132 | ||
133 | public String getUnformattedSingularLabel() { | |
134 | return SearchMessages.OccurrencesFinder_label_singular; | |
135 | } | |
136 | ||
137 | @Override | |
138 | public boolean visit(QualifiedName node) { | |
139 | final IBinding binding= node.resolveBinding(); | |
140 | if (binding instanceof IVariableBinding && ((IVariableBinding)binding).isField()) { | |
141 | SimpleName name= node.getName(); | |
142 | return !addUsage(name, name.resolveBinding()); | |
143 | } | |
144 | if (binding instanceof IMethodBinding) { | |
145 | if (isStaticImport(node)) { | |
146 | SimpleName name= node.getName(); | |
147 | return !addPossibleStaticImport(name, (IMethodBinding) binding); | |
148 | } | |
149 | } | |
150 | return !addUsage(node, binding); | |
151 | } | |
152 | ||
153 | private static boolean isStaticImport(ASTNode node) { | |
154 | if (!(node instanceof QualifiedName)) | |
155 | return false; | |
156 | ||
157 | ASTNode parent= ((QualifiedName)node).getParent(); | |
158 | return parent instanceof ImportDeclaration && ((ImportDeclaration) parent).isStatic(); | |
159 | } | |
160 | ||
161 | @Override | |
162 | public boolean visit(MethodInvocation node) { | |
163 | if (fTargetIsStaticMethodImport) { | |
164 | return !addPossibleStaticImport(node.getName(), node.resolveMethodBinding()); | |
165 | } | |
166 | return true; | |
167 | } | |
168 | ||
169 | @Override | |
170 | public boolean visit(SimpleName node) { | |
171 | addUsage(node, node.resolveBinding()); | |
172 | return true; | |
173 | } | |
174 | ||
175 | /* | |
176 | * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ConstructorInvocation) | |
177 | */ | |
178 | @Override | |
179 | public boolean visit(ClassInstanceCreation node) { | |
180 | // match with the constructor and the type. | |
181 | ||
182 | Type type= node.getType(); | |
183 | if (type instanceof ParameterizedType) { | |
184 | type= ((ParameterizedType) type).getType(); | |
185 | } | |
186 | if (type instanceof SimpleType) { | |
187 | Name name= ((SimpleType) type).getName(); | |
188 | if (name instanceof QualifiedName) | |
189 | name= ((QualifiedName)name).getName(); | |
190 | addUsage(name, node.resolveConstructorBinding()); | |
191 | } | |
192 | return super.visit(node); | |
193 | } | |
194 | ||
195 | @Override | |
196 | public boolean visit(Assignment node) { | |
197 | SimpleName name= getSimpleName(node.getLeftHandSide()); | |
198 | if (name != null) | |
199 | addWrite(name, name.resolveBinding()); | |
200 | return true; | |
201 | } | |
202 | ||
203 | @Override | |
204 | public boolean visit(SingleVariableDeclaration node) { | |
205 | addWrite(node.getName(), node.resolveBinding()); | |
206 | return true; | |
207 | } | |
208 | ||
209 | @Override | |
210 | public boolean visit(VariableDeclarationFragment node) { | |
211 | if (node.getParent() instanceof FieldDeclaration || node.getInitializer() != null) | |
212 | addWrite(node.getName(), node.resolveBinding()); | |
213 | return true; | |
214 | } | |
215 | ||
216 | @Override | |
217 | public boolean visit(PrefixExpression node) { | |
218 | PrefixExpression.Operator operator= node.getOperator(); | |
219 | if (operator == Operator.INCREMENT || operator == Operator.DECREMENT) { | |
220 | SimpleName name= getSimpleName(node.getOperand()); | |
221 | if (name != null) | |
222 | addWrite(name, name.resolveBinding()); | |
223 | } | |
224 | return true; | |
225 | } | |
226 | ||
227 | @Override | |
228 | public boolean visit(PostfixExpression node) { | |
229 | SimpleName name= getSimpleName(node.getOperand()); | |
230 | if (name != null) | |
231 | addWrite(name, name.resolveBinding()); | |
232 | return true; | |
233 | } | |
234 | ||
235 | private boolean addWrite(Name node, IBinding binding) { | |
236 | if (binding != null && Bindings.equals(getBindingDeclaration(binding), fTarget)) { | |
237 | fWriteUsages.add(node); | |
238 | return true; | |
239 | } | |
240 | return false; | |
241 | } | |
242 | ||
243 | private boolean addUsage(Name node, IBinding binding) { | |
244 | if (binding != null && Bindings.equals(getBindingDeclaration(binding), fTarget)) { | |
245 | int flag= 0; | |
246 | String description= fReadDescription; | |
247 | if (fTarget instanceof IVariableBinding) { | |
248 | boolean isWrite= fWriteUsages.remove(node); | |
249 | flag= isWrite ? F_WRITE_OCCURRENCE : F_READ_OCCURRENCE; | |
250 | if (isWrite) | |
251 | description= fWriteDescription; | |
252 | } | |
253 | fResult.add(new OccurrenceLocation(node.getStartPosition(), node.getLength(), flag, description)); | |
254 | return true; | |
255 | } | |
256 | return false; | |
257 | } | |
258 | ||
259 | public int getSearchKind() { | |
260 | return K_OCCURRENCE; | |
261 | } | |
262 | ||
263 | ||
264 | ||
265 | private boolean addPossibleStaticImport(Name node, IMethodBinding binding) { | |
266 | if (binding == null || node == null || !(fTarget instanceof IMethodBinding) || !Modifier.isStatic(binding.getModifiers())) | |
267 | return false; | |
268 | ||
269 | IMethodBinding targetMethodBinding= (IMethodBinding)fTarget; | |
270 | if ((fTargetIsStaticMethodImport || Modifier.isStatic(targetMethodBinding.getModifiers())) && (targetMethodBinding.getDeclaringClass().getTypeDeclaration() == binding.getDeclaringClass().getTypeDeclaration())) { | |
271 | if (node.getFullyQualifiedName().equals(targetMethodBinding.getName())) { | |
272 | fResult.add(new OccurrenceLocation(node.getStartPosition(), node.getLength(), 0, fReadDescription)); | |
273 | return true; | |
274 | } | |
275 | } | |
276 | return false; | |
277 | } | |
278 | ||
279 | private SimpleName getSimpleName(Expression expression) { | |
280 | if (expression instanceof SimpleName) | |
281 | return ((SimpleName)expression); | |
282 | else if (expression instanceof QualifiedName) | |
283 | return (((QualifiedName) expression).getName()); | |
284 | else if (expression instanceof FieldAccess) | |
285 | return ((FieldAccess)expression).getName(); | |
286 | return null; | |
287 | } | |
288 | ||
289 | private IBinding getBindingDeclaration(IBinding binding) { | |
290 | switch (binding.getKind()) { | |
291 | case IBinding.TYPE : | |
292 | return ((ITypeBinding)binding).getTypeDeclaration(); | |
293 | case IBinding.METHOD : | |
294 | return ((IMethodBinding)binding).getMethodDeclaration(); | |
295 | case IBinding.VARIABLE : | |
296 | return ((IVariableBinding)binding).getVariableDeclaration(); | |
297 | default: | |
298 | return binding; | |
299 | } | |
300 | } | |
301 | ||
302 | public String getID() { | |
303 | return ID; | |
304 | } | |
305 | ||
306 | public OccurrenceLocation[] generated_6444495884709496422(CompilationUnit astRoot, OccurrenceLocation[] locations, ASTNode selectedNode) { | |
307 | if (initialize(astRoot, selectedNode) == null) { | |
308 | locations= getOccurrences(); | |
309 | } | |
310 | return locations; | |
311 | } | |
312 | } |