KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > codeassist > SelectionEngine


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.codeassist;
12
13 import java.util.Locale JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import org.eclipse.jdt.core.Signature;
17 import org.eclipse.jdt.core.compiler.*;
18 import org.eclipse.jdt.core.search.IJavaSearchConstants;
19 import org.eclipse.jdt.internal.codeassist.impl.*;
20 import org.eclipse.jdt.internal.codeassist.select.*;
21 import org.eclipse.jdt.internal.compiler.*;
22 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
23 import org.eclipse.jdt.internal.compiler.env.*;
24 import org.eclipse.jdt.internal.compiler.ast.*;
25 import org.eclipse.jdt.internal.compiler.lookup.*;
26 import org.eclipse.jdt.internal.compiler.parser.*;
27 import org.eclipse.jdt.internal.compiler.problem.*;
28 import org.eclipse.jdt.internal.core.SearchableEnvironment;
29 import org.eclipse.jdt.internal.core.SelectionRequestor;
30 import org.eclipse.jdt.internal.core.SourceType;
31 import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
32 import org.eclipse.jdt.internal.core.util.ASTNodeFinder;
33
34 /**
35  * The selection engine is intended to infer the nature of a selected name in some
36  * source code. This name can be qualified.
37  *
38  * Selection is resolving context using a name environment (no need to search), assuming
39  * the source where selection occurred is correct and will not perform any completion
40  * attempt. If this was the desired behavior, a call to the CompletionEngine should be
41  * performed instead.
42  */

43 public final class SelectionEngine extends Engine implements ISearchRequestor {
44
45     public static boolean DEBUG = false;
46     public static boolean PERF = false;
47     
48     SelectionParser parser;
49     ISelectionRequestor requestor;
50
51     boolean acceptedAnswer;
52
53     private int actualSelectionStart;
54     private int actualSelectionEnd;
55     private char[] selectedIdentifier;
56     
57     private char[][][] acceptedClasses;
58     private int[] acceptedClassesModifiers;
59     private char[][][] acceptedInterfaces;
60     private int[] acceptedInterfacesModifiers;
61     private char[][][] acceptedEnums;
62     private int[] acceptedEnumsModifiers;
63     private char[][][] acceptedAnnotations;
64     private int[] acceptedAnnotationsModifiers;
65     int acceptedClassesCount;
66     int acceptedInterfacesCount;
67     int acceptedEnumsCount;
68     int acceptedAnnotationsCount;
69     
70     boolean noProposal = true;
71     CategorizedProblem problem = null;
72
73     /**
74      * The SelectionEngine is responsible for computing the selected object.
75      *
76      * It requires a searchable name environment, which supports some
77      * specific search APIs, and a requestor to feed back the results to a UI.
78      *
79      * @param nameEnvironment org.eclipse.jdt.internal.core.SearchableEnvironment
80      * used to resolve type/package references and search for types/packages
81      * based on partial names.
82      *
83      * @param requestor org.eclipse.jdt.internal.codeassist.ISelectionRequestor
84      * since the engine might produce answers of various forms, the engine
85      * is associated with a requestor able to accept all possible completions.
86      *
87      * @param settings java.util.Map
88      * set of options used to configure the code assist engine.
89      */

90     public SelectionEngine(
91         SearchableEnvironment nameEnvironment,
92         ISelectionRequestor requestor,
93         Map JavaDoc settings) {
94
95         super(settings);
96
97         this.requestor = requestor;
98         this.nameEnvironment = nameEnvironment;
99
100         ProblemReporter problemReporter =
101             new ProblemReporter(
102                 DefaultErrorHandlingPolicies.proceedWithAllProblems(),
103                 this.compilerOptions,
104                 new DefaultProblemFactory(Locale.getDefault())) {
105                     
106             public CategorizedProblem createProblem(
107                 char[] fileName,
108                 int problemId,
109                 String JavaDoc[] problemArguments,
110                 String JavaDoc[] messageArguments,
111                 int severity,
112                 int problemStartPosition,
113                 int problemEndPosition,
114                 int lineNumber,
115                 int columnNumber) {
116                 CategorizedProblem pb = super.createProblem(
117                     fileName,
118                     problemId,
119                     problemArguments,
120                     messageArguments,
121                     severity,
122                     problemStartPosition,
123                     problemEndPosition,
124                     lineNumber,
125                     columnNumber);
126                     if(SelectionEngine.this.problem == null && pb.isError() && (pb.getID() & IProblem.Syntax) == 0) {
127                         SelectionEngine.this.problem = pb;
128                     }
129
130                     return pb;
131             }
132         };
133         this.lookupEnvironment =
134             new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
135         this.parser = new SelectionParser(problemReporter);
136     }
137
138     public void acceptType(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, int modifiers, AccessRestriction accessRestriction) {
139         char[] typeName = enclosingTypeNames == null ?
140                 simpleTypeName :
141                     CharOperation.concat(
142                         CharOperation.concatWith(enclosingTypeNames, '.'),
143                         simpleTypeName,
144                         '.');
145         
146         if (CharOperation.equals(simpleTypeName, this.selectedIdentifier)) {
147             char[] flatEnclosingTypeNames =
148                 enclosingTypeNames == null || enclosingTypeNames.length == 0 ?
149                         null :
150                             CharOperation.concatWith(enclosingTypeNames, '.');
151             if(mustQualifyType(packageName, simpleTypeName, flatEnclosingTypeNames, modifiers)) {
152                 int length = 0;
153                 int kind = modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation);
154                 switch (kind) {
155                     case ClassFileConstants.AccAnnotation:
156                     case ClassFileConstants.AccAnnotation | ClassFileConstants.AccInterface:
157                         char[][] acceptedAnnotation = new char[2][];
158                         acceptedAnnotation[0] = packageName;
159                         acceptedAnnotation[1] = typeName;
160                         
161                         if(this.acceptedAnnotations == null) {
162                             this.acceptedAnnotations = new char[10][][];
163                             this.acceptedAnnotationsModifiers = new int[10];
164                             this.acceptedAnnotationsCount = 0;
165                         }
166                         length = this.acceptedAnnotations.length;
167                         if(length == this.acceptedAnnotationsCount) {
168                             int newLength = (length + 1)* 2;
169                             System.arraycopy(this.acceptedAnnotations, 0, this.acceptedAnnotations = new char[newLength][][], 0, length);
170                             System.arraycopy(this.acceptedAnnotationsModifiers, 0, this.acceptedAnnotationsModifiers = new int[newLength], 0, length);
171                         }
172                         this.acceptedAnnotationsModifiers[this.acceptedAnnotationsCount] = modifiers;
173                         this.acceptedAnnotations[this.acceptedAnnotationsCount++] = acceptedAnnotation;
174                         break;
175                     case ClassFileConstants.AccEnum:
176                         char[][] acceptedEnum = new char[2][];
177                         acceptedEnum[0] = packageName;
178                         acceptedEnum[1] = typeName;
179                         
180                         if(this.acceptedEnums == null) {
181                             this.acceptedEnums = new char[10][][];
182                             this.acceptedEnumsModifiers = new int[10];
183                             this.acceptedEnumsCount = 0;
184                         }
185                         length = this.acceptedEnums.length;
186                         if(length == this.acceptedEnumsCount) {
187                             int newLength = (length + 1)* 2;
188                             System.arraycopy(this.acceptedEnums, 0, this.acceptedEnums = new char[newLength][][], 0, length);
189                             System.arraycopy(this.acceptedEnumsModifiers, 0, this.acceptedEnumsModifiers = new int[newLength], 0, length);
190                         }
191                         this.acceptedEnumsModifiers[this.acceptedEnumsCount] = modifiers;
192                         this.acceptedEnums[this.acceptedEnumsCount++] = acceptedEnum;
193                         break;
194                     case ClassFileConstants.AccInterface:
195                         char[][] acceptedInterface= new char[2][];
196                         acceptedInterface[0] = packageName;
197                         acceptedInterface[1] = typeName;
198                         
199                         if(this.acceptedInterfaces == null) {
200                             this.acceptedInterfaces = new char[10][][];
201                             this.acceptedInterfacesModifiers = new int[10];
202                             this.acceptedInterfacesCount = 0;
203                         }
204                         length = this.acceptedInterfaces.length;
205                         if(length == this.acceptedInterfacesCount) {
206                             int newLength = (length + 1)* 2;
207                             System.arraycopy(this.acceptedInterfaces, 0, this.acceptedInterfaces = new char[newLength][][], 0, length);
208                             System.arraycopy(this.acceptedInterfacesModifiers, 0, this.acceptedInterfacesModifiers = new int[newLength], 0, length);
209                         }
210                         this.acceptedInterfacesModifiers[this.acceptedInterfacesCount] = modifiers;
211                         this.acceptedInterfaces[this.acceptedInterfacesCount++] = acceptedInterface;
212                         break;
213                     default:
214                         char[][] acceptedClass = new char[2][];
215                         acceptedClass[0] = packageName;
216                         acceptedClass[1] = typeName;
217                         
218                         if(this.acceptedClasses == null) {
219                             this.acceptedClasses = new char[10][][];
220                             this.acceptedClassesModifiers = new int[10];
221                             this.acceptedClassesCount = 0;
222                         }
223                         length = this.acceptedClasses.length;
224                         if(length == this.acceptedClassesCount) {
225                             int newLength = (length + 1)* 2;
226                             System.arraycopy(this.acceptedClasses, 0, this.acceptedClasses = new char[newLength][][], 0, length);
227                             System.arraycopy(this.acceptedClassesModifiers, 0, this.acceptedClassesModifiers = new int[newLength], 0, length);
228                         }
229                         this.acceptedClassesModifiers[this.acceptedClassesCount] = modifiers;
230                         this.acceptedClasses[this.acceptedClassesCount++] = acceptedClass;
231                         break;
232                 }
233             } else {
234                 this.noProposal = false;
235                 this.requestor.acceptType(
236                     packageName,
237                     typeName,
238                     modifiers,
239                     false,
240                     null,
241                     this.actualSelectionStart,
242                     this.actualSelectionEnd);
243                 this.acceptedAnswer = true;
244             }
245         }
246     }
247
248     /**
249      * One result of the search consists of a new package.
250      * @param packageName char[]
251      *
252      * NOTE - All package names are presented in their readable form:
253      * Package names are in the form "a.b.c".
254      * The default package is represented by an empty array.
255      */

