1 /*******************************************************************************
2  * Copyright (c) 2000, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.codeassist.complete;
15 
16 import org.eclipse.jdt.internal.compiler.*;
17 import org.eclipse.jdt.internal.compiler.ast.*;
18 import org.eclipse.jdt.internal.compiler.lookup.*;
19 
20 /**
21  * Detect the presence of a node in expression
22  */
23 public class CompletionNodeDetector extends ASTVisitor {
24 	private ASTNode searchedNode;
25 	private ASTNode parent;
26 	private boolean result;
27 
CompletionNodeDetector(ASTNode searchedNode, ASTNode visitedAst)28 	public CompletionNodeDetector(ASTNode searchedNode, ASTNode visitedAst){
29 		this.searchedNode = searchedNode;
30 		this.result = false;
31 
32 		if(searchedNode != null && visitedAst != null) {
33 			visitedAst.traverse(this, null);
34 		}
35 	}
36 
containsCompletionNode()37 	public boolean containsCompletionNode() {
38 		return this.result;
39 	}
40 
getCompletionNodeParent()41 	public ASTNode getCompletionNodeParent() {
42 		return this.parent;
43 	}
44 	@Override
endVisit(AllocationExpression allocationExpression, BlockScope scope)45 	public void endVisit(AllocationExpression allocationExpression, BlockScope scope) {
46 		endVisit(allocationExpression);
47 	}
48 	@Override
endVisit(AND_AND_Expression and_and_Expression, BlockScope scope)49 	public void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope) {
50 		endVisit(and_and_Expression);
51 	}
52 	@Override
endVisit(ArrayAllocationExpression arrayAllocationExpression, BlockScope scope)53 	public void endVisit(ArrayAllocationExpression arrayAllocationExpression, BlockScope scope) {
54 		endVisit(arrayAllocationExpression);
55 	}
56 	@Override
endVisit(ArrayInitializer arrayInitializer, BlockScope scope)57 	public void endVisit(ArrayInitializer arrayInitializer, BlockScope scope) {
58 		endVisit(arrayInitializer);
59 	}
60 	@Override
endVisit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope)61 	public void endVisit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope) {
62 		endVisit(arrayQualifiedTypeReference);
63 	}
64 	@Override
endVisit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope)65 	public void endVisit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope) {
66 		endVisit(arrayQualifiedTypeReference);
67 	}
68 	@Override
endVisit(ArrayReference arrayReference, BlockScope scope)69 	public void endVisit(ArrayReference arrayReference, BlockScope scope) {
70 		endVisit(arrayReference);
71 	}
72 	@Override
endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope)73 	public void endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
74 		endVisit(arrayTypeReference);
75 	}
76 	@Override
endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope)77 	public void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
78 		endVisit(arrayTypeReference);
79 	}
80 	@Override
endVisit(Assignment assignment, BlockScope scope)81 	public void endVisit(Assignment assignment, BlockScope scope) {
82 		endVisit(assignment);
83 	}
84 	@Override
endVisit(BinaryExpression binaryExpression, BlockScope scope)85 	public void endVisit(BinaryExpression binaryExpression, BlockScope scope) {
86 		endVisit(binaryExpression);
87 	}
88 	@Override
endVisit(CastExpression castExpression, BlockScope scope)89 	public void endVisit(CastExpression castExpression, BlockScope scope) {
90 		endVisit(castExpression);
91 	}
92 	@Override
endVisit(CompoundAssignment compoundAssignment, BlockScope scope)93 	public void endVisit(CompoundAssignment compoundAssignment, BlockScope scope) {
94 		endVisit(compoundAssignment);
95 	}
96 	@Override
endVisit(ConditionalExpression conditionalExpression, BlockScope scope)97 	public void endVisit(ConditionalExpression conditionalExpression, BlockScope scope) {
98 		endVisit(conditionalExpression);
99 	}
100 	@Override
endVisit(EqualExpression equalExpression, BlockScope scope)101 	public void endVisit(EqualExpression equalExpression, BlockScope scope) {
102 		endVisit(equalExpression);
103 	}
104 	@Override
endVisit(ExplicitConstructorCall explicitConstructor, BlockScope scope)105 	public void endVisit(ExplicitConstructorCall explicitConstructor, BlockScope scope) {
106 		endVisit(explicitConstructor);
107 	}
108 	@Override
endVisit(FieldReference fieldReference, BlockScope scope)109 	public void endVisit(FieldReference fieldReference, BlockScope scope) {
110 		endVisit(fieldReference);
111 	}
112 	@Override
endVisit(InstanceOfExpression instanceOfExpression, BlockScope scope)113 	public void endVisit(InstanceOfExpression instanceOfExpression, BlockScope scope) {
114 		endVisit(instanceOfExpression);
115 	}
116 	@Override
endVisit(MessageSend messageSend, BlockScope scope)117 	public void endVisit(MessageSend messageSend, BlockScope scope) {
118 		endVisit(messageSend);
119 	}
120 	@Override
endVisit(OR_OR_Expression or_or_Expression, BlockScope scope)121 	public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
122 		endVisit(or_or_Expression);
123 	}
124 	@Override
endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope)125 	public void endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope) {
126 		endVisit(parameterizedQualifiedTypeReference);
127 	}
128 	@Override
endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope)129 	public void endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope) {
130 		endVisit(parameterizedQualifiedTypeReference);
131 	}
132 	@Override
endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope)133 	public void endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope) {
134 		endVisit(parameterizedSingleTypeReference);
135 	}
136 	@Override
endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope)137 	public void endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope) {
138 		endVisit(parameterizedSingleTypeReference);
139 	}
140 	@Override
endVisit(PostfixExpression postfixExpression, BlockScope scope)141 	public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
142 		endVisit(postfixExpression);
143 	}
144 	@Override
endVisit(PrefixExpression prefixExpression, BlockScope scope)145 	public void endVisit(PrefixExpression prefixExpression, BlockScope scope) {
146 		endVisit(prefixExpression);
147 	}
148 	@Override
endVisit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope)149 	public void endVisit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope) {
150 		endVisit(qualifiedAllocationExpression);
151 	}
152 	@Override
endVisit(QualifiedNameReference qualifiedNameReference, BlockScope scope)153 	public void endVisit(QualifiedNameReference qualifiedNameReference, BlockScope scope) {
154 		endVisit(qualifiedNameReference);
155 	}
156 	@Override
endVisit(QualifiedSuperReference qualifiedSuperReference, BlockScope scope)157 	public void endVisit(QualifiedSuperReference qualifiedSuperReference, BlockScope scope) {
158 		endVisit(qualifiedSuperReference);
159 	}
160 	@Override
endVisit(QualifiedThisReference qualifiedThisReference, BlockScope scope)161 	public void endVisit(QualifiedThisReference qualifiedThisReference, BlockScope scope) {
162 		endVisit(qualifiedThisReference);
163 	}
164 	@Override
endVisit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope)165 	public void endVisit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope) {
166 		endVisit(qualifiedTypeReference);
167 	}
168 	@Override
endVisit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope)169 	public void endVisit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope) {
170 		endVisit(qualifiedTypeReference);
171 	}
172 	@Override
endVisit(ReferenceExpression referenceExpression, BlockScope blockScope)173 	public void endVisit(ReferenceExpression referenceExpression, BlockScope blockScope) {
174 		endVisit(referenceExpression);
175 	}
176 	@Override
endVisit(SingleNameReference singleNameReference, BlockScope scope)177 	public void endVisit(SingleNameReference singleNameReference, BlockScope scope) {
178 		endVisit(singleNameReference);
179 	}
180 	@Override
endVisit(SingleTypeReference singleTypeReference, BlockScope scope)181 	public void endVisit(SingleTypeReference singleTypeReference, BlockScope scope) {
182 		endVisit(singleTypeReference);
183 	}
184 	@Override
endVisit(SingleTypeReference singleTypeReference, ClassScope scope)185 	public void endVisit(SingleTypeReference singleTypeReference, ClassScope scope) {
186 		endVisit(singleTypeReference);
187 	}
188 	@Override
endVisit(SuperReference superReference, BlockScope scope)189 	public void endVisit(SuperReference superReference, BlockScope scope) {
190 		endVisit(superReference);
191 	}
192 	@Override
endVisit(ThisReference thisReference, BlockScope scope)193 	public void endVisit(ThisReference thisReference, BlockScope scope) {
194 		endVisit(thisReference);
195 	}
196 	@Override
endVisit(UnaryExpression unaryExpression, BlockScope scope)197 	public void endVisit(UnaryExpression unaryExpression, BlockScope scope) {
198 		endVisit(unaryExpression);
199 	}
200 	@Override
endVisit(MemberValuePair pair, BlockScope scope)201 	public void endVisit(MemberValuePair pair, BlockScope scope) {
202 		endVisit(pair);
203 	}
endVisit(MemberValuePair pair, CompilationUnitScope scope)204 	public void endVisit(MemberValuePair pair, CompilationUnitScope scope) {
205 		endVisit(pair);
206 	}
207 	@Override
endVisit(LambdaExpression lambda, BlockScope scope)208 	public void endVisit(LambdaExpression lambda, BlockScope scope) {
209 		endVisit(lambda);
210 	}
211 	@Override
visit(AllocationExpression allocationExpression, BlockScope scope)212 	public boolean visit(AllocationExpression allocationExpression, BlockScope scope) {
213 		return this.visit(allocationExpression);
214 	}
215 	@Override
visit(AND_AND_Expression and_and_Expression, BlockScope scope)216 	public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) {
217 		return this.visit(and_and_Expression);
218 	}
219 	@Override
visit(ArrayAllocationExpression arrayAllocationExpression, BlockScope scope)220 	public boolean visit(ArrayAllocationExpression arrayAllocationExpression, BlockScope scope) {
221 		return this.visit(arrayAllocationExpression);
222 	}
223 	@Override
visit(ArrayInitializer arrayInitializer, BlockScope scope)224 	public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {
225 		return this.visit(arrayInitializer);
226 	}
227 	@Override
visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope)228 	public boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope) {
229 		return this.visit(arrayQualifiedTypeReference);
230 	}
231 	@Override
visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope)232 	public boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope) {
233 		return this.visit(arrayQualifiedTypeReference);
234 	}
235 	@Override
visit(ArrayReference arrayReference, BlockScope scope)236 	public boolean visit(ArrayReference arrayReference, BlockScope scope) {
237 		return this.visit(arrayReference);
238 	}
239 	@Override
visit(ArrayTypeReference arrayTypeReference, BlockScope scope)240 	public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
241 		return this.visit(arrayTypeReference);
242 	}
243 	@Override
visit(ArrayTypeReference arrayTypeReference, ClassScope scope)244 	public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
245 		return this.visit(arrayTypeReference);
246 	}
247 	@Override
visit(Assignment assignment, BlockScope scope)248 	public boolean visit(Assignment assignment, BlockScope scope) {
249 		return this.visit(assignment);
250 	}
251 	@Override
visit(BinaryExpression binaryExpression, BlockScope scope)252 	public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
253 		return this.visit(binaryExpression);
254 	}
255 	@Override
visit(CastExpression castExpression, BlockScope scope)256 	public boolean visit(CastExpression castExpression, BlockScope scope) {
257 		return this.visit(castExpression);
258 	}
259 	@Override
visit(CompoundAssignment compoundAssignment, BlockScope scope)260 	public boolean visit(CompoundAssignment compoundAssignment, BlockScope scope) {
261 		return this.visit(compoundAssignment);
262 	}
263 	@Override
visit(ConditionalExpression conditionalExpression, BlockScope scope)264 	public boolean visit(ConditionalExpression conditionalExpression, BlockScope scope) {
265 		return this.visit(conditionalExpression);
266 	}
267 	@Override
visit(EqualExpression equalExpression, BlockScope scope)268 	public boolean visit(EqualExpression equalExpression, BlockScope scope) {
269 		return this.visit(equalExpression);
270 	}
271 	@Override
visit(ExplicitConstructorCall explicitConstructor, BlockScope scope)272 	public boolean visit(ExplicitConstructorCall explicitConstructor, BlockScope scope) {
273 		return this.visit(explicitConstructor);
274 	}
275 	@Override
visit(FieldReference fieldReference, BlockScope scope)276 	public boolean visit(FieldReference fieldReference, BlockScope scope) {
277 		return this.visit(fieldReference);
278 	}
279 	@Override
visit(InstanceOfExpression instanceOfExpression, BlockScope scope)280 	public boolean visit(InstanceOfExpression instanceOfExpression, BlockScope scope) {
281 		return this.visit(instanceOfExpression);
282 	}
283 	@Override
visit(MessageSend messageSend, BlockScope scope)284 	public boolean visit(MessageSend messageSend, BlockScope scope) {
285 		return this.visit(messageSend);
286 	}
287 	@Override
visit(OR_OR_Expression or_or_Expression, BlockScope scope)288 	public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
289 		return this.visit(or_or_Expression);
290 	}
291 	@Override
visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope)292 	public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope) {
293 		return this.visit(parameterizedQualifiedTypeReference);
294 	}
295 	@Override
visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope)296 	public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope) {
297 		return this.visit(parameterizedQualifiedTypeReference);
298 	}
299 	@Override
visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope)300 	public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope) {
301 		return this.visit(parameterizedSingleTypeReference);
302 	}
303 	@Override
visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope)304 	public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope) {
305 		return this.visit(parameterizedSingleTypeReference);
306 	}
307 	@Override
visit(PostfixExpression postfixExpression, BlockScope scope)308 	public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
309 		return this.visit(postfixExpression);
310 	}
311 	@Override
visit(PrefixExpression prefixExpression, BlockScope scope)312 	public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
313 		return this.visit(prefixExpression);
314 	}
315 	@Override
visit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope)316 	public boolean visit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope) {
317 		return this.visit(qualifiedAllocationExpression);
318 	}
319 	@Override
visit(QualifiedNameReference qualifiedNameReference, BlockScope scope)320 	public boolean visit(QualifiedNameReference qualifiedNameReference, BlockScope scope) {
321 		return this.visit(qualifiedNameReference);
322 	}
323 	@Override
visit(QualifiedSuperReference qualifiedSuperReference, BlockScope scope)324 	public boolean visit(QualifiedSuperReference qualifiedSuperReference, BlockScope scope) {
325 		return this.visit(qualifiedSuperReference);
326 	}
327 	@Override
visit(QualifiedThisReference qualifiedThisReference, BlockScope scope)328 	public boolean visit(QualifiedThisReference qualifiedThisReference, BlockScope scope) {
329 		return this.visit(qualifiedThisReference);
330 	}
331 	@Override
visit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope)332 	public boolean visit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope) {
333 		return this.visit(qualifiedTypeReference);
334 	}
335 	@Override
visit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope)336 	public boolean visit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope) {
337 		return this.visit(qualifiedTypeReference);
338 	}
339 	@Override
visit(ReferenceExpression referenceExpression, BlockScope blockScope)340 	public boolean visit(ReferenceExpression referenceExpression, BlockScope blockScope) {
341 		return this.visit(referenceExpression);
342 	}
343 	@Override
visit(SingleNameReference singleNameReference, BlockScope scope)344 	public boolean visit(SingleNameReference singleNameReference, BlockScope scope) {
345 		return this.visit(singleNameReference);
346 	}
347 	@Override
visit(SingleTypeReference singleTypeReference, BlockScope scope)348 	public boolean visit(SingleTypeReference singleTypeReference, BlockScope scope) {
349 		return this.visit(singleTypeReference);
350 	}
351 	@Override
visit(SingleTypeReference singleTypeReference, ClassScope scope)352 	public boolean visit(SingleTypeReference singleTypeReference, ClassScope scope) {
353 		return this.visit(singleTypeReference);
354 	}
355 	@Override
visit(StringLiteral stringLiteral, BlockScope scope)356 	public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
357 		return this.visit(stringLiteral);
358 	}
359 	@Override
visit(SuperReference superReference, BlockScope scope)360 	public boolean visit(SuperReference superReference, BlockScope scope) {
361 		return this.visit(superReference);
362 	}
363 	@Override
visit(ThisReference thisReference, BlockScope scope)364 	public boolean visit(ThisReference thisReference, BlockScope scope) {
365 		return this.visit(thisReference);
366 	}
367 	@Override
visit(UnaryExpression unaryExpression, BlockScope scope)368 	public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
369 		return this.visit(unaryExpression);
370 	}
371 	@Override
visit(MemberValuePair pair, BlockScope scope)372 	public boolean visit(MemberValuePair pair, BlockScope scope) {
373 		return this.visit(pair);
374 	}
visit(MemberValuePair pair, CompilationUnitScope scope)375 	public boolean visit(MemberValuePair pair, CompilationUnitScope scope) {
376 		return this.visit(pair);
377 	}
endVisit(ASTNode astNode)378 	private void endVisit(ASTNode astNode) {
379 		if(this.result && this.parent == null && astNode != this.searchedNode) {
380 			if(!(astNode instanceof AllocationExpression && ((AllocationExpression) astNode).type == this.searchedNode)
381 				&& !(astNode instanceof ConditionalExpression && ((ConditionalExpression) astNode).valueIfTrue == this.searchedNode)
382 				&& !(astNode instanceof ConditionalExpression && ((ConditionalExpression) astNode).valueIfFalse == this.searchedNode)) {
383 				this.parent = astNode;
384 			}
385 		}
386 	}
visit(ASTNode astNode)387 	private boolean visit(ASTNode astNode) {
388 		if(astNode == this.searchedNode) {
389 			this.result = true;
390 		}
391 		return !this.result;
392 	}
393 }
394