1 /*******************************************************************************
2  * Copyright (c) 2004, 2020 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.core.tests.model;
15 
16 import java.util.Arrays;
17 import java.util.Comparator;
18 
19 import org.eclipse.jdt.core.CompletionContext;
20 import org.eclipse.jdt.core.CompletionProposal;
21 import org.eclipse.jdt.core.CompletionRequestor;
22 import org.eclipse.jdt.core.Flags;
23 import org.eclipse.jdt.core.IJavaElement;
24 import org.eclipse.jdt.core.Signature;
25 import org.eclipse.jdt.core.compiler.IProblem;
26 import org.eclipse.jdt.internal.codeassist.InternalCompletionContext;
27 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
28 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
29 import org.eclipse.jdt.internal.core.JavaElement;
30 
31 @SuppressWarnings({"rawtypes", "unchecked"})
32 public class CompletionTestsRequestor2 extends CompletionRequestor {
33 	private final char[] NULL_LITERAL = "null".toCharArray();//$NON-NLS-1$
34 
35 	private CompletionContext context;
36 	public int proposalsPtr = -1;
37 	private final static int PROPOSALS_INCREMENT = 10;
38 	private CompletionProposal[] proposals = new CompletionProposal[PROPOSALS_INCREMENT];
39 	private IProblem problem;
40 
41 	private boolean showParameterNames;
42 	private boolean showUniqueKeys;
43 	private boolean showPositions;
44 	private boolean showTokenPositions;
45 	private boolean shortContext;
46 	private boolean showMissingTypes;
47 	private boolean showModifiers;
48 
49 	private boolean computeVisibleElements;
50 	private boolean computeEnclosingElement;
51 	private String assignableType;
52 
53 	public boolean debug = false;
54 
CompletionTestsRequestor2()55 	public CompletionTestsRequestor2() {
56 		this(false, false);
57 	}
CompletionTestsRequestor2(boolean showParamNames)58 	public CompletionTestsRequestor2(boolean showParamNames) {
59 		this(showParamNames, false, false);
60 	}
CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys)61 	public CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys) {
62 		this(showParamNames, showUniqueKeys, false);
63 	}
CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys, boolean showPositions)64 	public CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys, boolean showPositions) {
65 		this(showParamNames, showUniqueKeys, showPositions, true, false);
66 	}
67 
CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys, boolean showPositions, boolean shortContext)68 	public CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys, boolean showPositions, boolean shortContext) {
69 		this(showParamNames, showUniqueKeys, showPositions, shortContext, false);
70 	}
CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys, boolean showPositions, boolean shortContext, boolean showMissingTypes)71 	public CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys, boolean showPositions, boolean shortContext, boolean showMissingTypes) {
72 		this(showParamNames, showUniqueKeys, showPositions, shortContext, showMissingTypes, false);
73 	}
CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys, boolean showPositions, boolean shortContext, boolean showMissingTypes, boolean showTokenPositions)74 	public CompletionTestsRequestor2(boolean showParamNames, boolean showUniqueKeys, boolean showPositions, boolean shortContext, boolean showMissingTypes, boolean showTokenPositions) {
75 		this(false, showParamNames, showUniqueKeys, showPositions, shortContext, showMissingTypes, showTokenPositions, false);
76 	}
CompletionTestsRequestor2( boolean ignoreAll, boolean showParamNames, boolean showUniqueKeys, boolean showPositions, boolean shortContext, boolean showMissingTypes, boolean showTokenPositions, boolean showModifiers)77 	public CompletionTestsRequestor2(
78 			boolean ignoreAll,
79 			boolean showParamNames,
80 			boolean showUniqueKeys,
81 			boolean showPositions,
82 			boolean shortContext,
83 			boolean showMissingTypes,
84 			boolean showTokenPositions,
85 			boolean showModifiers) {
86 		super(ignoreAll);
87 		this.showParameterNames = showParamNames;
88 		this.showUniqueKeys = showUniqueKeys;
89 		this.showPositions = showPositions;
90 		this.showTokenPositions =  showTokenPositions;
91 		this.shortContext = shortContext;
92 		this.showMissingTypes = showMissingTypes;
93 		this.showModifiers = showModifiers;
94 	}
acceptContext(CompletionContext cc)95 	public void acceptContext(CompletionContext cc) {
96 		this.context = cc;
97 	}
accept(CompletionProposal proposal)98 	public void accept(CompletionProposal proposal) {
99 		int length = this.proposals.length;
100 		if (++this.proposalsPtr== length) {
101 			System.arraycopy(this.proposals, 0, this.proposals = new CompletionProposal[length+PROPOSALS_INCREMENT], 0, length);
102 		}
103 		this.proposals[this.proposalsPtr] = proposal;
104 	}
105 
allowAllRequiredProposals()106 	public void allowAllRequiredProposals() {
107 		for (int i = CompletionProposal.ANONYMOUS_CLASS_DECLARATION; i <= CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION; i++) {
108 			for (int j = CompletionProposal.ANONYMOUS_CLASS_DECLARATION; j <= CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION; j++) {
109 				setAllowsRequiredProposals(i, j, true);
110 			}
111 		}
112 	}
113 
completionFailure(IProblem p)114 	public void completionFailure(IProblem p) {
115 		this.problem = p;
116 	}
117 
getContext()118 	public String getContext() {
119 		if(this.context == null) return "";
120 
121 		StringBuffer buffer = new StringBuffer();
122 
123 		if(!this.shortContext) {
124 			buffer.append("completion offset=");
125 			buffer.append(this.context.getOffset());
126 			buffer.append('\n');
127 
128 			buffer.append("completion range=[");
129 			buffer.append(this.context.getTokenStart());
130 			buffer.append(", ");
131 			buffer.append(this.context.getTokenEnd());
132 			buffer.append("]\n");
133 
134 			char[] token = this.context.getToken();
135 			buffer.append("completion token=");
136 			if(token == null) {
137 				buffer.append("null");
138 			} else {
139 				buffer.append('\"');
140 				buffer.append(token);
141 				buffer.append('\"');
142 			}
143 			buffer.append('\n');
144 
145 			buffer.append("completion token kind=");
146 			int tokenKind = this.context.getTokenKind();
147 			if(tokenKind == CompletionContext.TOKEN_KIND_STRING_LITERAL) {
148 				buffer.append("TOKEN_KIND_STRING_LITERAL");
149 			} else if(tokenKind == CompletionContext.TOKEN_KIND_NAME) {
150 				buffer.append("TOKEN_KIND_NAME");
151 			} else {
152 				buffer.append("TOKEN_KIND_UNKNOWN");
153 			}
154 			buffer.append('\n');
155 		}
156 		char[][] expectedTypesSignatures = this.context.getExpectedTypesSignatures();
157 		buffer.append("expectedTypesSignatures=");
158 		if(expectedTypesSignatures == null) {
159 			buffer.append(this.NULL_LITERAL);
160 		} else {
161 			buffer.append('{');
162 			for (int i = 0; i < expectedTypesSignatures.length; i++) {
163 				if(i > 0) buffer.append(',');
164 				buffer.append(expectedTypesSignatures[i]);
165 
166 			}
167 			buffer.append('}');
168 		}
169 		buffer.append('\n');
170 
171 		char[][] expectedTypesKeys = this.context.getExpectedTypesKeys();
172 		buffer.append("expectedTypesKeys=");
173 		if(expectedTypesSignatures == null) {
174 			buffer.append(this.NULL_LITERAL);
175 		} else {
176 			buffer.append('{');
177 			for (int i = 0; i < expectedTypesKeys.length; i++) {
178 				if(i > 0) buffer.append(',');
179 				buffer.append(expectedTypesKeys[i]);
180 
181 			}
182 			buffer.append('}');
183 		}
184 
185 		if(!this.shortContext) {
186 			buffer.append('\n');
187 
188 			int locationType = this.context.getTokenLocation();
189 			if (locationType == 0) {
190 				buffer.append("completion token location=UNKNOWN"); //$NON-NLS-1$
191 			} else {
192 				buffer.append("completion token location={"); //$NON-NLS-1$
193 				boolean first = true;
194 				if ((locationType & CompletionContext.TL_MEMBER_START) != 0) {
195 					if (!first) buffer.append(',');
196 					buffer.append("MEMBER_START"); //$NON-NLS-1$
197 					first = false;
198 				}
199 				if ((locationType & CompletionContext.TL_STATEMENT_START) != 0) {
200 					if (!first) buffer.append(',');
201 					buffer.append("STATEMENT_START"); //$NON-NLS-1$
202 					first = false;
203 				}
204 				if ((locationType & CompletionContext.TL_CONSTRUCTOR_START) != 0) {
205 					if (!first) buffer.append(',');
206 					buffer.append("CONSTRUCTOR_START"); //$NON-NLS-1$
207 					first = false;
208 				}
209 				if ((locationType & CompletionContext.TL_IN_IMPORT) != 0) {
210 					if (!first) buffer.append(',');
211 					buffer.append("IN_IMPORT"); //$NON-NLS-1$
212 					first = false;
213 				}
214 				buffer.append('}');
215 			}
216 		}
217 
218 		if (this.computeEnclosingElement) {
219 			buffer.append('\n');
220 			buffer.append("enclosingElement="); //$NON-NLS-1$
221 			JavaElement enclosingElement = (JavaElement)this.context.getEnclosingElement();
222 			if (enclosingElement == null) {
223 				buffer.append("null"); //$NON-NLS-1$
224 			} else {
225 				buffer.append(enclosingElement.toStringWithAncestors(true /*show resolved info*/));
226 			}
227 		}
228 
229 		if (this.computeVisibleElements) {
230 			buffer.append('\n');
231 
232 			IJavaElement[] visibleElements = this.context.getVisibleElements(this.assignableType);
233 			buffer.append("visibleElements="); //$NON-NLS-1$
234 			if (visibleElements == null) {
235 				buffer.append("null"); //$NON-NLS-1$
236 			} else if (visibleElements.length == 0) {
237 				buffer.append("{}"); //$NON-NLS-1$
238 			} else {
239 				buffer.append('{');
240 				buffer.append('\n');
241 				for (int i = 0; i < visibleElements.length; i++) {
242 					JavaElement element = (JavaElement) visibleElements[i];
243 					buffer.append('\t');
244 					buffer.append(element.toStringWithAncestors(true /*show resolved info*/));
245 					buffer.append(",\n"); //$NON-NLS-1$
246 				}
247 				buffer.append('}');
248 			}
249 		}
250 
251 		//buffer.append('\n');
252 
253 
254 		return buffer.toString();
255 	}
getProblem()256 	public String getProblem() {
257 		return this.problem == null ? "" : this.problem.getMessage();
258 	}
259 
getProposals()260 	public CompletionProposal[] getProposals() {
261 		return this.proposals;
262 	}
263 	/*
264 	 * Get sorted results in ascending order
265 	 */
getResults()266 	public String getResults() {
267 		if(this.proposalsPtr < 0) return "";
268 		quickSort(this.proposals, 0, this.proposalsPtr);
269 		return getResultsWithoutSorting();
270 	}
271 
272 	/*
273 	 * Get sorted results in ascending order
274 	 */
getReversedResults()275 	public String getReversedResults() {
276 		if(this.proposalsPtr < 0) return "";
277 		Arrays.sort(this.proposals, new Comparator() {
278 			@Override
279 			public int compare(Object o1, Object o2) {
280 				if (o1 == o2)
281 					return 0;
282 				if (o1 == null)
283 					return 1;
284 				if (o2 == null)
285 					return -1;
286 				CompletionProposal p1 = (CompletionProposal) o1;
287 				CompletionProposal p2 = (CompletionProposal) o2;
288 				int relDif = p2.getRelevance() - p1.getRelevance();
289 				if(relDif != 0) return relDif;
290 				String name1 = getElementName(p1);
291 				String name2 = getElementName(p2);
292 				return name1.compareTo(name2);
293 			}
294 		});
295 		return getResultsWithoutSorting();
296 	}
297 
298 	/*
299 	 * Get unsorted results (ie. same order as they were accepted by requestor)
300 	 */
getResultsWithoutSorting()301 	public String getResultsWithoutSorting() {
302 		if(this.proposalsPtr < 0) return "";
303 		StringBuffer buffer = printProposal(this.proposals[0]);
304 		for(int i = 1; i <=this.proposalsPtr; i++) {
305 			if(i > 0) buffer.append('\n');
306 			buffer.append(printProposal(this.proposals[i]));
307 		}
308 		return buffer.toString();
309 	}
getStringsResult()310 	public String[] getStringsResult() {
311 		if(this.proposalsPtr < 0) {
312 			return new String[0];
313 		}
314 		String[] strings = new String[this.proposalsPtr+1];
315 		for (int i=0; i<=this.proposalsPtr; i++) {
316 			strings[i] =  printProposal(this.proposals[i]).toString();
317 		}
318 		return strings;
319 	}
320 
printProposal(CompletionProposal proposal)321 	protected StringBuffer printProposal(CompletionProposal proposal) {
322 		StringBuffer buffer = new StringBuffer();
323 		return printProposal(proposal, 0, buffer);
324 	}
325 
printProposal(CompletionProposal proposal, int tab, StringBuffer buffer)326 	protected StringBuffer printProposal(CompletionProposal proposal, int tab, StringBuffer buffer) {
327 		for (int i = 0; i < tab; i++) {
328 			buffer.append("   "); //$NON-NLS-1$
329 		}
330 		buffer.append(getElementName(proposal));
331 		buffer.append('[');
332 		switch(proposal.getKind()) {
333 			case CompletionProposal.ANONYMOUS_CLASS_DECLARATION :
334 				buffer.append("ANONYMOUS_CLASS_DECLARATION"); //$NON-NLS-1$
335 				break;
336 			case CompletionProposal.FIELD_REF :
337 				buffer.append("FIELD_REF"); //$NON-NLS-1$
338 				break;
339 			case CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER :
340 				buffer.append("FIELD_REF_WITH_CASTED_RECEIVER"); //$NON-NLS-1$
341 				break;
342 			case CompletionProposal.KEYWORD :
343 				buffer.append("KEYWORD"); //$NON-NLS-1$
344 				break;
345 			case CompletionProposal.LABEL_REF :
346 				buffer.append("LABEL_REF"); //$NON-NLS-1$
347 				break;
348 			case CompletionProposal.LOCAL_VARIABLE_REF :
349 				buffer.append("LOCAL_VARIABLE_REF"); //$NON-NLS-1$
350 				break;
351 			case CompletionProposal.METHOD_DECLARATION :
352 				buffer.append("METHOD_DECLARATION"); //$NON-NLS-1$
353 				if(proposal.isConstructor()) {
354 					buffer.append("<CONSTRUCTOR>"); //$NON-NLS-1$
355 				}
356 				break;
357 			case CompletionProposal.METHOD_REF :
358 				buffer.append("METHOD_REF"); //$NON-NLS-1$
359 				if(proposal.isConstructor()) {
360 					buffer.append("<CONSTRUCTOR>"); //$NON-NLS-1$
361 				}
362 				break;
363 			case CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER :
364 				buffer.append("METHOD_REF_WITH_CASTED_RECEIVER"); //$NON-NLS-1$
365 				if(proposal.isConstructor()) {
366 					buffer.append("<CONSTRUCTOR>"); //$NON-NLS-1$
367 				}
368 				break;
369 			case CompletionProposal.MODULE_DECLARATION :
370 				buffer.append("MODULE_DECLARATION"); //$NON-NLS-1$
371 				break;
372 			case CompletionProposal.MODULE_REF :
373 				buffer.append("MODULE_REF"); //$NON-NLS-1$
374 				break;
375 			case CompletionProposal.PACKAGE_REF :
376 				buffer.append("PACKAGE_REF"); //$NON-NLS-1$
377 				break;
378 			case CompletionProposal.TYPE_REF :
379 				buffer.append("TYPE_REF"); //$NON-NLS-1$
380 				break;
381 			case CompletionProposal.VARIABLE_DECLARATION :
382 				buffer.append("VARIABLE_DECLARATION"); //$NON-NLS-1$
383 				break;
384 			case CompletionProposal.POTENTIAL_METHOD_DECLARATION :
385 				buffer.append("POTENTIAL_METHOD_DECLARATION"); //$NON-NLS-1$
386 				break;
387 			case CompletionProposal.METHOD_NAME_REFERENCE :
388 				buffer.append("METHOD_NAME_REFERENCE"); //$NON-NLS-1$
389 				break;
390 			case CompletionProposal.ANNOTATION_ATTRIBUTE_REF :
391 				buffer.append("ANNOTATION_ATTRIBUTE_REF"); //$NON-NLS-1$
392 				break;
393 			case CompletionProposal.JAVADOC_BLOCK_TAG :
394 				buffer.append("JAVADOC_BLOCK_TAG"); //$NON-NLS-1$
395 				break;
396 			case CompletionProposal.JAVADOC_INLINE_TAG :
397 				buffer.append("JAVADOC_INLINE_TAG"); //$NON-NLS-1$
398 				break;
399 			case CompletionProposal.JAVADOC_FIELD_REF:
400 				buffer.append("JAVADOC_FIELD_REF"); //$NON-NLS-1$
401 				break;
402 			case CompletionProposal.JAVADOC_METHOD_REF :
403 				buffer.append("JAVADOC_METHOD_REF"); //$NON-NLS-1$
404 				break;
405 			case CompletionProposal.JAVADOC_TYPE_REF :
406 				buffer.append("JAVADOC_TYPE_REF"); //$NON-NLS-1$
407 				break;
408 			case CompletionProposal.JAVADOC_PARAM_REF :
409 				buffer.append("JAVADOC_PARAM_REF"); //$NON-NLS-1$
410 				break;
411 			case CompletionProposal.JAVADOC_VALUE_REF :
412 				buffer.append("JAVADOC_VALUE_REF"); //$NON-NLS-1$
413 				break;
414 			case CompletionProposal.FIELD_IMPORT :
415 				buffer.append("FIELD_IMPORT"); //$NON-NLS-1$
416 				break;
417 			case CompletionProposal.METHOD_IMPORT :
418 				buffer.append("METHOD_IMPORT"); //$NON-NLS-1$
419 				break;
420 			case CompletionProposal.TYPE_IMPORT :
421 				buffer.append("TYPE_IMPORT"); //$NON-NLS-1$
422 				break;
423 			case CompletionProposal.CONSTRUCTOR_INVOCATION :
424 				buffer.append("CONSTRUCTOR_INVOCATION"); //$NON-NLS-1$
425 				break;
426 			case CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION :
427 				buffer.append("ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION"); //$NON-NLS-1$
428 				break;
429 			default :
430 				buffer.append("PROPOSAL"); //$NON-NLS-1$
431 				break;
432 
433 		}
434 		buffer.append("]{");
435 		buffer.append(proposal.getCompletion() == null ? this.NULL_LITERAL : proposal.getCompletion());
436 		buffer.append(", ");
437 		buffer.append(proposal.getDeclarationSignature() == null ? this.NULL_LITERAL : proposal.getDeclarationSignature());
438 		buffer.append(", ");
439 		buffer.append(proposal.getSignature() == null ? this.NULL_LITERAL : proposal.getSignature());
440 
441 		char[] receiverSignature = proposal.getReceiverSignature();
442 		if (receiverSignature != null) {
443 			buffer.append(", ");
444 			buffer.append(receiverSignature);
445 		}
446 
447 		if(this.showUniqueKeys) {
448 			buffer.append(", ");
449 			buffer.append(proposal.getDeclarationKey() == null ? this.NULL_LITERAL : proposal.getDeclarationKey());
450 			buffer.append(", ");
451 			buffer.append(proposal.getKey() == null ? this.NULL_LITERAL : proposal.getKey());
452 		}
453 		buffer.append(", ");
454 		buffer.append(proposal.getName() == null ? this.NULL_LITERAL : proposal.getName());
455 		if(this.showParameterNames) {
456 			char[][] parameterNames = proposal.findParameterNames(null);
457 			buffer.append(", ");
458 			if(parameterNames == null || parameterNames.length <= 0) {
459 				buffer.append(this.NULL_LITERAL);
460 			} else {
461 				buffer.append("(");
462 				for (int i = 0; i < parameterNames.length; i++) {
463 					if(i > 0) buffer.append(", ");
464 					buffer.append(parameterNames[i]);
465 				}
466 				buffer.append(")");
467 			}
468 		}
469 
470 		if(this.showPositions) {
471 			buffer.append(", ");
472 			if(this.showTokenPositions || receiverSignature != null) buffer.append("replace");
473 			buffer.append("[");
474 			buffer.append(proposal.getReplaceStart());
475 			buffer.append(", ");
476 			buffer.append(proposal.getReplaceEnd());
477 			buffer.append("]");
478 		}
479 		if(this.showTokenPositions) {
480 			buffer.append(", token[");
481 			buffer.append(proposal.getTokenStart());
482 			buffer.append(", ");
483 			buffer.append(proposal.getTokenEnd());
484 			buffer.append("]");
485 		}
486 		if(this.showPositions && receiverSignature != null) {
487 			buffer.append(", receiver[");
488 			buffer.append(proposal.getReceiverStart());
489 			buffer.append(", ");
490 			buffer.append(proposal.getReceiverEnd());
491 			buffer.append("]");
492 		}
493 		if(this.showModifiers) {
494 			int flags = proposal.getFlags();
495 			buffer.append(", ");
496 			buffer.append(Flags.toString(flags));
497 			if (Flags.isDeprecated(flags)) {
498 				buffer.append(" deprecated"); //$NON-NLS-1$
499 			}
500 		}
501 		buffer.append(", ");
502 		buffer.append(proposal.getRelevance());
503 		buffer.append('}');
504 		if(this.showMissingTypes) {
505 			CompletionProposal[] requiredProposals = proposal.getRequiredProposals();
506 			if (requiredProposals != null) {
507 				int length = requiredProposals.length;
508 				System.arraycopy(requiredProposals, 0, requiredProposals = new CompletionProposal[length], 0, length);
509 				quickSort(requiredProposals, 0, length - 1);
510 				for (int i = 0; i < length; i++) {
511 					buffer.append('\n');
512 					printProposal(requiredProposals[i], tab + 1, buffer);
513 				}
514 			}
515 		}
516 		return buffer;
517 	}
518 
quickSort(CompletionProposal[] collection, int left, int right)519 	protected CompletionProposal[] quickSort(CompletionProposal[] collection, int left, int right) {
520 		int original_left = left;
521 		int original_right = right;
522 		CompletionProposal mid = collection[left + ((right - left)/2)];
523 		do {
524 			while (compare(mid, collection[left]) > 0)
525 				// s[left] >= mid
526 				left++;
527 			while (compare(mid, collection[right]) < 0)
528 				// s[right] <= mid
529 				right--;
530 			if (left <= right) {
531 				CompletionProposal tmp = collection[left];
532 				collection[left] = collection[right];
533 				collection[right] = tmp;
534 				left++;
535 				right--;
536 			}
537 		} while (left <= right);
538 		if (original_left < right)
539 			collection = quickSort(collection, original_left, right);
540 		if (left < original_right)
541 			collection = quickSort(collection, left, original_right);
542 		return collection;
543 	}
544 
compare(CompletionProposal proposal1, CompletionProposal proposal2)545 	protected int compare(CompletionProposal proposal1, CompletionProposal proposal2) {
546 		int relDif = proposal1.getRelevance() - proposal2.getRelevance();
547 		if(relDif != 0) return relDif;
548 		String name1 = getElementName(proposal1);
549 		String name2 = getElementName(proposal2);
550 		int nameDif = name1.compareTo(name2);
551 		if(nameDif != 0) return nameDif;
552 		int kindDif = proposal1.getKind() - proposal2.getKind();
553 		if(kindDif != 0) return kindDif;
554 		String completion1 = new String(proposal1.getCompletion());
555 		String completion2 = new String(proposal2.getCompletion());
556 		int completionDif = completion1.compareTo(completion2);
557 		if(completionDif != 0) return completionDif;
558 		char[] temp = proposal1.getSignature();
559 		String signature1 = temp == null ? null: new String(temp);
560 		temp = proposal2.getSignature();
561 		String signature2 = temp == null ? null: new String(temp);
562 		int signatureDif = 0;
563 		if(signature1 != null && signature2 != null) {
564 			signatureDif = signature1.compareTo(signature2);
565 		}
566 		if(signatureDif != 0) return signatureDif;
567 		temp = proposal1.getDeclarationSignature();
568 		String declarationSignature1 = temp == null ? null: new String(temp);
569 		temp = proposal2.getDeclarationSignature();
570 		String declarationSignature2 = temp == null ? null: new String(temp);
571 		int declarationSignatureDif = 0;
572 		if(declarationSignature1 != null && declarationSignature2 != null) {
573 			declarationSignatureDif = declarationSignature1.compareTo(declarationSignature2);
574 		}
575 		if(declarationSignatureDif != 0) return declarationSignatureDif;
576 		return 0;
577 	}
578 
getElementName(CompletionProposal proposal)579 	protected String getElementName(CompletionProposal proposal) {
580 		switch(proposal.getKind()) {
581 			case CompletionProposal.ANONYMOUS_CLASS_DECLARATION :
582 				return new String(Signature.getSignatureSimpleName(proposal.getDeclarationSignature()));
583 			case CompletionProposal.TYPE_REF :
584 			case CompletionProposal.TYPE_IMPORT :
585 			case CompletionProposal.JAVADOC_TYPE_REF :
586 				return new String(Signature.getSignatureSimpleName(proposal.getSignature()));
587 			case CompletionProposal.FIELD_REF :
588 			case CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER :
589 			case CompletionProposal.KEYWORD:
590 			case CompletionProposal.LABEL_REF:
591 			case CompletionProposal.LOCAL_VARIABLE_REF:
592 			case CompletionProposal.METHOD_REF:
593 			case CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER:
594 			case CompletionProposal.METHOD_DECLARATION:
595 			case CompletionProposal.VARIABLE_DECLARATION:
596 			case CompletionProposal.POTENTIAL_METHOD_DECLARATION:
597 			case CompletionProposal.METHOD_NAME_REFERENCE:
598 			case CompletionProposal.ANNOTATION_ATTRIBUTE_REF:
599 			case CompletionProposal.JAVADOC_BLOCK_TAG :
600 			case CompletionProposal.JAVADOC_INLINE_TAG :
601 			case CompletionProposal.JAVADOC_FIELD_REF:
602 			case CompletionProposal.JAVADOC_METHOD_REF :
603 			case CompletionProposal.JAVADOC_PARAM_REF :
604 			case CompletionProposal.JAVADOC_VALUE_REF :
605 			case CompletionProposal.FIELD_IMPORT :
606 			case CompletionProposal.METHOD_IMPORT :
607 			case CompletionProposal.CONSTRUCTOR_INVOCATION :
608 			case CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION :
609 				return new String(proposal.getName());
610 			case CompletionProposal.PACKAGE_REF:
611 			case CompletionProposal.MODULE_DECLARATION:
612 				return new String(proposal.getDeclarationSignature());
613 		}
614 		return "";
615 	}
toString()616 	public String toString() {
617 		return getResults();
618 	}
setComputeVisibleElements(boolean computeVisibleElements)619 	public void setComputeVisibleElements(boolean computeVisibleElements) {
620 		this.computeVisibleElements = computeVisibleElements;
621 	}
setAssignableType(String typeSignature)622 	public void setAssignableType(String typeSignature) {
623 		this.assignableType = typeSignature;
624 	}
setComputeEnclosingElement(boolean computeEnclosingElement)625 	public void setComputeEnclosingElement(boolean computeEnclosingElement) {
626 		this.computeEnclosingElement = computeEnclosingElement;
627 	}
628 
canUseDiamond(int proposalNo)629 	public boolean canUseDiamond(int proposalNo) {
630 		if (proposalNo < this.proposals.length && this.proposals[proposalNo] != null) {
631 			return this.proposals[proposalNo].canUseDiamond(this.context);
632 		}
633 		return false;
634 	}
635 
getCompletionNode()636 	public String getCompletionNode() {
637 		if (this.context instanceof InternalCompletionContext) {
638 			InternalCompletionContext internalCompletionContext = (InternalCompletionContext) this.context;
639 			ASTNode astNode = internalCompletionContext.getCompletionNode();
640 			if (astNode != null) return astNode.toString();
641 
642 		}
643 		return null;
644 	}
645 
getCompletionNodeParent()646 	public String getCompletionNodeParent() {
647 		if (this.context instanceof InternalCompletionContext) {
648 			InternalCompletionContext internalCompletionContext = (InternalCompletionContext) this.context;
649 			ASTNode astNode = internalCompletionContext.getCompletionNodeParent();
650 			if (astNode != null) return astNode.toString();
651 
652 		}
653 		return null;
654 	}
655 
getVisibleLocalVariables()656 	public String getVisibleLocalVariables() {
657 		if (this.context instanceof InternalCompletionContext) {
658 			InternalCompletionContext internalCompletionContext = (InternalCompletionContext) this.context;
659 			ObjectVector locals = internalCompletionContext.getVisibleLocalVariables();
660 			if (locals != null) return locals.toString();
661 
662 		}
663 		return null;
664 	}
665 
getVisibleFields()666 	public String getVisibleFields() {
667 		if (this.context instanceof InternalCompletionContext) {
668 			InternalCompletionContext internalCompletionContext = (InternalCompletionContext) this.context;
669 			ObjectVector fields = internalCompletionContext.getVisibleFields();
670 			if (fields != null) return fields.toString();
671 
672 		}
673 		return null;
674 	}
675 
getVisibleMethods()676 	public String getVisibleMethods() {
677 		if (this.context instanceof InternalCompletionContext) {
678 			InternalCompletionContext internalCompletionContext = (InternalCompletionContext) this.context;
679 			ObjectVector methods = internalCompletionContext.getVisibleMethods();
680 			if (methods != null) return methods.toString();
681 
682 		}
683 		return null;
684 	}
685 }
686