256     public void acceptPackage(char[] packageName) {
257         // implementation of interface method
258
}
259
260     private void acceptQualifiedTypes() {
261         if(this.acceptedClasses != null){
262             this.acceptedAnswer = true;
263             for (int i = 0; i < this.acceptedClassesCount; i++) {
264                 this.noProposal = false;
265                 this.requestor.acceptType(
266                     this.acceptedClasses[i][0],
267                     this.acceptedClasses[i][1],
268                     this.acceptedClassesModifiers[i],
269                     false,
270                     null,
271                     this.actualSelectionStart,
272                     this.actualSelectionEnd);
273             }
274             this.acceptedClasses = null;
275             this.acceptedClassesModifiers = null;
276             this.acceptedClassesCount = 0;
277         }
278         if(this.acceptedInterfaces != null){
279             this.acceptedAnswer = true;
280             for (int i = 0; i < this.acceptedInterfacesCount; i++) {
281                 this.noProposal = false;
282                 this.requestor.acceptType(
283                     this.acceptedInterfaces[i][0],
284                     this.acceptedInterfaces[i][1],
285                     this.acceptedInterfacesModifiers[i],
286                     false,
287                     null,
288                     this.actualSelectionStart,
289                     this.actualSelectionEnd);
290             }
291             this.acceptedInterfaces = null;
292             this.acceptedInterfacesModifiers = null;
293             this.acceptedInterfacesCount = 0;
294         }
295         if(this.acceptedAnnotations != null){
296             this.acceptedAnswer = true;
297             for (int i = 0; i < this.acceptedAnnotationsCount; i++) {
298                 this.noProposal = false;
299                 this.requestor.acceptType(
300                     this.acceptedAnnotations[i][0],
301                     this.acceptedAnnotations[i][1],
302                     this.acceptedAnnotationsModifiers[i],
303                     false,
304                     null,
305                     this.actualSelectionStart,
306                     this.actualSelectionEnd);
307             }
308             this.acceptedAnnotations = null;
309             this.acceptedAnnotationsModifiers = null;
310             this.acceptedAnnotationsCount = 0;
311         }
312         if(this.acceptedEnums != null){
313             this.acceptedAnswer = true;
314             for (int i = 0; i < this.acceptedEnumsCount; i++) {
315                 this.noProposal = false;
316                 this.requestor.acceptType(
317                     this.acceptedEnums[i][0],
318                     this.acceptedEnums[i][1],
319                     this.acceptedEnumsModifiers[i],
320                     false,
321                     null,
322                     this.actualSelectionStart,
323                     this.actualSelectionEnd);
324             }
325             this.acceptedEnums = null;
326             this.acceptedEnumsModifiers = null;
327             this.acceptedEnumsCount = 0;
328         }
329     }
330     private boolean checkSelection(
331         char[] source,
332         int selectionStart,
333         int selectionEnd) {
334
335         Scanner scanner = new Scanner();
336         scanner.setSource(source);
337         
338         int lastIdentifierStart = -1;
339         int lastIdentifierEnd = -1;
340         char[] lastIdentifier = null;
341         int token;
342         
343         if(selectionStart > selectionEnd){
344             int end = source.length - 1;
345             
346             // compute start position of current line
347
int currentPosition = selectionStart - 1;
348             int nextCharacterPosition = selectionStart;
349             char currentCharacter = ' ';
350             try {
351                 lineLoop: while(currentPosition > 0){
352                     
353                     if(source[currentPosition] == '\\' && source[currentPosition+1] == 'u') {
354                         int pos = currentPosition + 2;
355                         int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
356                         while (source[pos] == 'u') {
357                             pos++;
358                         }
359                         
360                         int endOfUnicode = pos + 3;
361                         if (end < endOfUnicode) {
362                             if (endOfUnicode < source.length) {
363                                 end = endOfUnicode;
364                             } else {
365                                 return false; // not enough characters to decode an unicode
366
}
367                         }
368
369                         if ((c1 = ScannerHelper.getNumericValue(source[pos++])) > 15
370                             || c1 < 0
371                             || (c2 = ScannerHelper.getNumericValue(source[pos++])) > 15
372                             || c2 < 0
373                             || (c3 = ScannerHelper.getNumericValue(source[pos++])) > 15
374                             || c3 < 0
375                             || (c4 = ScannerHelper.getNumericValue(source[pos++])) > 15
376                             || c4 < 0) {
377                             return false;
378                         } else {
379                             currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
380                             nextCharacterPosition = pos;
381                         }
382                     } else {
383                         currentCharacter = source[currentPosition];
384                         nextCharacterPosition = currentPosition+1;
385                     }
386                     
387                     switch(currentCharacter) {
388                         case '\r':
389                         case '\n':
390                         case '/':
391                         case '"':
392                         case '\'':
393                             break lineLoop;
394                     }
395                     currentPosition--;
396                 }
397             } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
398                 return false;
399             }
400             
401             // compute start and end of the last token
402
scanner.resetTo(nextCharacterPosition, end);
403             do {
404                 try {
405                     token = scanner.getNextToken();
406                 } catch (InvalidInputException e) {
407                     return false;
408                 }
409                 switch (token) {
410                     case TerminalTokens.TokenNamethis:
411                     case TerminalTokens.TokenNamesuper:
412                     case TerminalTokens.TokenNameIdentifier:
413                         if (scanner.startPosition <= selectionStart && selectionStart <= scanner.currentPosition) {
414                             if (scanner.currentPosition == scanner.eofPosition) {
415                                 int temp = scanner.eofPosition;
416                                 scanner.eofPosition = scanner.source.length;
417                                 while(scanner.getNextCharAsJavaIdentifierPart()){/*empty*/}
418                                 scanner.eofPosition = temp;
419                             }
420                             lastIdentifierStart = scanner.startPosition;
421                             lastIdentifierEnd = scanner.currentPosition - 1;
422                             lastIdentifier = scanner.getCurrentTokenSource();
423                         }
424                         break;
425                 }
426             } while (token != TerminalTokens.TokenNameEOF);
427         } else {
428             scanner.resetTo(selectionStart, selectionEnd);
429     
430             boolean expectingIdentifier = true;
431             try {
432                 do {
433                     token = scanner.getNextToken();
434
435                     switch (token) {
436                         case TerminalTokens.TokenNamethis :
437                         case TerminalTokens.TokenNamesuper :
438                         case TerminalTokens.TokenNameIdentifier :
439                             if (!expectingIdentifier)
440                                 return false;
441                             lastIdentifier = scanner.getCurrentTokenSource();
442                             lastIdentifierStart = scanner.startPosition;
443                             lastIdentifierEnd = scanner.currentPosition - 1;
444                             if(lastIdentifierEnd > selectionEnd) {
445                                 lastIdentifierEnd = selectionEnd;
446                                 lastIdentifier = CharOperation.subarray(lastIdentifier, 0,lastIdentifierEnd - lastIdentifierStart + 1);
447                             }
448     
449                             expectingIdentifier = false;
450                             break;
451                         case TerminalTokens.TokenNameDOT :
452                             if (expectingIdentifier)
453                                 return false;
454                             expectingIdentifier = true;
455                             break;
456                         case TerminalTokens.TokenNameEOF :
457                             if (expectingIdentifier)
458                                 return false;
459                             break;
460                         case TerminalTokens.TokenNameLESS :
461                             if(!checkTypeArgument(scanner))
462                                 return false;
463                             break;
464                         case TerminalTokens.TokenNameAT:
465                             if(scanner.startPosition != scanner.initialPosition)
466                                 return false;
467                             break;
468                         default :
469                             return false;
470                     }
471                 } while (token != TerminalTokens.TokenNameEOF);
472             } catch (InvalidInputException e) {
473                 return false;
474             }
475         }
476         if (lastIdentifierStart > 0) {
477             this.actualSelectionStart = lastIdentifierStart;
478             this.actualSelectionEnd = lastIdentifierEnd;
479             this.selectedIdentifier = lastIdentifier;
480             return true;
481         }
482         return false;
483     }
484     private boolean checkTypeArgument(Scanner scanner) throws InvalidInputException {
485         int depth = 1;
486         int token;
487         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
488         do {
489             token = scanner.getNextToken();
490     
491             switch(token) {
492                 case TerminalTokens.TokenNameLESS :
493                     depth++;
494                     buffer.append(scanner.getCurrentTokenSource());
495                     break;
496                 case TerminalTokens.TokenNameGREATER :
497                     depth--;
498                     buffer.append(scanner.getCurrentTokenSource());
499                     break;
500                 case TerminalTokens.TokenNameRIGHT_SHIFT :
501                     depth-=2;
502                     buffer.append(scanner.getCurrentTokenSource());
503                     break;
504                 case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT :
505                     depth-=3;
506                     buffer.append(scanner.getCurrentTokenSource());
507                     break;
508                 case TerminalTokens.TokenNameextends :
509                 case TerminalTokens.TokenNamesuper :
510                     buffer.append(' ');
511                     buffer.append(scanner.getCurrentTokenSource());
512                     buffer.append(' ');
513                     break;
514                 case TerminalTokens.TokenNameCOMMA :
515                     if(depth == 1) {
516                         int length = buffer.length();
517                         char[] typeRef = new char[length];
518                         buffer.getChars(0, length, typeRef, 0);
519                         try {
520                             Signature.createTypeSignature(typeRef, true);
521                             buffer = new StringBuffer JavaDoc();
522                         } catch(IllegalArgumentException JavaDoc e) {
523                             return false;
524                         }
525                     }
526                     break;
527                 default :
528                     buffer.append(scanner.getCurrentTokenSource());
529                     break;
530                 
531             }
532             if(depth < 0) {
533                 return false;
534             }
535         } while (depth != 0 && token != TerminalTokens.TokenNameEOF);
536         
537         if(depth == 0) {
538             int length = buffer.length() - 1;
539             char[] typeRef = new char[length];
540             buffer.getChars(0, length, typeRef, 0);
541             try {
542                 Signature.createTypeSignature(typeRef, true);
543                 return true;
544             } catch(IllegalArgumentException JavaDoc e) {
545                 return false;
546             }
547         }
548         
549         return false;
550     }
551     
552     public AssistParser getParser() {
553         return this.parser;
554     }
555
556     /*
557      * Returns whether the given binding is a local/anonymous reference binding, or if its declaring class is
558      * local.
559      */

560     private boolean isLocal(ReferenceBinding binding) {
561         if(binding instanceof ParameterizedTypeBinding) {
562             return isLocal(((ParameterizedTypeBinding)binding).genericType());
563         }
564         if (!(binding instanceof SourceTypeBinding)) return false;
565         if (binding instanceof LocalTypeBinding) return true;
566         if (binding instanceof MemberTypeBinding) {
567             return isLocal(((MemberTypeBinding)binding).enclosingType);
568         }
569         return false;
570     }
571
572     /**
573      * Ask the engine to compute the selection at the specified position
574      * of the given compilation unit.
575
576      * @param sourceUnit org.eclipse.jdt.internal.compiler.env.ICompilationUnit
577      * the source of the current compilation unit.
578      *
579      * @param selectionSourceStart int
580      * @param selectionSourceEnd int
581      * a range in the source where the selection is.
582      */

583     public void select(
584         ICompilationUnit sourceUnit,
585         int selectionSourceStart,
586         int selectionSourceEnd) {
587
588         char[] source = sourceUnit.getContents();
589         
590         if(DEBUG) {
591             System.out.print("SELECTION IN "); //$NON-NLS-1$
592
System.out.print(sourceUnit.getFileName());
593             System.out.print(" FROM "); //$NON-NLS-1$
594
System.out.print(selectionSourceStart);
595             System.out.print(" TO "); //$NON-NLS-1$
596
System.out.println(selectionSourceEnd);
597             System.out.println("SELECTION - Source :"); //$NON-NLS-1$
598
System.out.println(source);
599         }
600         if (!checkSelection(source, selectionSourceStart, selectionSourceEnd)) {
601             return;
602         }
603         if (DEBUG) {
604             System.out.print("SELECTION - Checked : \""); //$NON-NLS-1$
605
System.out.print(new String JavaDoc(source, actualSelectionStart, actualSelectionEnd-actualSelectionStart+1));
606             System.out.println('"');
607         }
608         try {
609             this.acceptedAnswer = false;
610             CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
611             CompilationUnitDeclaration parsedUnit =
612                 this.parser.dietParse(sourceUnit, result, this.actualSelectionStart, this.actualSelectionEnd);
613
614             if (parsedUnit != null) {
615                 if(DEBUG) {
616                     System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
617
System.out.println(parsedUnit.toString());
618                 }
619                 
620                 // scan the package & import statements first
621
if (parsedUnit.currentPackage instanceof SelectionOnPackageReference) {
622                     char[][] tokens =
623                         ((SelectionOnPackageReference) parsedUnit.currentPackage).tokens;
624                     this.noProposal = false;
625                     this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
626                     return;
627                 }
628                 ImportReference[] imports = parsedUnit.imports;
629                 if (imports != null) {
630                     for (int i = 0, length = imports.length; i < length; i++) {
631                         ImportReference importReference = imports[i];
632                         if (importReference instanceof SelectionOnImportReference) {
633                             char[][] tokens = ((SelectionOnImportReference) importReference).tokens;
634                             this.noProposal = false;
635                             this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
636                             this.nameEnvironment.findTypes(CharOperation.concatWith(tokens, '.'), false, false, IJavaSearchConstants.TYPE, this);
637                             
638                             this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
639                             if ((this.unitScope = parsedUnit.scope) != null) {
640                                 int tokenCount = tokens.length;
641                                 char[] lastToken = tokens[tokenCount - 1];
642                                 char[][] qualifierTokens = CharOperation.subarray(tokens, 0, tokenCount - 1);
643                                 
644                                 if(qualifierTokens != null && qualifierTokens.length > 0) {
645                                     Binding binding = this.unitScope.getTypeOrPackage(qualifierTokens);
646                                     if(binding != null && binding instanceof ReferenceBinding) {
647                                         ReferenceBinding ref = (ReferenceBinding) binding;
648                                         selectMemberTypeFromImport(parsedUnit, lastToken, ref, importReference.isStatic());
649                                         if(importReference.isStatic()) {
650                                             selectStaticFieldFromStaticImport(parsedUnit, lastToken, ref);
651                                             selectStaticMethodFromStaticImport(parsedUnit, lastToken, ref);
652                                         }
653                                     }
654                                 }
655                             }
656                             
657                             // accept qualified types only if no unqualified type was accepted
658
if(!this.acceptedAnswer) {
659                                 acceptQualifiedTypes();
660                                 if (!this.acceptedAnswer) {
661                                     this.nameEnvironment.findTypes(this.selectedIdentifier, false, false, IJavaSearchConstants.TYPE, this);
662                                     // try with simple type name
663
if(!this.acceptedAnswer) {
664                                         acceptQualifiedTypes();
665                                     }
666                                 }
667                             }
668                             if(this.noProposal && this.problem != null) {
669                                 this.requestor.acceptError(this.problem);
670                             }
671                             return;
672                         }
673                     }
674                 }
675                 if (parsedUnit.types != null || parsedUnit.isPackageInfo()) {
676                     if(selectDeclaration(parsedUnit))
677                         return;
678                     this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
679                     if ((this.unitScope = parsedUnit.scope) != null) {
680                         try {
681                             this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
682                             parsedUnit.scope.faultInTypes();
683                             ASTNode node = null;
684                             if (parsedUnit.types != null)
685                                 node = parseBlockStatements(parsedUnit, selectionSourceStart);
686                             if(DEBUG) {
687                                 System.out.println("SELECTION - AST :"); //$NON-NLS-1$
688
System.out.println(parsedUnit.toString());
689                             }
690                             parsedUnit.resolve();
691                             if (node != null) {
692                                 selectLocalDeclaration(node);
693                             }
694                         } catch (SelectionNodeFound e) {
695                             if (e.binding != null) {
696                                 if(DEBUG) {
697                                     System.out.println("SELECTION - Selection binding:"); //$NON-NLS-1$
698
System.out.println(e.binding.toString());
699                                 }
700                                 // if null then we found a problem in the selection node
701
selectFrom(e.binding, parsedUnit, e.isDeclaration);
702                             }
703                         }
704                     }
705                 }
706             }
707             // only reaches here if no selection could be derived from the parsed tree
708
// thus use the selected source and perform a textual type search
709
if (!this.acceptedAnswer) {
710                 this.nameEnvironment.findTypes(this.selectedIdentifier, false, false, IJavaSearchConstants.TYPE, this);
711                 
712                 // accept qualified types only if no unqualified type was accepted
713
if(!this.acceptedAnswer) {
714                     acceptQualifiedTypes();
715                 }
716             }
717             if(this.noProposal && this.problem != null) {
718                 this.requestor.acceptError(this.problem);
719             }
720         } catch (IndexOutOfBoundsException JavaDoc e) { // work-around internal failure - 1GEMF6D
721
if(DEBUG) {
722                 System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
723
e.printStackTrace(System.out);
724             }
725         } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
726
if(DEBUG) {
727                 System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
728
e.printStackTrace(System.out);
729             }
730         } finally {
731             reset();
732         }
733     }
734
735     private void selectMemberTypeFromImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref, boolean staticOnly) {
736         int fieldLength = lastToken.length;
737         ReferenceBinding[] memberTypes = ref.memberTypes();
738         next : for (int j = 0; j < memberTypes.length; j++) {
739             ReferenceBinding memberType = memberTypes[j];
740             
741             if (fieldLength > memberType.sourceName.length)
742                 continue next;
743
744             if (staticOnly && !memberType.isStatic())
745                 continue next;
746
747             if (!CharOperation.equals(lastToken, memberType.sourceName, true))
748                 continue next;
749             
750             this.selectFrom(memberType, parsedUnit, false);
751         }
752     }
753     
754     private void selectStaticFieldFromStaticImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref) {
755         int fieldLength = lastToken.length;
756         FieldBinding[] fields = ref.fields();
757         next : for (int j = 0; j < fields.length; j++) {
758             FieldBinding field = fields[j];
759             
760             if (fieldLength > field.name.length)
761                 continue next;
762             
763             if (field.isSynthetic())
764                 continue next;
765
766             if (!field.isStatic())
767                 continue next;
768
769             if (!CharOperation.equals(lastToken, field.name, true))
770                 continue next;
771             
772             this.selectFrom(field, parsedUnit, false);
773         }
774     }
775     
776     private void selectStaticMethodFromStaticImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref) {
777         int methodLength = lastToken.length;
778         MethodBinding[] methods = ref.methods();
779         next : for (int j = 0; j < methods.length; j++) {
780             MethodBinding method = methods[j];
781             
782             if (method.isSynthetic()) continue next;
783
784             if (method.isDefaultAbstract()) continue next;
785
786             if (method.isConstructor()) continue next;
787
788             if (!method.isStatic()) continue next;
789
790             if (methodLength > method.selector.length)
791                 continue next;
792
793             if (!CharOperation.equals(lastToken, method.selector, true))
794                 continue next;
795             
796             this.selectFrom(method, parsedUnit, false);
797         }
798     }
799
800     private void selectFrom(Binding binding, CompilationUnitDeclaration parsedUnit, boolean isDeclaration) {
801         if(binding instanceof TypeVariableBinding) {
802             TypeVariableBinding typeVariableBinding = (TypeVariableBinding) binding;
803             Binding enclosingElement = typeVariableBinding.declaringElement;
804             this.noProposal = false;
805             
806             if(enclosingElement instanceof SourceTypeBinding) {
807                 SourceTypeBinding enclosingType = (SourceTypeBinding) enclosingElement;
808                 if (isLocal(enclosingType) && this.requestor instanceof SelectionRequestor) {
809                     ((SelectionRequestor)this.requestor).acceptLocalTypeParameter(typeVariableBinding);
810                 } else {
811                     this.requestor.acceptTypeParameter(
812                         enclosingType.qualifiedPackageName(),
813                         enclosingType.qualifiedSourceName(),
814                         typeVariableBinding.sourceName(),
815                         false,
816                         this.actualSelectionStart,
817                         this.actualSelectionEnd);
818                 }
819             } else if(enclosingElement instanceof MethodBinding) {
820                 MethodBinding enclosingMethod = (MethodBinding) enclosingElement;
821                 if (isLocal(enclosingMethod.declaringClass) && this.requestor instanceof SelectionRequestor) {
822                     ((SelectionRequestor)this.requestor).acceptLocalMethodTypeParameter(typeVariableBinding);
823                 } else {
824                     this.requestor.acceptMethodTypeParameter(
825                         enclosingMethod.declaringClass.qualifiedPackageName(),
826                         enclosingMethod.declaringClass.qualifiedSourceName(),
827                         enclosingMethod.isConstructor()
828                                 ? enclosingMethod.declaringClass.sourceName()
829                                 : enclosingMethod.selector,
830                         enclosingMethod.sourceStart(),
831                         enclosingMethod.sourceEnd(),
832                         typeVariableBinding.sourceName(),
833                         false,
834                         this.actualSelectionStart,
835                         this.actualSelectionEnd);
836                 }
837             }
838             this.acceptedAnswer = true;
839         } else if (binding instanceof ReferenceBinding) {
840             ReferenceBinding typeBinding = (ReferenceBinding) binding;
841             if(typeBinding instanceof ProblemReferenceBinding) {
842                 typeBinding = typeBinding.closestMatch();
843             }
844             if (typeBinding == null) return;
845             if (isLocal(typeBinding) && this.requestor instanceof SelectionRequestor) {
846                 this.noProposal = false;
847                 ((SelectionRequestor)this.requestor).acceptLocalType(typeBinding);
848             } else {
849                 this.noProposal = false;
850
851                 this.requestor.acceptType(
852                     typeBinding.qualifiedPackageName(),
853                     typeBinding.qualifiedSourceName(),
854                     typeBinding.modifiers,
855                     false,
856                     typeBinding.computeUniqueKey(),
857                     this.actualSelectionStart,
858                     this.actualSelectionEnd);
859             }
860             this.acceptedAnswer = true;
861         } else
862             if (binding instanceof MethodBinding) {
863                 MethodBinding methodBinding = (MethodBinding) binding;
864                 this.noProposal = false;
865                 
866                 boolean isValuesOrValueOf = false;
867                 if(binding instanceof SyntheticMethodBinding) {
868                     SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding) binding;
869                     if(syntheticMethodBinding.kind == SyntheticMethodBinding.EnumValues
870                             || syntheticMethodBinding.kind == SyntheticMethodBinding.EnumValueOf) {
871                         isValuesOrValueOf = true;
872                     }
873                 }
874                         
875                 if(!isValuesOrValueOf && !methodBinding.isSynthetic()) {
876                     TypeBinding[] parameterTypes = methodBinding.original().parameters;
877                     int length = parameterTypes.length;
878                     char[][] parameterPackageNames = new char[length][];
879                     char[][] parameterTypeNames = new char[length][];
880                     String JavaDoc[] parameterSignatures = new String JavaDoc[length];
881                     for (int i = 0; i < length; i++) {
882                         parameterPackageNames[i] = parameterTypes[i].qualifiedPackageName();
883                         parameterTypeNames[i] = parameterTypes[i].qualifiedSourceName();
884                         parameterSignatures[i] = new String JavaDoc(getSignature(parameterTypes[i])).replace('/', '.');
885                     }
886                     
887                     TypeVariableBinding[] typeVariables = methodBinding.original().typeVariables;
888                     length = typeVariables == null ? 0 : typeVariables.length;
889                     char[][] typeParameterNames = new char[length][];
890                     char[][][] typeParameterBoundNames = new char[length][][];
891                     for (int i = 0; i < length; i++) {
892                         TypeVariableBinding typeVariable = typeVariables[i];
893                         typeParameterNames[i] = typeVariable.sourceName;
894                         if (typeVariable.firstBound == null) {
895                             typeParameterBoundNames[i] = new char[0][];
896                         } else if (typeVariable.firstBound == typeVariable.superclass) {
897                             int boundCount = 1 + (typeVariable.superInterfaces == null ? 0 : typeVariable.superInterfaces.length);
898                             typeParameterBoundNames[i] = new char[boundCount][];
899                             typeParameterBoundNames[i][0] = typeVariable.superclass.sourceName;
900                             for (int j = 1; j < boundCount; j++) {
901                                 typeParameterBoundNames[i][j] = typeVariables[i].superInterfaces[j - 1].sourceName;
902                             }
903                         } else {
904                             int boundCount = typeVariable.superInterfaces == null ? 0 : typeVariable.superInterfaces.length;
905                             typeParameterBoundNames[i] = new char[boundCount][];
906                             for (int j = 0; j < boundCount; j++) {
907                                 typeParameterBoundNames[i][j] = typeVariables[i].superInterfaces[j].sourceName;
908                             }
909                         }
910                     }
911                     
912                     ReferenceBinding declaringClass = methodBinding.declaringClass;
913                     if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) {
914                         ((SelectionRequestor)this.requestor).acceptLocalMethod(methodBinding);
915                     } else {
916                         this.requestor.acceptMethod(
917                             declaringClass.qualifiedPackageName(),
918                             declaringClass.qualifiedSourceName(),
919                             declaringClass.enclosingType() == null ? null : new String JavaDoc(getSignature(declaringClass.enclosingType())),
920                             methodBinding.isConstructor()
921                                 ? declaringClass.sourceName()
922                                 : methodBinding.selector,
923                             parameterPackageNames,
924                             parameterTypeNames,
925                             parameterSignatures,
926                             typeParameterNames,
927                             typeParameterBoundNames,
928                             methodBinding.isConstructor(),
929                             isDeclaration,
930                             methodBinding.computeUniqueKey(),
931                             this.actualSelectionStart,
932                             this.actualSelectionEnd);
933                     }
934                 }
935                 this.acceptedAnswer = true;
936             } else
937                 if (binding instanceof FieldBinding) {
938                     FieldBinding fieldBinding = (FieldBinding) binding;
939                     ReferenceBinding declaringClass = fieldBinding.declaringClass;
940                     if (declaringClass != null) { // arraylength
941
this.noProposal = false;
942                         if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) {
943                             ((SelectionRequestor)this.requestor).acceptLocalField(fieldBinding);
944                         } else {
945                             this.requestor.acceptField(
946                                 declaringClass.qualifiedPackageName(),
947                                 declaringClass.qualifiedSourceName(),
948                                 fieldBinding.name,
949                                 false,
950                                 fieldBinding.computeUniqueKey(),
951                                 this.actualSelectionStart,
952                                 this.actualSelectionEnd);
953                         }
954                         this.acceptedAnswer = true;
955                     }
956                 } else
957                     if (binding instanceof LocalVariableBinding) {
958                         if (this.requestor instanceof SelectionRequestor) {
959                             ((SelectionRequestor)this.requestor).acceptLocalVariable((LocalVariableBinding)binding);
960                             this.acceptedAnswer = true;
961                         } else {
962                             // open on the type of the variable
963
selectFrom(((LocalVariableBinding) binding).type, parsedUnit, false);
964                         }
965                     } else
966                         if (binding instanceof ArrayBinding) {
967                             selectFrom(((ArrayBinding) binding).leafComponentType, parsedUnit, false);
968                             // open on the type of the array
969
} else
970                             if (binding instanceof PackageBinding) {
971                                 PackageBinding packageBinding = (PackageBinding) binding;
972                                 this.noProposal = false;
973                                 this.requestor.acceptPackage(packageBinding.readableName());
974                                 this.acceptedAnswer = true;
975                             } else
976                                 if(binding instanceof BaseTypeBinding) {
977                                     this.acceptedAnswer = true;
978                                 }
979     }
980     
981     /*
982      * Checks if a local declaration got selected in this method/initializer/field.
983      */

984     private void selectLocalDeclaration(ASTNode node) {
985         // the selected identifier is not identical to the parser one (equals but not identical),
986
// for traversing the parse tree, the parser assist identifier is necessary for identitiy checks
987
final char[] assistIdentifier = this.getParser().assistIdentifier();
988         if (assistIdentifier == null) return;
989         
990         class Visitor extends ASTVisitor {
991             public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
992                 if (constructorDeclaration.selector == assistIdentifier){
993                     if (constructorDeclaration.binding != null) {
994                         throw new SelectionNodeFound(constructorDeclaration.binding);
995                     } else {
996                         if (constructorDeclaration.scope != null) {
997                             throw new SelectionNodeFound(new MethodBinding(constructorDeclaration.modifiers, constructorDeclaration.selector, null, null, null, constructorDeclaration.scope.referenceType().binding));
998                         }
999                     }
1000                }
1001                return true;
1002            }
1003            public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
1004                if (fieldDeclaration.name == assistIdentifier){
1005                    throw new SelectionNodeFound(fieldDeclaration.binding);
1006                }
1007                return true;
1008            }
1009            public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
1010                if (localTypeDeclaration.name == assistIdentifier) {
1011                    throw new SelectionNodeFound(localTypeDeclaration.binding);
1012                }
1013                return true;
1014            }
1015            public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
1016                if (memberTypeDeclaration.name == assistIdentifier) {
1017                    throw new SelectionNodeFound(memberTypeDeclaration.binding);
1018                }
1019                return true;
1020            }
1021            public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
1022                if (methodDeclaration.selector == assistIdentifier){
1023                    if (methodDeclaration.binding != null) {
1024                        throw new SelectionNodeFound(methodDeclaration.binding);
1025                    } else {
1026                        if (methodDeclaration.scope != null) {
1027                            throw new SelectionNodeFound(new MethodBinding(methodDeclaration.modifiers, methodDeclaration.selector, null, null, null, methodDeclaration.scope.referenceType().binding));
1028                        }
1029                    }
1030                }
1031                return true;
1032            }
1033            public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
1034                if (typeDeclaration.name == assistIdentifier) {
1035                    throw new SelectionNodeFound(typeDeclaration.binding);
1036                }
1037                return true;
1038            }
1039            public boolean visit(TypeParameter typeParameter, BlockScope scope) {
1040                if (typeParameter.name == assistIdentifier) {
1041                    throw new SelectionNodeFound(typeParameter.binding);
1042                }
1043                return true;
1044            }
1045            public boolean visit(TypeParameter typeParameter, ClassScope scope) {
1046                if (typeParameter.name == assistIdentifier) {
1047                    throw new SelectionNodeFound(typeParameter.binding);
1048                }
1049                return true;
1050            }
1051        }
1052        
1053        if (node instanceof AbstractMethodDeclaration) {
1054            ((AbstractMethodDeclaration)node).traverse(new Visitor(), (ClassScope)null);
1055        } else {
1056            ((FieldDeclaration)node).traverse(new Visitor(), (MethodScope)null);
1057        }
1058    }
1059
1060    /**
1061     * Asks the engine to compute the selection of the given type
1062     * from the source type.
1063     *
1064     * @param sourceType org.eclipse.jdt.internal.compiler.env.ISourceType
1065     * a source form of the current type in which code assist is invoked.
1066     *
1067     * @param typeName char[]
1068     * a type name which is to be resolved in the context of a compilation unit.
1069     * NOTE: the type name is supposed to be correctly reduced (no whitespaces, no unicodes left)
1070     *
1071     * @param topLevelTypes SourceTypeElementInfo[]
1072     * a source form of the top level types of the compilation unit in which code assist is invoked.
1073
1074     * @param searchInEnvironment
1075     * if <code>true</code> and no selection could be found in context then search type in environment.
1076     */

1077    public void selectType(ISourceType sourceType, char[] typeName, SourceTypeElementInfo[] topLevelTypes, boolean searchInEnvironment) {
1078        try {
1079            this.acceptedAnswer = false;
1080            
1081            // only the type erasure are returned by IType.resolvedType(...)
1082
if (CharOperation.indexOf('<', typeName) != -1) {
1083                char[] typeSig = Signature.createCharArrayTypeSignature(typeName, false/*not resolved*/);
1084                typeSig = Signature.getTypeErasure(typeSig);
1085                typeName = Signature.toCharArray(typeSig);
1086            }
1087
1088            // find the outer most type
1089
ISourceType outerType = sourceType;
1090            ISourceType parent = sourceType.getEnclosingType();
1091            while (parent != null) {
1092                outerType = parent;
1093                parent = parent.getEnclosingType();
1094            }
1095            // compute parse tree for this most outer type
1096
CompilationResult result = new CompilationResult(outerType.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
1097            if (!(sourceType instanceof SourceTypeElementInfo)) return;
1098            SourceType typeHandle = (SourceType) ((SourceTypeElementInfo)sourceType).getHandle();
1099            int flags = SourceTypeConverter.FIELD_AND_METHOD | SourceTypeConverter.MEMBER_TYPE;
1100            if (typeHandle.isAnonymous() || typeHandle.isLocal())
1101                flags |= SourceTypeConverter.LOCAL_TYPE;
1102            CompilationUnitDeclaration parsedUnit =
1103                SourceTypeConverter.buildCompilationUnit(
1104                        topLevelTypes,
1105                        flags,
1106                        this.parser.problemReporter(),
1107                        result);
1108
1109            if (parsedUnit != null && parsedUnit.types != null) {
1110                if(DEBUG) {
1111                    System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
1112
System.out.println(parsedUnit.toString());
1113                }
1114                // find the type declaration that corresponds to the original source type
1115
TypeDeclaration typeDecl = new ASTNodeFinder(parsedUnit).findType(typeHandle);
1116
1117                if (typeDecl != null) {
1118
1119                    // add fake field with the type we're looking for
1120
// note: since we didn't ask for fields above, there is no field defined yet
1121
FieldDeclaration field = new FieldDeclaration();
1122                    int dot;
1123                    if ((dot = CharOperation.lastIndexOf('.', typeName)) == -1) {
1124                        this.selectedIdentifier = typeName;
1125                        field.type = new SelectionOnSingleTypeReference(typeName, -1);
1126                        // position not used
1127
} else {
1128                        char[][] previousIdentifiers = CharOperation.splitOn('.', typeName, 0, dot);
1129                        char[] selectionIdentifier =
1130                            CharOperation.subarray(typeName, dot + 1, typeName.length);
1131                        this.selectedIdentifier = selectionIdentifier;
1132                        field.type =
1133                            new SelectionOnQualifiedTypeReference(
1134                                previousIdentifiers,
1135                                selectionIdentifier,
1136                                new long[previousIdentifiers.length + 1]);
1137                    }
1138                    field.name = "<fakeField>".toCharArray(); //$NON-NLS-1$
1139
typeDecl.fields = new FieldDeclaration[] { field };
1140
1141                    // build bindings
1142
this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
1143                    if ((this.unitScope = parsedUnit.scope) != null) {
1144                        try {
1145                            // build fields
1146
// note: this builds fields only in the parsed unit (the buildFieldsAndMethods flag is not passed along)
1147
this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
1148
1149                            // resolve
1150
parsedUnit.scope.faultInTypes();
1151                            parsedUnit.resolve();
1152                        } catch (SelectionNodeFound e) {
1153                            if (e.binding != null) {
1154                                if(DEBUG) {
1155                                    System.out.println("SELECTION - Selection binding :"); //$NON-NLS-1$
1156
System.out.println(e.binding.toString());
1157                                }
1158                                // if null then we found a problem in the selection node
1159
selectFrom(e.binding, parsedUnit, e.isDeclaration);
1160                            }
1161                        }
1162                    }
1163                }
1164            }
1165            // only reaches here if no selection could be derived from the parsed tree
1166
// thus use the selected source and perform a textual type search
1167
if (!this.acceptedAnswer && searchInEnvironment) {
1168                if (this.selectedIdentifier != null) {
1169                    this.nameEnvironment.findTypes(typeName, false, false, IJavaSearchConstants.TYPE, this);
1170                    
1171                    // accept qualified types only if no unqualified type was accepted
1172
if(!this.acceptedAnswer) {
1173                        acceptQualifiedTypes();
1174                    }
1175                }
1176            }
1177            if(this.noProposal && this.problem != null) {
1178                this.requestor.acceptError(this.problem);
1179            }
1180        } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
1181
} finally {
1182            reset();
1183        }
1184    }
1185
1186    // Check if a declaration got selected in this unit
1187
private boolean selectDeclaration(CompilationUnitDeclaration compilationUnit){
1188
1189        // the selected identifier is not identical to the parser one (equals but not identical),
1190
// for traversing the parse tree, the parser assist identifier is necessary for identitiy checks
1191
char[] assistIdentifier = this.getParser().assistIdentifier();
1192        if (assistIdentifier == null) return false;
1193        
1194        ImportReference currentPackage = compilationUnit.currentPackage;
1195        char[] packageName = currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(currentPackage.tokens, '.');
1196        // iterate over the types
1197
TypeDeclaration[] types = compilationUnit.types;
1198        for (int i = 0, length = types == null ? 0 : types.length; i < length; i++){
1199            if(selectDeclaration(types[i], assistIdentifier, packageName))
1200                return true;
1201        }
1202        return false;
1203    }
1204
1205    // Check if a declaration got selected in this type
1206
private boolean selectDeclaration(TypeDeclaration typeDeclaration, char[] assistIdentifier, char[] packageName){
1207    
1208        if (typeDeclaration.name == assistIdentifier){
1209            char[] qualifiedSourceName = null;
1210            
1211            TypeDeclaration enclosingType = typeDeclaration;
1212            while(enclosingType != null) {
1213                qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
1214                enclosingType = enclosingType.enclosingType;
1215            }
1216            char[] uniqueKey = typeDeclaration.binding != null ? typeDeclaration.binding.computeUniqueKey() : null;
1217            
1218            this.requestor.acceptType(
1219                packageName,
1220                qualifiedSourceName,
1221                typeDeclaration.modifiers,
1222                true,
1223                uniqueKey,
1224                this.actualSelectionStart,
1225                this.actualSelectionEnd);
1226            
1227            this.noProposal = false;
1228            return true;
1229        }
1230        TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
1231        for (int i = 0, length = memberTypes == null ? 0 : memberTypes.length; i < length; i++){
1232            if(selectDeclaration(memberTypes[i], assistIdentifier, packageName))
1233                return true;
1234        }
1235        FieldDeclaration[] fields = typeDeclaration.fields;
1236        for (int i = 0, length = fields == null ? 0 : fields.length; i < length; i++){
1237            if (fields[i].name == assistIdentifier){
1238                char[] qualifiedSourceName = null;
1239                
1240                TypeDeclaration enclosingType = typeDeclaration;
1241                while(enclosingType != null) {
1242                    qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
1243                    enclosingType = enclosingType.enclosingType;
1244                }
1245                FieldDeclaration field = fields[i];
1246                this.requestor.acceptField(
1247                    packageName,
1248                    qualifiedSourceName,
1249                    field.name,
1250                    true,
1251                    field.binding != null ? field.binding.computeUniqueKey() : null,
1252                    this.actualSelectionStart,
1253                    this.actualSelectionEnd);
1254
1255                this.noProposal = false;
1256                return true;
1257            }
1258        }
1259        AbstractMethodDeclaration[] methods = typeDeclaration.methods;
1260        for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++){
1261            AbstractMethodDeclaration method = methods[i];
1262            
1263            if (method.selector == assistIdentifier){
1264                char[] qualifiedSourceName = null;
1265                
1266                TypeDeclaration enclosingType = typeDeclaration;
1267                while(enclosingType != null) {
1268                    qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
1269                    enclosingType = enclosingType.enclosingType;
1270                }
1271                
1272                this.requestor.acceptMethod(
1273                    packageName,
1274                    qualifiedSourceName,
1275                    null, // SelectionRequestor does not need of declaring type signature for method declaration
1276
method.selector,
1277                    null, // SelectionRequestor does not need of parameters type for method declaration
1278
null, // SelectionRequestor does not need of parameters type for method declaration
1279
null, // SelectionRequestor does not need of parameters type for method declaration
1280
null, // SelectionRequestor does not need of type parameters name for method declaration
1281
null, // SelectionRequestor does not need of type parameters bounds for method declaration
1282
method.isConstructor(),
1283                    true,
1284                    method.binding != null ? method.binding.computeUniqueKey() : null,
1285                    this.actualSelectionStart,
1286                    this.actualSelectionEnd);
1287                
1288                this.noProposal = false;
1289                return true;
1290            }
1291            
1292            TypeParameter[] methodTypeParameters = method.typeParameters();
1293            for (int j = 0, length2 = methodTypeParameters == null ? 0 : methodTypeParameters.length; j < length2; j++){
1294                TypeParameter methodTypeParameter = methodTypeParameters[j];
1295                
1296                if(methodTypeParameter.name == assistIdentifier) {
1297                    char[] qualifiedSourceName = null;
1298                    
1299                    TypeDeclaration enclosingType = typeDeclaration;
1300                    while(enclosingType != null) {
1301                        qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
1302                        enclosingType = enclosingType.enclosingType;
1303                    }
1304                    
1305                    this.requestor.acceptMethodTypeParameter(
1306                        packageName,
1307                        qualifiedSourceName,
1308                        method.selector,
1309                        method.sourceStart,
1310                        method.sourceEnd,
1311                        methodTypeParameter.name,
1312                        true,
1313                        this.actualSelectionStart,
1314                        this.actualSelectionEnd);
1315                    
1316                    this.noProposal = false;
1317                    return true;
1318                }
1319            }
1320        }
1321        
1322        TypeParameter[] typeParameters = typeDeclaration.typeParameters;
1323        for (int i = 0, length = typeParameters == null ? 0 : typeParameters.length; i < length; i++){
1324            TypeParameter typeParameter = typeParameters[i];
1325            if(typeParameter.name == assistIdentifier) {
1326                char[] qualifiedSourceName = null;
1327                
1328                TypeDeclaration enclosingType = typeDeclaration;
1329                while(enclosingType != null) {
1330                    qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
1331                    enclosingType = enclosingType.enclosingType;
1332                }
1333                
1334                this.requestor.acceptTypeParameter(
1335                    packageName,
1336                    qualifiedSourceName,
1337                    typeParameter.name,
1338                    true,
1339                    this.actualSelectionStart,
1340                    this.actualSelectionEnd);
1341                
1342                this.noProposal = false;
1343                return true;
1344            }
1345        }
1346        
1347        return false;
1348    }
1349}
1350
Popular Tags