8d4ed7969765e57192f923579675e13d0e7437fe
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / codeassist / CompletionEngine.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.codeassist;
12
13 import java.util.*;
14
15 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
16 import net.sourceforge.phpdt.internal.compiler.*;
17 import net.sourceforge.phpdt.internal.compiler.env.*;
18
19 import net.sourceforge.phpdt.internal.codeassist.impl.*;
20 import net.sourceforge.phpdt.core.ICompletionRequestor;
21 import net.sourceforge.phpdt.core.IType;
22 //import net.sourceforge.phpdt.core.JavaCore;
23 //import net.sourceforge.phpdt.core.JavaModelException;
24 import net.sourceforge.phpdt.core.compiler.*;
25 import net.sourceforge.phpdt.core.compiler.IProblem;
26 import net.sourceforge.phpdt.internal.codeassist.complete.*;
27
28 import net.sourceforge.phpdt.internal.compiler.ast.*;
29 import net.sourceforge.phpdt.internal.compiler.lookup.*;
30 import net.sourceforge.phpdt.internal.compiler.parser.*;
31 import net.sourceforge.phpdt.internal.compiler.problem.*;
32 import net.sourceforge.phpdt.internal.compiler.util.*;
33 import net.sourceforge.phpdt.internal.core.BasicCompilationUnit;
34 import net.sourceforge.phpdt.internal.core.TypeConverter;
35 import net.sourceforge.phpdt.internal.compiler.impl.*;
36
37 /**
38  * This class is the entry point for source completions.
39  * It contains two public APIs used to call CodeAssist on a given source with
40  * a given environment, assisting position and storage (and possibly options).
41  */
42 public final class CompletionEngine
43         extends Engine
44         implements ISearchRequestor, TypeConstants , ITerminalSymbols , RelevanceConstants {
45         
46         public static boolean DEBUG = false;
47
48         private final static char[] ERROR_PATTERN = "*error*".toCharArray();  //$NON-NLS-1$
49         private final static char[] EXCEPTION_PATTERN = "*exception*".toCharArray();  //$NON-NLS-1$
50         private final static char[] SEMICOLON = new char[] { ';' };
51         TypeBinding[] expectedTypes;
52         
53         boolean assistNodeIsClass;
54         boolean assistNodeIsException;
55         boolean assistNodeIsInterface;
56         
57         CompletionParser parser;
58         ICompletionRequestor requestor;
59         ProblemReporter problemReporter;
60         char[] source;
61         char[] token;
62         boolean resolvingImports = false;
63         boolean insideQualifiedReference = false;
64         int startPosition, actualCompletionPosition, endPosition, offset;
65         HashtableOfObject knownPkgs = new HashtableOfObject(10);
66         HashtableOfObject knownTypes = new HashtableOfObject(10);
67         Scanner nameScanner;
68
69         /*
70                 static final char[][] mainDeclarations =
71                         new char[][] {
72                                 "package".toCharArray(),
73                                 "import".toCharArray(),
74                                 "abstract".toCharArray(),
75                                 "final".toCharArray(),
76                                 "public".toCharArray(),
77                                 "class".toCharArray(),
78                                 "interface".toCharArray()};
79         
80                 static final char[][] modifiers = // may want field, method, type & member type modifiers
81                         new char[][] {
82                                 "abstract".toCharArray(),
83                                 "final".toCharArray(),
84                                 "native".toCharArray(),
85                                 "public".toCharArray(),
86                                 "protected".toCharArray(),
87                                 "private".toCharArray(),
88                                 "static".toCharArray(),
89                                 "strictfp".toCharArray(),
90                                 "synchronized".toCharArray(),
91                                 "transient".toCharArray(),
92                                 "volatile".toCharArray()};
93         */
94         static final char[][] baseTypes = new char[][] { 
95                 "boolean".toCharArray(), //$NON-NLS-1$
96                 "byte".toCharArray(), //$NON-NLS-1$
97                 "char".toCharArray(), //$NON-NLS-1$
98                 "double".toCharArray(), //$NON-NLS-1$
99                 "float".toCharArray(), //$NON-NLS-1$
100                 "int".toCharArray(), //$NON-NLS-1$
101                 "long".toCharArray(), //$NON-NLS-1$
102                 "short".toCharArray(), //$NON-NLS-1$
103                 "void".toCharArray(), //$NON-NLS-1$
104         };
105                 
106         static final char[] classField = "class".toCharArray();  //$NON-NLS-1$
107         static final char[] lengthField = "length".toCharArray();  //$NON-NLS-1$
108         static final char[] THIS = "this".toCharArray();  //$NON-NLS-1$
109         static final char[] THROWS = "throws".toCharArray();  //$NON-NLS-1$
110         
111         static InvocationSite FakeInvocationSite = new InvocationSite(){
112                 public boolean isSuperAccess(){ return false; }
113                 public boolean isTypeAccess(){ return false; }
114                 public void setActualReceiverType(ReferenceBinding receiverType) {}
115                 public void setDepth(int depth){}
116                 public void setFieldIndex(int depth){}
117         };
118
119         /**
120          * The CompletionEngine is responsible for computing source completions.
121          *
122          * It requires a searchable name environment, which supports some
123          * specific search APIs, and a requestor to feed back the results to a UI.
124          *
125          *  @param nameEnvironment net.sourceforge.phpdt.internal.codeassist.ISearchableNameEnvironment
126          *      used to resolve type/package references and search for types/packages
127          *      based on partial names.
128          *
129          *  @param requestor net.sourceforge.phpdt.internal.codeassist.ICompletionRequestor
130          *      since the engine might produce answers of various forms, the engine 
131          *      is associated with a requestor able to accept all possible completions.
132          *
133          *  @param settings java.util.Map
134          *              set of options used to configure the code assist engine.
135          */
136         public CompletionEngine(
137                 ISearchableNameEnvironment nameEnvironment,
138                 ICompletionRequestor requestor,
139                 Map settings) {
140
141                 super(settings);
142                 this.requestor = requestor;
143                 this.nameEnvironment = nameEnvironment;
144
145                 problemReporter = new ProblemReporter(
146                                 DefaultErrorHandlingPolicies.proceedWithAllProblems(),
147                                 this.compilerOptions,
148                                 new DefaultProblemFactory(Locale.getDefault()) {
149                                         public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
150                                                 if (problem.isError() && (problem.getID() & IProblem.Syntax) != 0) {
151                                                         CompletionEngine.this.requestor.acceptError(problem);
152                                                 }
153                                         }
154                                 });
155                 this.parser =
156                         new CompletionParser(problemReporter, this.compilerOptions.assertMode);
157                 this.lookupEnvironment =
158                         new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
159                 this.nameScanner =
160                         new Scanner(false, false, false, this.compilerOptions.assertMode);
161         }
162
163         /**
164          * One result of the search consists of a new class.
165          *
166          * NOTE - All package and type names are presented in their readable form:
167          *    Package names are in the form "a.b.c".
168          *    Nested type names are in the qualified form "A.M".
169          *    The default package is represented by an empty array.
170          */
171         public void acceptClass(char[] packageName, char[] className, int modifiers) {
172
173                 char[] fullyQualifiedName = CharOperation.concat(packageName, className, '.');
174                 char[] completionName = fullyQualifiedName;
175                 
176                 if (this.knownTypes.containsKey(completionName)) return;
177
178                 this.knownTypes.put(completionName, this);
179                 
180                 int relevance = R_DEFAULT;
181                 if (resolvingImports) {
182                         completionName = CharOperation.concat(completionName, SEMICOLON);
183                         relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
184                 } else {
185                         if (!insideQualifiedReference) {
186                                 if (mustQualifyType(packageName, className)) {
187                                         if (packageName == null || packageName.length == 0)
188                                                 if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
189                                                         return; // ignore types from the default package from outside it
190                                 } else {
191                                         completionName = className;
192                                 }
193                         }
194                         relevance += computeRelevanceForCaseMatching(token, className);
195                         relevance += computeRelevanceForExpectingType(packageName, className);
196                         relevance += computeRelevanceForClass();
197                         relevance += computeRelevanceForException(className);
198                 }
199
200                 requestor.acceptClass(
201                         packageName,
202                         className,
203                         completionName,
204                         modifiers,
205                         startPosition - offset,
206                         endPosition - offset,
207                         relevance);
208         }
209         
210         /**
211          * One result of the search consists of a new interface.
212          *
213          * NOTE - All package and type names are presented in their readable form:
214          *    Package names are in the form "a.b.c".
215          *    Nested type names are in the qualified form "A.I".
216          *    The default package is represented by an empty array.
217          */
218         public void acceptInterface(
219                 char[] packageName,
220                 char[] interfaceName,
221                 int modifiers) {
222
223                 char[] fullyQualifiedName = CharOperation.concat(packageName, interfaceName, '.');
224                 char[] completionName = fullyQualifiedName;
225
226                 if (this.knownTypes.containsKey(completionName)) return;
227
228                 this.knownTypes.put(completionName, this);
229
230                 int relevance = R_DEFAULT;
231                 if (resolvingImports) {
232                         completionName = CharOperation.concat(completionName, new char[] { ';' });
233                         relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
234                 } else {
235                         if (!insideQualifiedReference) {
236                                 if (mustQualifyType(packageName, interfaceName)) {
237                                         if (packageName == null || packageName.length == 0)
238                                                 if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
239                                                         return; // ignore types from the default package from outside it
240                                 } else {
241                                         completionName = interfaceName;
242                                 }
243                         }
244                         relevance += computeRelevanceForCaseMatching(token, interfaceName);
245                         relevance += computeRelevanceForExpectingType(packageName, interfaceName);
246                         relevance += computeRelevanceForInterface();
247                 }
248                 
249                 requestor.acceptInterface(
250                         packageName,
251                         interfaceName,
252                         completionName,
253                         modifiers,
254                         startPosition - offset,
255                         endPosition - offset,
256                         relevance);
257         }
258
259         /**
260          * One result of the search consists of a new package.
261          *
262          * NOTE - All package names are presented in their readable form:
263          *    Package names are in the form "a.b.c".
264          *    The default package is represented by an empty array.
265          */
266         public void acceptPackage(char[] packageName) {
267
268                 if (this.knownPkgs.containsKey(packageName)) return;
269
270                 this.knownPkgs.put(packageName, this);
271                 
272                 int relevance = R_DEFAULT;
273                 relevance += computeRelevanceForCaseMatching(token, packageName);
274
275                 requestor.acceptPackage(
276                         packageName,
277                         resolvingImports
278                                 ? CharOperation.concat(packageName, new char[] { '.', '*', ';' })
279                                 : packageName,
280                         startPosition - offset,
281                         endPosition - offset,
282                         relevance);
283         }
284
285         /**
286          * One result of the search consists of a new type.
287          *
288          * NOTE - All package and type names are presented in their readable form:
289          *    Package names are in the form "a.b.c".
290          *    Nested type names are in the qualified form "A.M".
291          *    The default package is represented by an empty array.
292          */
293         public void acceptType(char[] packageName, char[] typeName) {
294
295                 char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.');
296                 char[] completionName = fullyQualifiedName;
297                 
298                 if (this.knownTypes.containsKey(completionName)) return;
299
300                 this.knownTypes.put(completionName, this);
301
302                 int relevance = R_DEFAULT;
303                 if (resolvingImports) {
304                         completionName = CharOperation.concat(completionName, new char[] { ';' });
305                         relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
306                 } else {
307                         if (!insideQualifiedReference) {
308                                 if (mustQualifyType(packageName, typeName)) {
309                                         if (packageName == null || packageName.length == 0)
310                                                 if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
311                                                         return; // ignore types from the default package from outside it
312                                 } else {
313                                         completionName = typeName;
314                                 }
315                         }
316                         relevance += computeRelevanceForCaseMatching(token, typeName);
317                         relevance += computeRelevanceForExpectingType(packageName, typeName);
318                 }
319                 
320                 requestor.acceptType(
321                         packageName,
322                         typeName,
323                         completionName,
324                         startPosition - offset,
325                         endPosition - offset,
326                         relevance);
327         }
328
329         private void complete(AstNode astNode, Binding qualifiedBinding, Scope scope) {
330
331                 setSourceRange(astNode.sourceStart, astNode.sourceEnd);
332                 
333                 if(parser.assistNodeParent != null) {
334                         computeExpectedTypes(parser.assistNodeParent, scope);
335                 }
336
337                 // defaults... some nodes will change these
338                 if (astNode instanceof CompletionOnFieldType) {
339
340                         CompletionOnFieldType field = (CompletionOnFieldType) astNode;
341                         CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type;
342                         token = type.token;
343                         setSourceRange(type.sourceStart, type.sourceEnd);
344                         //              findKeywords(token, modifiers, scope); // could be the start of a field, method or member type
345                         findTypesAndPackages(token, scope);
346                         
347                         if(!field.isLocalVariable && field.modifiers == CompilerModifiers.AccDefault) {
348                                 findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
349                         }
350                 } else {
351                         if(astNode instanceof CompletionOnMethodReturnType) {
352                                 
353                                 CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode;
354                                 SingleTypeReference type = (CompletionOnSingleTypeReference) method.returnType;
355                                 token = type.token;
356                                 setSourceRange(type.sourceStart, type.sourceEnd);
357                                 findTypesAndPackages(token, scope);
358                                 
359                                 if(method.modifiers == CompilerModifiers.AccDefault) {
360                                         findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
361                                 }
362                         } else {
363                                 
364                                 if (astNode instanceof CompletionOnSingleNameReference) {
365         
366                                         token = ((CompletionOnSingleNameReference) astNode).token;
367                                         findVariablesAndMethods(
368                                                 token,
369                                                 scope,
370                                                 (CompletionOnSingleNameReference) astNode,
371                                                 scope);
372                                         // can be the start of a qualified type name
373                                         findTypesAndPackages(token, scope);
374         
375                                 } else {
376         
377                                         if (astNode instanceof CompletionOnSingleTypeReference) {
378         
379                                                 token = ((CompletionOnSingleTypeReference) astNode).token;
380                                                 
381                                                 assistNodeIsClass = astNode instanceof CompletionOnClassReference;
382                                                 assistNodeIsException = astNode instanceof CompletionOnExceptionReference;
383                                                 assistNodeIsInterface = astNode instanceof CompletionOnInterfaceReference;
384         
385                                                 // can be the start of a qualified type name
386                                                 if (qualifiedBinding == null) {
387                                                         findTypesAndPackages(token, scope);
388                                                         } else {
389                                                                 findMemberTypes(
390                                                                 token,
391                                                                 (ReferenceBinding) qualifiedBinding,
392                                                                 scope,
393                                                                 scope.enclosingSourceType());
394                                                 }
395                                         } else {
396                                                 
397                                                 if (astNode instanceof CompletionOnQualifiedNameReference) {
398         
399                                                         insideQualifiedReference = true;
400                                                         CompletionOnQualifiedNameReference ref =
401                                                                 (CompletionOnQualifiedNameReference) astNode;
402                                                         token = ref.completionIdentifier;
403                                                         long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
404         
405                                                         if (qualifiedBinding instanceof VariableBinding) {
406         
407                                                                 setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
408                                                                 TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type;
409                                                                 if (receiverType != null) {
410                                                                         findFieldsAndMethods(token, receiverType, scope, ref, scope,false);
411                                                                 }
412         
413                                                         } else {
414         
415                                                                 if (qualifiedBinding instanceof ReferenceBinding) {
416         
417                                                                         ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
418                                                                         setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
419         
420                                                                         findMemberTypes(token, receiverType, scope, scope.enclosingSourceType());
421         
422                                                                         findClassField(token, (TypeBinding) qualifiedBinding, scope);
423         
424                                                                         findFields(
425                                                                                 token,
426                                                                                 receiverType,
427                                                                                 scope,
428                                                                                 new ObjectVector(),
429                                                                                 new ObjectVector(),
430                                                                                 true,
431                                                                                 ref,
432                                                                                 scope,
433                                                                                 false);
434         
435                                                                         findMethods(
436                                                                                 token,
437                                                                                 null,
438                                                                                 receiverType,
439                                                                                 scope,
440                                                                                 new ObjectVector(),
441                                                                                 true,
442                                                                                 false,
443                                                                                 false,
444                                                                                 ref,
445                                                                                 scope,
446                                                                                 false);
447         
448                                                                 } else {
449         
450                                                                         if (qualifiedBinding instanceof PackageBinding) {
451         
452                                                                                 setSourceRange(astNode.sourceStart, (int) completionPosition);
453                                                                                 // replace to the end of the completion identifier
454                                                                                 findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
455                                                                         }
456                                                                 }
457                                                         }
458         
459                                                 } else {
460         
461                                                                 if (astNode instanceof CompletionOnQualifiedTypeReference) {
462         
463                                                                 insideQualifiedReference = true;
464                                                                 
465                                                                 assistNodeIsClass = astNode instanceof CompletionOnQualifiedClassReference;
466                                                                 assistNodeIsException = astNode instanceof CompletionOnQualifiedExceptionReference;
467                                                                 assistNodeIsInterface = astNode instanceof CompletionOnQualifiedInterfaceReference;
468                                                                 
469                                                                 CompletionOnQualifiedTypeReference ref =
470                                                                         (CompletionOnQualifiedTypeReference) astNode;
471                                                                 token = ref.completionIdentifier;
472                                                                 long completionPosition = ref.sourcePositions[ref.tokens.length];
473         
474                                                                 // get the source positions of the completion identifier
475                                                                 if (qualifiedBinding instanceof ReferenceBinding) {
476         
477                                                                         setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
478                                                                         findMemberTypes(
479                                                                                 token,
480                                                                                 (ReferenceBinding) qualifiedBinding,
481                                                                                 scope,
482                                                                                 scope.enclosingSourceType());
483         
484                                                                 } else {
485         
486                                                                         if (qualifiedBinding instanceof PackageBinding) {
487         
488                                                                                 setSourceRange(astNode.sourceStart, (int) completionPosition);
489                                                                                 // replace to the end of the completion identifier
490                                                                                 findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
491                                                                         }
492                                                                 }
493         
494                                                         } else {
495         
496                                                                 if (astNode instanceof CompletionOnMemberAccess) {
497         
498                                                                         CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode;
499                                                                         long completionPosition = access.nameSourcePosition;
500                                                                         setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
501                                         
502                                                                         token = access.token;
503         
504                                                                         findFieldsAndMethods(
505                                                                                 token,
506                                                                                 (TypeBinding) qualifiedBinding,
507                                                                                 scope,
508                                                                                 access,
509                                                                                 scope,
510                                                                                 false);
511         
512                                                                 } else {
513         
514                                                                         if (astNode instanceof CompletionOnMessageSend) {
515         
516                                                                                 CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
517                                                                                 TypeBinding[] argTypes =
518                                                                                         computeTypes(messageSend.arguments, (BlockScope) scope);
519                                                                                 token = messageSend.selector;
520                                                                                 if (qualifiedBinding == null) {
521                                                                                         
522                                                                                         findImplicitMessageSends(token, argTypes, scope, messageSend, scope);
523                                                                                 } else {
524         
525                                                                                         findMethods(
526                                                                                                 token,
527                                                                                                 argTypes,
528                                                                                                 (ReferenceBinding) qualifiedBinding,
529                                                                                                 scope,
530                                                                                                 new ObjectVector(),
531                                                                                                 false,
532                                                                                                 true,
533                                                                                                 false,
534                                                                                                 messageSend,
535                                                                                                 scope,
536                                                                                                 false);
537                                                                                 }
538         
539                                                                         } else {
540         
541                                                                                 if (astNode instanceof CompletionOnExplicitConstructorCall) {
542         
543                                                                                         CompletionOnExplicitConstructorCall constructorCall =
544                                                                                                 (CompletionOnExplicitConstructorCall) astNode;
545                                                                                         TypeBinding[] argTypes =
546                                                                                                 computeTypes(constructorCall.arguments, (BlockScope) scope);
547                                                                                         findConstructors(
548                                                                                                 (ReferenceBinding) qualifiedBinding,
549                                                                                                 argTypes,
550                                                                                                 scope,
551                                                                                                 constructorCall,
552                                                                                                 false);
553         
554                                                                                 } else {
555         
556                                                                                         if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
557         
558                                                                                                 CompletionOnQualifiedAllocationExpression allocExpression =
559                                                                                                         (CompletionOnQualifiedAllocationExpression) astNode;
560                                                                                                 TypeBinding[] argTypes =
561                                                                                                         computeTypes(allocExpression.arguments, (BlockScope) scope);
562                                                                                                 
563                                                                                                 ReferenceBinding ref = (ReferenceBinding) qualifiedBinding;
564                                                                                                 if(ref.isClass()) {
565                                                                                                         if(!ref.isAbstract()) {
566                                                                                                                 findConstructors(
567                                                                                                                         ref,
568                                                                                                                         argTypes,
569                                                                                                                         scope,
570                                                                                                                         allocExpression,
571                                                                                                                         false);
572                                                                                                         }
573                                                                                                 }
574                                                                                                 if(!ref.isFinal()){
575                                                                                                         findAnonymousType(
576                                                                                                                 ref,
577                                                                                                                 argTypes,
578                                                                                                                 scope,
579                                                                                                                 allocExpression);
580                                                                                                 }
581         
582                                                                                         } else {
583         
584                                                                                                 if (astNode instanceof CompletionOnClassLiteralAccess) {
585                                                                                                         CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode;
586                                                                                                         setSourceRange(access.classStart, access.sourceEnd);
587                                                                         
588                                                                                                         token = access.completionIdentifier;
589                                                                         
590                                                                                                         findClassField(token, (TypeBinding) qualifiedBinding, scope);
591                                                                                                 } else {
592                                                                                                         if(astNode instanceof CompletionOnMethodName) {
593                                                                                                                 CompletionOnMethodName method = (CompletionOnMethodName) astNode;
594                                                                                                                         
595                                                                                                                 setSourceRange(method.sourceStart, method.selectorEnd);
596                                                                                                                         
597                                                                                                                 FieldBinding[] fields = scope.enclosingSourceType().fields();
598                                                                                                                 char[][] excludeNames = new char[fields.length][];
599                                                                                                                 for(int i = 0 ; i < fields.length ; i++){
600                                                                                                                         excludeNames[i] = fields[i].name;
601                                                                                                                 }
602                                                                                                                 
603                                                                                                                 token = method.selector;
604                                                                                                                 
605                                                                                                                 findVariableNames(token, method.returnType, excludeNames);
606                                                                                                         } else {
607                                                                                                                 if (astNode instanceof CompletionOnFieldName) {
608                                                                                                                         CompletionOnFieldName field = (CompletionOnFieldName) astNode;
609                                                                                                                         
610                                                                                                                         FieldBinding[] fields = scope.enclosingSourceType().fields();
611                                                                                                                         char[][] excludeNames = new char[fields.length][];
612                                                                                                                         for(int i = 0 ; i < fields.length ; i++){
613                                                                                                                                 excludeNames[i] = fields[i].name;
614                                                                                                                         }
615                                                                                                                         
616                                                                                                                         token = field.realName;
617                                                                                                                         
618                                                                                                                         findVariableNames(field.realName, field.type, excludeNames);
619                                                                                                                 } else {
620                                                                                                                         if (astNode instanceof CompletionOnLocalName ||
621                                                                                                                                 astNode instanceof CompletionOnArgumentName){
622                                                                                                                                 LocalDeclaration variable = (LocalDeclaration) astNode;
623                                                                                                                                 
624                                                                                                                                 LocalVariableBinding[] locals = ((BlockScope)scope).locals;
625                                                                                                                                 char[][] excludeNames = new char[locals.length][];
626                                                                                                                                 int localCount = 0;
627                                                                                                                                 for(int i = 0 ; i < locals.length ; i++){
628                                                                                                                                         if(locals[i] != null) {
629                                                                                                                                                 excludeNames[localCount++] = locals[i].name;
630                                                                                                                                         }
631                                                                                                                                 }
632                                                                                                                                 System.arraycopy(excludeNames, 0, excludeNames = new char[localCount][], 0, localCount);
633                                                                                                                                 
634                                                                                                                                 if(variable instanceof CompletionOnLocalName){
635                                                                                                                                         token = ((CompletionOnLocalName) variable).realName;
636                                                                                                                                 } else {
637                                                                                                                                         token = ((CompletionOnArgumentName) variable).realName;
638                                                                                                                                 }
639                                                                                                                                 findVariableNames(token, variable.type, excludeNames);
640                                                                                                                         }
641                                                                                                                 }
642                                                                                                         }
643                                                                                                 }
644                                                                                         }
645                                                                                 }
646                                                                         }
647                                                                 }
648                                                         }
649                                                 }
650                                         }
651                                 }
652                         }
653                 }
654         }
655         
656 //      public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){   
657 //              TypeConverter converter = new TypeConverter();
658 //              
659 //              IType topLevelType = type;
660 //              while(topLevelType.getDeclaringType() != null) {
661 //                      topLevelType = topLevelType.getDeclaringType();
662 //              }
663 //              
664 //              CompilationResult compilationResult = new CompilationResult((topLevelType.getElementName() + ".java").toCharArray(), 1, 1, this.compilerOptions.maxProblemsPerUnit); //$NON-NLS-1$
665 //      
666 //              CompilationUnitDeclaration compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, 0);
667 //      
668 //              try {
669 //                      TypeDeclaration typeDeclaration = converter.buildTypeDeclaration(type, compilationUnit, compilationResult, problemReporter);
670 //              
671 //                      if(typeDeclaration != null) {   
672 //                              // build AST from snippet
673 //                              Initializer fakeInitializer = parseSnippeInitializer(snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
674 //                              
675 //                              // merge AST
676 //                              FieldDeclaration[] oldFields = typeDeclaration.fields;
677 //                              FieldDeclaration[] newFields = new FieldDeclaration[oldFields.length + 1];
678 //                              System.arraycopy(oldFields, 0, newFields, 0, oldFields.length);
679 //                              newFields[oldFields.length] = fakeInitializer;
680 //                              typeDeclaration.fields = newFields;
681 //              
682 //                              if(DEBUG) {
683 //                                      System.out.println("SNIPPET COMPLETION AST :"); //$NON-NLS-1$
684 //                                      System.out.println(compilationUnit.toString());
685 //                              }
686 //                              
687 //                              if (compilationUnit.types != null) {
688 //                                      try {
689 //                                              lookupEnvironment.buildTypeBindings(compilationUnit);
690 //                              
691 //                                              if ((unitScope = compilationUnit.scope) != null) {
692 //                                                      lookupEnvironment.completeTypeBindings(compilationUnit, true);
693 //                                                      compilationUnit.scope.faultInTypes();
694 //                                                      compilationUnit.resolve();
695 //                                              }
696 //                                      } catch (CompletionNodeFound e) {
697 //                                              //                                      completionNodeFound = true;
698 //                                              if (e.astNode != null) {
699 //                                                      // if null then we found a problem in the completion node
700 //                                                      complete(e.astNode, e.qualifiedBinding, e.scope);
701 //                                              }
702 //                                      }
703 //                              }
704 //                      }
705 //              } catch(JavaModelException e) {
706 //                      // Do nothing
707 //              }
708 //      }
709         
710 //      private Initializer parseSnippeInitializer(char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
711 //              StringBuffer prefix = new StringBuffer();
712 //              prefix.append("public class FakeType {\n "); //$NON-NLS-1$
713 //              if(isStatic) {
714 //                      prefix.append("static "); //$NON-NLS-1$
715 //              }
716 //              prefix.append("{\n"); //$NON-NLS-1$
717 //              for (int i = 0; i < localVariableTypeNames.length; i++) {
718 //                      prefix.append(AstNode.modifiersString(localVariableModifiers[i]));
719 //                      prefix.append(' ');
720 //                      prefix.append(localVariableTypeNames[i]);
721 //                      prefix.append(' ');
722 //                      prefix.append(localVariableNames[i]);
723 //                      prefix.append(';');
724 //              }
725 //              
726 //              char[] fakeSource = CharOperation.concat(prefix.toString().toCharArray(), snippet, "}}".toCharArray());//$NON-NLS-1$ 
727 //              offset = prefix.length();
728 //              
729 //              String encoding = JavaCore.getOption(JavaCore.CORE_ENCODING);
730 //              BasicCompilationUnit fakeUnit = new BasicCompilationUnit(
731 //                      fakeSource, 
732 //                      null,
733 //                      "FakeType.java", //$NON-NLS-1$
734 //                      encoding); 
735 //                      
736 //              actualCompletionPosition = prefix.length() + position - 1;
737 //                      
738 //              CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
739 //              CompilationUnitDeclaration fakeAST = parser.dietParse(fakeUnit, fakeResult, actualCompletionPosition);
740 //              
741 //              parseMethod(fakeAST, actualCompletionPosition);
742 //              
743 //              return (Initializer)fakeAST.types[0].fields[0];
744 //      }
745
746         /**
747          * Ask the engine to compute a completion at the specified position
748          * of the given compilation unit.
749          *
750          *  @return void
751          *      completion results are answered through a requestor.
752          *
753          *  @param sourceUnit net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit
754          *      the source of the current compilation unit.
755          *
756          *  @param completionPosition int
757          *      a position in the source where the completion is taking place. 
758          *      This position is relative to the source provided.
759          */
760         public void complete(ICompilationUnit sourceUnit, int completionPosition, int offset) {
761
762                 if(DEBUG) {
763                         System.out.print("COMPLETION IN "); //$NON-NLS-1$
764                         System.out.print(sourceUnit.getFileName());
765                         System.out.print(" AT POSITION "); //$NON-NLS-1$
766                         System.out.println(completionPosition);
767                         System.out.println("COMPLETION - Source :"); //$NON-NLS-1$
768                         System.out.println(sourceUnit.getContents());
769                 }
770                 try {
771                         actualCompletionPosition = completionPosition - 1;
772                         this.offset = offset;
773                         // for now until we can change the UI.
774                         CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
775                         CompilationUnitDeclaration parsedUnit = parser.dietParse(sourceUnit, result, actualCompletionPosition);
776
777                         //              boolean completionNodeFound = false;
778                         if (parsedUnit != null) {
779                                 if(DEBUG) {
780                                         System.out.println("COMPLETION - Diet AST :"); //$NON-NLS-1$
781                                         System.out.println(parsedUnit.toString());
782                                 }
783
784                                 // scan the package & import statements first
785                                 if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
786                                         findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
787                                         return;
788                                 }
789
790                                 ImportReference[] imports = parsedUnit.imports;
791                                 if (imports != null) {
792                                         for (int i = 0, length = imports.length; i < length; i++) {
793                                                 ImportReference importReference = imports[i];
794                                                 if (importReference instanceof CompletionOnImportReference) {
795                                                         findImports((CompletionOnImportReference) importReference);
796                                                         return;
797                                                 }
798                                         }
799                                 }
800
801                                 if (parsedUnit.types != null) {
802                                         try {
803                                                 lookupEnvironment.buildTypeBindings(parsedUnit);
804
805                                                 if ((unitScope = parsedUnit.scope) != null) {
806                                                         source = sourceUnit.getContents();
807                                                         lookupEnvironment.completeTypeBindings(parsedUnit, true);
808                                                         parsedUnit.scope.faultInTypes();
809                                                         parseMethod(parsedUnit, actualCompletionPosition);
810                                                         if(DEBUG) {
811                                                                 System.out.println("COMPLETION - AST :"); //$NON-NLS-1$
812                                                                 System.out.println(parsedUnit.toString());
813                                                         }
814                                                         parsedUnit.resolve();
815                                                 }
816                                         } catch (CompletionNodeFound e) {
817                                                 //                                      completionNodeFound = true;
818                                                 if (e.astNode != null) {
819                                                         if(DEBUG) {
820                                                                 System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
821                                                                 System.out.println(e.astNode.toString());
822                                                         }
823                                                         // if null then we found a problem in the completion node
824                                                         complete(e.astNode, e.qualifiedBinding, e.scope);
825                                                 }
826                                         }
827                                 }
828                         }
829
830                         /* Ignore package, import, class & interface keywords for now...
831                                         if (!completionNodeFound) {
832                                                 if (parsedUnit == null || parsedUnit.types == null) {
833                                                         // this is not good enough... can still be trying to define a second type
834                                                         CompletionScanner scanner = (CompletionScanner) parser.scanner;
835                                                         setSourceRange(scanner.completedIdentifierStart, scanner.completedIdentifierEnd);
836                                                         findKeywords(scanner.completionIdentifier, mainDeclarations, null);
837                                                 }
838                                                 // currently have no way to know if extends/implements are possible keywords
839                                         }
840                         */
841                 } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
842                 } catch (InvalidCursorLocation e) { // may eventually report a usefull error
843                 } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
844                 } catch (CompletionNodeFound e){ // internal failure - bugs 5618
845                 } finally {
846                         reset();
847                 }
848         }
849
850         private TypeBinding[] computeTypes(Expression[] arguments, BlockScope scope) {
851
852                 if (arguments == null)
853                         return null;
854
855                 int argsLength = arguments.length;
856                 TypeBinding[] argTypes = new TypeBinding[argsLength];
857                 for (int a = argsLength; --a >= 0;)
858                         argTypes[a] = arguments[a].resolveType(scope);
859                 return argTypes;
860         }
861         
862         private void findAnonymousType(
863                 ReferenceBinding currentType,
864                 TypeBinding[] argTypes,
865                 Scope scope,
866                 InvocationSite invocationSite) {
867
868                 if (currentType.isInterface()) {
869                         char[] completion = TypeConstants.NoChar;
870                         // nothing to insert - do not want to replace the existing selector & arguments
871                         if (source == null
872                                 || source.length <= endPosition
873                                 || source[endPosition] != ')')
874                                 completion = new char[] { ')' };
875                         
876                         requestor.acceptAnonymousType(
877                                 currentType.qualifiedPackageName(),
878                                 currentType.qualifiedSourceName(),
879                                 TypeConstants.NoCharChar,
880                                 TypeConstants.NoCharChar,
881                                 TypeConstants.NoCharChar,
882                                 completion,
883                                 IConstants.AccPublic,
884                                 endPosition - offset,
885                                 endPosition - offset,
886                                 R_DEFAULT);
887                 } else {
888                         findConstructors(
889                                 currentType,
890                                 argTypes,
891                                 scope,
892                                 invocationSite,
893                                 true);
894                 }
895         }
896
897         private void findClassField(char[] token, TypeBinding receiverType, Scope scope) {
898
899                 if (token == null)
900                         return;
901
902                 if (token.length <= classField.length
903                         && CharOperation.prefixEquals(token, classField, false /* ignore case */
904                 )) {
905                         int relevance = R_DEFAULT;
906                         relevance += computeRelevanceForCaseMatching(token, classField);
907                         relevance += computeRelevanceForExpectingType(scope.getJavaLangClass());
908                                 
909                         requestor.acceptField(
910                                 NoChar,
911                                 NoChar,
912                                 classField,
913                                 NoChar,
914                                 NoChar,
915                                 classField,
916                                 CompilerModifiers.AccStatic | CompilerModifiers.AccPublic,
917                                 startPosition - offset,
918                                 endPosition - offset,
919                                 relevance);
920                 }
921         }
922
923         private void findConstructors(
924                 ReferenceBinding currentType,
925                 TypeBinding[] argTypes,
926                 Scope scope,
927                 InvocationSite invocationSite,
928                 boolean forAnonymousType) {
929
930                 // No visibility checks can be performed without the scope & invocationSite
931                 MethodBinding[] methods = currentType.availableMethods();
932                 if(methods != null) {
933                         int minArgLength = argTypes == null ? 0 : argTypes.length;
934                         next : for (int f = methods.length; --f >= 0;) {
935                                 MethodBinding constructor = methods[f];
936                                 if (constructor.isConstructor()) {
937                                         
938                                         if (constructor.isSynthetic()) continue next;
939                                                 
940                                         if (options.checkVisibility
941                                                 && !constructor.canBeSeenBy(invocationSite, scope)) continue next;
942         
943                                         TypeBinding[] parameters = constructor.parameters;
944                                         int paramLength = parameters.length;
945                                         if (minArgLength > paramLength)
946                                                 continue next;
947                                         for (int a = minArgLength; --a >= 0;)
948                                                 if (argTypes[a] != null) // can be null if it could not be resolved properly
949                                                         if (!scope.areTypesCompatible(argTypes[a], constructor.parameters[a]))
950                                                                 continue next;
951         
952                                         char[][] parameterPackageNames = new char[paramLength][];
953                                         char[][] parameterTypeNames = new char[paramLength][];
954                                         for (int i = 0; i < paramLength; i++) {
955                                                 TypeBinding type = parameters[i];
956                                                 parameterPackageNames[i] = type.qualifiedPackageName();
957                                                 parameterTypeNames[i] = type.qualifiedSourceName();
958                                         }
959                                         char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames);
960                                         
961                                         char[] completion = TypeConstants.NoChar;
962                                         // nothing to insert - do not want to replace the existing selector & arguments
963                                         if (source == null
964                                                 || source.length <= endPosition
965                                                 || source[endPosition] != ')')
966                                                 completion = new char[] { ')' };
967                                         
968                                         if(forAnonymousType){
969                                                 requestor.acceptAnonymousType(
970                                                         currentType.qualifiedPackageName(),
971                                                         currentType.qualifiedSourceName(),
972                                                         parameterPackageNames,
973                                                         parameterTypeNames,
974                                                         parameterNames,
975                                                         completion,
976                                                         constructor.modifiers,
977                                                         endPosition - offset,
978                                                         endPosition - offset,
979                                                         R_DEFAULT);
980                                         } else {
981                                                 requestor.acceptMethod(
982                                                         currentType.qualifiedPackageName(),
983                                                         currentType.qualifiedSourceName(),
984                                                         currentType.sourceName(),
985                                                         parameterPackageNames,
986                                                         parameterTypeNames,
987                                                         parameterNames,
988                                                         TypeConstants.NoChar,
989                                                         TypeConstants.NoChar,
990                                                         completion,
991                                                         constructor.modifiers,
992                                                         endPosition - offset,
993                                                         endPosition - offset,
994                                                         R_DEFAULT);
995                                         }
996                                 }
997                         }
998                 }
999         }
1000         
1001         // Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
1002         private void findFields(
1003                 char[] fieldName,
1004                 FieldBinding[] fields,
1005                 Scope scope,
1006                 ObjectVector fieldsFound,
1007                 ObjectVector localsFound,
1008                 boolean onlyStaticFields,
1009                 ReferenceBinding receiverType,
1010                 InvocationSite invocationSite,
1011                 Scope invocationScope,
1012                 boolean implicitCall) {
1013
1014                 // Inherited fields which are hidden by subclasses are filtered out
1015                 // No visibility checks can be performed without the scope & invocationSite
1016                 
1017                 int fieldLength = fieldName.length;
1018                 next : for (int f = fields.length; --f >= 0;) {                 
1019                         FieldBinding field = fields[f];
1020
1021                         if (field.isSynthetic())        continue next;
1022
1023                         if (onlyStaticFields && !field.isStatic()) continue next;
1024
1025                         if (fieldLength > field.name.length) continue next;
1026
1027                         if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */))        continue next;
1028
1029                         if (options.checkVisibility
1030                                 && !field.canBeSeenBy(receiverType, invocationSite, scope))     continue next;
1031
1032                         boolean prefixRequired = false;
1033
1034                         for (int i = fieldsFound.size; --i >= 0;) {
1035                                 Object[] other = (Object[])fieldsFound.elementAt(i);
1036                                 FieldBinding otherField = (FieldBinding) other[0];
1037                                 ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
1038                                 if (field == otherField && receiverType == otherReceiverType)
1039                                         continue next;
1040                                 if (CharOperation.equals(field.name, otherField.name, true)) {
1041                                         if (field.declaringClass.isSuperclassOf(otherField.declaringClass))
1042                                                 continue next;
1043                                         if (otherField.declaringClass.isInterface())
1044                                                 if (field.declaringClass.implementsInterface(otherField.declaringClass, true))
1045                                                         continue next;
1046                                         if (field.declaringClass.isInterface())
1047                                                 if (otherField.declaringClass.implementsInterface(field.declaringClass, true))
1048                                                         continue next;
1049                                         prefixRequired = true;
1050                                 }
1051                         }
1052
1053                         for (int l = localsFound.size; --l >= 0;) {
1054                                 LocalVariableBinding local = (LocalVariableBinding) localsFound.elementAt(l);   
1055
1056                                 if (CharOperation.equals(field.name, local.name, true)) {
1057                                         SourceTypeBinding declarationType = scope.enclosingSourceType();
1058                                         if (declarationType.isAnonymousType() && declarationType != invocationScope.enclosingSourceType()) {
1059                                                 continue next;
1060                                         }
1061                                         prefixRequired = true;
1062                                         break;
1063                                 }
1064                         }
1065                         
1066                         fieldsFound.add(new Object[]{field, receiverType});
1067                         
1068                         char[] completion = field.name;
1069                         
1070                         if(prefixRequired || options.forceImplicitQualification){
1071                                 char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), field.isStatic());
1072                                 completion = CharOperation.concat(prefix,completion,'.');
1073                         }
1074
1075                         int relevance = R_DEFAULT;
1076                         relevance += computeRelevanceForCaseMatching(fieldName, field.name);
1077                         relevance += computeRelevanceForExpectingType(field.type);
1078
1079                         requestor
1080                                 .acceptField(
1081                                         field.declaringClass.qualifiedPackageName(),
1082                                         field.declaringClass.qualifiedSourceName(),
1083                                         field.name,
1084                                         field.type.qualifiedPackageName(),
1085                                         field.type.qualifiedSourceName(),
1086                                         completion,
1087                         // may include some qualification to resolve ambiguities
1088                         field.modifiers, startPosition - offset, endPosition - offset,
1089                         relevance);
1090                 }
1091         }
1092
1093         private void findFields(
1094                 char[] fieldName,
1095                 ReferenceBinding receiverType,
1096                 Scope scope,
1097                 ObjectVector fieldsFound,
1098                 ObjectVector localsFound,
1099                 boolean onlyStaticFields,
1100                 InvocationSite invocationSite,
1101                 Scope invocationScope,
1102                 boolean implicitCall) {
1103
1104                 if (fieldName == null)
1105                         return;
1106
1107                 ReferenceBinding currentType = receiverType;
1108                 ReferenceBinding[][] interfacesToVisit = null;
1109                 int lastPosition = -1;
1110                 do {
1111
1112                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1113                         if (itsInterfaces != NoSuperInterfaces) {
1114
1115                                 if (interfacesToVisit == null)
1116                                         interfacesToVisit = new ReferenceBinding[5][];
1117
1118                                 if (++lastPosition == interfacesToVisit.length)
1119                                         System.arraycopy(
1120                                                 interfacesToVisit,
1121                                                 0,
1122                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1123                                                 0,
1124                                                 lastPosition);
1125                                 interfacesToVisit[lastPosition] = itsInterfaces;
1126                         }
1127
1128                         FieldBinding[] fields = currentType.availableFields();
1129                         if(fields != null) {
1130                                 findFields(
1131                                         fieldName,
1132                                         fields,
1133                                         scope,
1134                                         fieldsFound,
1135                                         localsFound,
1136                                         onlyStaticFields,
1137                                         receiverType,
1138                                         invocationSite,
1139                                         invocationScope,
1140                                         implicitCall);
1141                         }
1142                         currentType = currentType.superclass();
1143                 } while (currentType != null);
1144
1145                 if (interfacesToVisit != null) {
1146                         for (int i = 0; i <= lastPosition; i++) {
1147                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
1148                                 for (int j = 0, length = interfaces.length; j < length; j++) {
1149
1150                                         ReferenceBinding anInterface = interfaces[j];
1151                                         if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) {
1152                                                 // if interface as not already been visited
1153                                                 anInterface.tagBits |= TagBits.InterfaceVisited;
1154
1155                                                 FieldBinding[] fields = anInterface.availableFields();
1156                                                 if(fields !=  null) {
1157                                                         findFields(
1158                                                                 fieldName,
1159                                                                 fields,
1160                                                                 scope,
1161                                                                 fieldsFound,
1162                                                                 localsFound,
1163                                                                 onlyStaticFields,
1164                                                                 receiverType,
1165                                                                 invocationSite,
1166                                                                 invocationScope,
1167                                                                 implicitCall);
1168                                                 }
1169
1170                                                 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
1171                                                 if (itsInterfaces != NoSuperInterfaces) {
1172                                                         if (++lastPosition == interfacesToVisit.length)
1173                                                                 System.arraycopy(
1174                                                                         interfacesToVisit,
1175                                                                         0,
1176                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1177                                                                         0,
1178                                                                         lastPosition);
1179                                                         interfacesToVisit[lastPosition] = itsInterfaces;
1180                                                 }
1181                                         }
1182                                 }
1183                         }
1184
1185                         // bit reinitialization
1186                         for (int i = 0; i <= lastPosition; i++) {
1187                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
1188                                 for (int j = 0, length = interfaces.length; j < length; j++)
1189                                         interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
1190                         }
1191                 }
1192         }
1193
1194         private void findFieldsAndMethods(
1195                 char[] token,
1196                 TypeBinding receiverType,
1197                 Scope scope,
1198                 InvocationSite invocationSite,
1199                 Scope invocationScope,
1200                 boolean implicitCall) {
1201
1202                 if (token == null)
1203                         return;
1204
1205                 if (receiverType.isBaseType())
1206                         return; // nothing else is possible with base types
1207
1208                 if (receiverType.isArrayType()) {
1209                         if (token.length <= lengthField.length
1210                                 && CharOperation.prefixEquals(token, lengthField, false /* ignore case */
1211                         )) {
1212                                 
1213                                 int relevance = R_DEFAULT;
1214                                 relevance += computeRelevanceForCaseMatching(token,lengthField);
1215                                 relevance += computeRelevanceForExpectingType(BaseTypes.IntBinding);
1216                                 
1217                                 requestor.acceptField(
1218                                         NoChar,
1219                                         NoChar,
1220                                         lengthField,
1221                                         NoChar,
1222                                         NoChar,
1223                                         lengthField,
1224                                         CompilerModifiers.AccPublic,
1225                                         startPosition - offset,
1226                                         endPosition - offset,
1227                                         relevance);
1228                         }
1229                         receiverType = scope.getJavaLangObject();
1230                 }
1231
1232                 findFields(
1233                         token,
1234                         (ReferenceBinding) receiverType,
1235                         scope,
1236                         new ObjectVector(),
1237                         new ObjectVector(),
1238                         false,
1239                         invocationSite,
1240                         invocationScope,
1241                         implicitCall);
1242
1243                 findMethods(
1244                         token,
1245                         null,
1246                         (ReferenceBinding) receiverType,
1247                         scope,
1248                         new ObjectVector(),
1249                         false,
1250                         false,
1251                         false,
1252                         invocationSite,
1253                         invocationScope,
1254                         implicitCall);
1255         }
1256
1257         private void findImports(CompletionOnImportReference importReference) {
1258                 char[][] tokens = importReference.tokens;
1259                         
1260                 char[] importName = CharOperation.concatWith(tokens, '.');
1261                 
1262                 if (importName.length == 0)
1263                         return;
1264                         
1265                 char[] lastToken = tokens[tokens.length - 1];
1266                 if(lastToken != null && lastToken.length == 0)
1267                         importName = CharOperation.concat(importName, new char[]{'.'});
1268
1269                 resolvingImports = true;
1270                 setSourceRange(
1271                         importReference.sourceStart,
1272                         importReference.declarationSourceEnd);
1273                         
1274                 token =  importName;
1275                 // want to replace the existing .*;
1276                 nameEnvironment.findPackages(importName, this);
1277                 nameEnvironment.findTypes(importName, this);
1278         }
1279
1280         // what about onDemand types? Ignore them since it does not happen!
1281         // import p1.p2.A.*;
1282         private void findKeywords(char[] keyword, char[][] choices, Scope scope) {
1283
1284                 int length = keyword.length;
1285                 if (length > 0)
1286                         for (int i = 0; i < choices.length; i++)
1287                                 if (length <= choices[i].length
1288                                         && CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */
1289                                 )){
1290                                         int relevance = R_DEFAULT;
1291                                         relevance += computeRelevanceForCaseMatching(keyword, choices[i]);
1292                                         
1293                                         requestor.acceptKeyword(choices[i], startPosition - offset, endPosition - offset,relevance);
1294                                 }
1295         }
1296
1297         // Helper method for findMemberTypes(char[], ReferenceBinding, Scope)
1298         private void findMemberTypes(
1299                 char[] typeName,
1300                 ReferenceBinding[] memberTypes,
1301                 ObjectVector typesFound,
1302                 ReferenceBinding receiverType,
1303                 SourceTypeBinding invocationType) {
1304
1305                 // Inherited member types which are hidden by subclasses are filtered out
1306                 // No visibility checks can be performed without the scope & invocationSite
1307                 int typeLength = typeName.length;
1308                 next : for (int m = memberTypes.length; --m >= 0;) {
1309                         ReferenceBinding memberType = memberTypes[m];
1310                         //              if (!wantClasses && memberType.isClass()) continue next;
1311                         //              if (!wantInterfaces && memberType.isInterface()) continue next;
1312                         if (typeLength > memberType.sourceName.length)
1313                                 continue next;
1314
1315                         if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false
1316                                 /* ignore case */
1317                                 ))
1318                                 continue next;
1319
1320                         if (options.checkVisibility
1321                                 && !memberType.canBeSeenBy(receiverType, invocationType))
1322                                 continue next;
1323
1324                         for (int i = typesFound.size; --i >= 0;) {
1325                                 ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i);
1326
1327                                 if (memberType == otherType)
1328                                         continue next;
1329
1330                                 if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)) {
1331
1332                                         if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType()))
1333                                                 continue next;
1334
1335                                         if (otherType.enclosingType().isInterface())
1336                                                 if (memberType.enclosingType()
1337                                                         .implementsInterface(otherType.enclosingType(), true))
1338                                                         continue next;
1339
1340                                         if (memberType.enclosingType().isInterface())
1341                                                 if (otherType.enclosingType()
1342                                                         .implementsInterface(memberType.enclosingType(), true))
1343                                                         continue next;
1344                                 }
1345                         }
1346
1347                         typesFound.add(memberType);
1348
1349                         int relevance = R_DEFAULT;
1350                         relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName);
1351                         relevance += computeRelevanceForExpectingType(memberType);
1352
1353                         if (memberType.isClass()) {
1354                                 relevance += computeRelevanceForClass();
1355                                 requestor.acceptClass(
1356                                         memberType.qualifiedPackageName(),
1357                                         memberType.qualifiedSourceName(),
1358                                         memberType.sourceName(),
1359                                         memberType.modifiers,
1360                                         startPosition - offset,
1361                                         endPosition - offset,
1362                                         relevance);
1363
1364                         } else {
1365                                 relevance += computeRelevanceForInterface();
1366                                 requestor.acceptInterface(
1367                                         memberType.qualifiedPackageName(),
1368                                         memberType.qualifiedSourceName(),
1369                                         memberType.sourceName(),
1370                                         memberType.modifiers,
1371                                         startPosition - offset,
1372                                         endPosition - offset,
1373                                         relevance);
1374                         }
1375                 }
1376         }
1377
1378         private void findMemberTypes(
1379                 char[] typeName,
1380                 ReferenceBinding receiverType,
1381                 Scope scope,
1382                 SourceTypeBinding typeInvocation) {
1383
1384                 ReferenceBinding currentType = receiverType;
1385                 if (typeName == null)
1386                         return;
1387
1388                 if (currentType.superInterfaces() == null)
1389                         return; // we're trying to find a supertype
1390
1391                 ObjectVector typesFound = new ObjectVector();
1392                 if (insideQualifiedReference
1393                         || typeName.length == 0) { // do not search up the hierarchy
1394
1395                         findMemberTypes(
1396                                 typeName,
1397                                 currentType.memberTypes(),
1398                                 typesFound,
1399                                 receiverType,
1400                                 typeInvocation);
1401                         return;
1402                 }
1403
1404                 ReferenceBinding[][] interfacesToVisit = null;
1405                 int lastPosition = -1;
1406
1407                 do {
1408
1409                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1410                         if (itsInterfaces != NoSuperInterfaces) {
1411
1412                                 if (interfacesToVisit == null)
1413                                         interfacesToVisit = new ReferenceBinding[5][];
1414
1415                                 if (++lastPosition == interfacesToVisit.length)
1416                                         System.arraycopy(
1417                                                 interfacesToVisit,
1418                                                 0,
1419                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1420                                                 0,
1421                                                 lastPosition);
1422                                 interfacesToVisit[lastPosition] = itsInterfaces;
1423                         }
1424
1425                         findMemberTypes(
1426                                 typeName,
1427                                 currentType.memberTypes(),
1428                                 typesFound,
1429                                 receiverType,
1430                                 typeInvocation);
1431                         currentType = currentType.superclass();
1432
1433                 } while (currentType != null);
1434
1435                 if (interfacesToVisit != null) {
1436                         for (int i = 0; i <= lastPosition; i++) {
1437                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
1438                                 for (int j = 0, length = interfaces.length; j < length; j++) {
1439
1440                                         ReferenceBinding anInterface = interfaces[j];
1441                                         if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) {
1442                                                 // if interface as not already been visited
1443                                                 anInterface.tagBits |= TagBits.InterfaceVisited;
1444
1445                                                 findMemberTypes(
1446                                                         typeName,
1447                                                         anInterface.memberTypes(),
1448                                                         typesFound,
1449                                                         receiverType,
1450                                                         typeInvocation);
1451
1452                                                 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
1453                                                 if (itsInterfaces != NoSuperInterfaces) {
1454
1455                                                         if (++lastPosition == interfacesToVisit.length)
1456                                                                 System.arraycopy(
1457                                                                         interfacesToVisit,
1458                                                                         0,
1459                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1460                                                                         0,
1461                                                                         lastPosition);
1462                                                         interfacesToVisit[lastPosition] = itsInterfaces;
1463                                                 }
1464                                         }
1465                                 }
1466                         }
1467
1468                         // bit reinitialization
1469                         for (int i = 0; i <= lastPosition; i++) {
1470                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
1471                                 for (int j = 0, length = interfaces.length; j < length; j++)
1472                                         interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
1473                         }
1474                 }
1475         }
1476
1477         private void findIntefacesMethods(
1478                 char[] selector,
1479                 TypeBinding[] argTypes,
1480                 ReferenceBinding receiverType,
1481                 ReferenceBinding[] itsInterfaces,
1482                 Scope scope,
1483                 ObjectVector methodsFound,
1484                 boolean onlyStaticMethods,
1485                 boolean exactMatch,
1486                 boolean isCompletingDeclaration,
1487                 InvocationSite invocationSite,
1488                 Scope invocationScope,
1489                 boolean implicitCall) {
1490
1491                 if (selector == null)
1492                         return;
1493
1494                 if (itsInterfaces != NoSuperInterfaces) {
1495                         ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
1496                         int lastPosition = 0;
1497                         interfacesToVisit[lastPosition] = itsInterfaces;
1498                         
1499                         for (int i = 0; i <= lastPosition; i++) {
1500                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
1501
1502                                 for (int j = 0, length = interfaces.length; j < length; j++) {
1503                                         ReferenceBinding currentType = interfaces[j];
1504
1505                                         if ((currentType.tagBits & TagBits.InterfaceVisited) == 0) {
1506                                                 // if interface as not already been visited
1507                                                 currentType.tagBits |= TagBits.InterfaceVisited;
1508
1509                                                 MethodBinding[] methods = currentType.availableMethods();
1510                                                 if(methods != null) {
1511                                                         if(isCompletingDeclaration){
1512         
1513                                                                 findLocalMethodDeclarations(
1514                                                                         selector,
1515                                                                         methods,
1516                                                                         scope,
1517                                                                         methodsFound,
1518                                                                         onlyStaticMethods,
1519                                                                         exactMatch,
1520                                                                         receiverType);
1521         
1522                                                         } else {
1523         
1524                                                                 findLocalMethods(
1525                                                                         selector,
1526                                                                         argTypes,
1527                                                                         methods,
1528                                                                         scope,
1529                                                                         methodsFound,
1530                                                                         onlyStaticMethods,
1531                                                                         exactMatch,
1532                                                                         receiverType,
1533                                                                         invocationSite,
1534                                                                         invocationScope,
1535                                                                         implicitCall);
1536                                                         }
1537                                                 }
1538
1539                                                 itsInterfaces = currentType.superInterfaces();
1540                                                 if (itsInterfaces != NoSuperInterfaces) {
1541
1542                                                         if (++lastPosition == interfacesToVisit.length)
1543                                                                 System.arraycopy(
1544                                                                         interfacesToVisit,
1545                                                                         0,
1546                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1547                                                                         0,
1548                                                                         lastPosition);
1549                                                         interfacesToVisit[lastPosition] = itsInterfaces;
1550                                                 }
1551                                         }
1552                                 }
1553                         }
1554
1555                         // bit reinitialization
1556                         for (int i = 0; i <= lastPosition; i++) {
1557                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
1558
1559                                 for (int j = 0, length = interfaces.length; j < length; j++){
1560                                         interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
1561                                 }
1562                         }
1563                 }
1564         }
1565         
1566         private void findImplicitMessageSends(
1567                 char[] token,
1568                 TypeBinding[] argTypes,
1569                 Scope scope,
1570                 InvocationSite invocationSite,
1571                 Scope invocationScope) {
1572
1573                 if (token == null)
1574                         return;
1575
1576                 boolean staticsOnly = false;
1577                 // need to know if we're in a static context (or inside a constructor)
1578                 ObjectVector methodsFound = new ObjectVector();
1579
1580                 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1581
1582                         switch (scope.kind) {
1583
1584                                 case Scope.METHOD_SCOPE :
1585                                         // handle the error case inside an explicit constructor call (see MethodScope>>findField)
1586                                         MethodScope methodScope = (MethodScope) scope;
1587                                         staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
1588                                         break;
1589
1590                                 case Scope.CLASS_SCOPE :
1591                                         ClassScope classScope = (ClassScope) scope;
1592                                         SourceTypeBinding enclosingType = classScope.referenceContext.binding;
1593                                         findMethods(
1594                                                 token,
1595                                                 argTypes,
1596                                                 enclosingType,
1597                                                 classScope,
1598                                                 methodsFound,
1599                                                 staticsOnly,
1600                                                 true,
1601                                                 false,
1602                                                 invocationSite,
1603                                                 invocationScope,
1604                                                 true);
1605                                         staticsOnly |= enclosingType.isStatic();
1606                                         break;
1607
1608                                 case Scope.COMPILATION_UNIT_SCOPE :
1609                                         break done;
1610                         }
1611                         scope = scope.parent;
1612                 }
1613         }
1614
1615         // Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean)
1616         private void findLocalMethods(
1617                 char[] methodName,
1618                 TypeBinding[] argTypes,
1619                 MethodBinding[] methods,
1620                 Scope scope,
1621                 ObjectVector methodsFound,
1622                 boolean onlyStaticMethods,
1623                 boolean exactMatch,
1624                 ReferenceBinding receiverType,
1625                 InvocationSite invocationSite,
1626                 Scope invocationScope,
1627                 boolean implicitCall) {
1628
1629                 // Inherited methods which are hidden by subclasses are filtered out
1630                 // No visibility checks can be performed without the scope & invocationSite
1631
1632                 int methodLength = methodName.length;
1633                 int minArgLength = argTypes == null ? 0 : argTypes.length;
1634
1635                 next : for (int f = methods.length; --f >= 0;) {
1636                         MethodBinding method = methods[f];
1637
1638                         if (method.isSynthetic()) continue next;
1639
1640                         if (method.isDefaultAbstract()) continue next;
1641
1642                         if (method.isConstructor()) continue next;
1643
1644                         //              if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
1645                         if (onlyStaticMethods && !method.isStatic()) continue next;
1646
1647                         if (options.checkVisibility
1648                                 && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
1649
1650                         if (exactMatch) {
1651                                 if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
1652                                         ))
1653                                         continue next;
1654
1655                         } else {
1656
1657                                 if (methodLength > method.selector.length)
1658                                         continue next;
1659
1660                                 if (!CharOperation.prefixEquals(methodName, method.selector, false
1661                                         /* ignore case */
1662                                         ))
1663                                         continue next;
1664                         }
1665                         if (minArgLength > method.parameters.length)
1666                                 continue next;
1667
1668                         for (int a = minArgLength; --a >= 0;){
1669                                 if (argTypes[a] != null){ // can be null if it could not be resolved properly
1670                                         if (!scope.areTypesCompatible(argTypes[a], method.parameters[a])) {
1671                                                 continue next;
1672                                         }
1673                                 }
1674                         }
1675                         
1676                         boolean prefixRequired = false;
1677                         
1678                         for (int i = methodsFound.size; --i >= 0;) {
1679                                 Object[] other = (Object[]) methodsFound.elementAt(i);
1680                                 MethodBinding otherMethod = (MethodBinding) other[0];
1681                                 ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
1682                                 if (method == otherMethod && receiverType == otherReceiverType)
1683                                         continue next;
1684
1685                                 if (CharOperation.equals(method.selector, otherMethod.selector, true)
1686                                         && method.areParametersEqual(otherMethod)) {
1687
1688                                         if (method.declaringClass.isSuperclassOf(otherMethod.declaringClass))
1689                                                 continue next;
1690
1691                                         if (otherMethod.declaringClass.isInterface())
1692                                                 if (method
1693                                                         .declaringClass
1694                                                         .implementsInterface(otherMethod.declaringClass, true))
1695                                                         continue next;
1696
1697                                         if (method.declaringClass.isInterface())
1698                                                 if(otherMethod
1699                                                         .declaringClass
1700                                                         .implementsInterface(method.declaringClass,true))
1701                                                         continue next;
1702                                         prefixRequired = true;
1703                                 }
1704                         }
1705
1706                         methodsFound.add(new Object[]{method, receiverType});
1707                         int length = method.parameters.length;
1708                         char[][] parameterPackageNames = new char[length][];
1709                         char[][] parameterTypeNames = new char[length][];
1710
1711                         for (int i = 0; i < length; i++) {
1712                                 TypeBinding type = method.parameters[i];
1713                                 parameterPackageNames[i] = type.qualifiedPackageName();
1714                                 parameterTypeNames[i] = type.qualifiedSourceName();
1715                         }
1716                         char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
1717
1718                         char[] completion = TypeConstants.NoChar;
1719                         
1720                         int previousStartPosition = startPosition;
1721                         
1722                         // nothing to insert - do not want to replace the existing selector & arguments
1723                         if (!exactMatch) {
1724                                 if (source != null
1725                                         && source.length > endPosition
1726                                         && source[endPosition] == '(')
1727                                         completion = method.selector;
1728                                 else
1729                                         completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
1730                         } else {
1731                                 if(prefixRequired && (source != null)) {
1732                                         completion = CharOperation.subarray(source, startPosition, endPosition);
1733                                 } else {
1734                                         startPosition = endPosition;
1735                                 }
1736                         }
1737                         
1738                         if(prefixRequired || options.forceImplicitQualification){
1739                                 char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), method.isStatic());
1740                                 completion = CharOperation.concat(prefix,completion,'.');
1741                         }
1742
1743                         int relevance = R_DEFAULT;
1744                         relevance += computeRelevanceForCaseMatching(methodName, method.selector);
1745                         relevance += computeRelevanceForExpectingType(method.returnType);
1746
1747                         requestor.acceptMethod(
1748                                 method.declaringClass.qualifiedPackageName(),
1749                                 method.declaringClass.qualifiedSourceName(),
1750                                 method.selector,
1751                                 parameterPackageNames,
1752                                 parameterTypeNames,
1753                                 parameterNames,
1754                                 method.returnType.qualifiedPackageName(),
1755                                 method.returnType.qualifiedSourceName(),
1756                                 completion,
1757                                 method.modifiers,
1758                                 startPosition - offset,
1759                                 endPosition - offset,
1760                                 relevance);
1761                         startPosition = previousStartPosition;
1762                 }
1763         }
1764         
1765         private int computeRelevanceForCaseMatching(char[] token, char[] proposalName){
1766                 if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) {
1767                         return  R_CASE;
1768                 } else {
1769                         return R_DEFAULT;
1770                 }
1771         }
1772         private int computeRelevanceForClass(){
1773                 if(assistNodeIsClass) {
1774                         return R_CLASS;
1775                 }
1776                 return 0;
1777         }
1778         private int computeRelevanceForInterface(){
1779                 if(assistNodeIsInterface) {
1780                         return R_INTERFACE;
1781                 }
1782                 return R_DEFAULT;
1783         }
1784         private int computeRelevanceForException(char[] proposalName){
1785                 
1786                 if(assistNodeIsException &&
1787                         (CharOperation.match(EXCEPTION_PATTERN, proposalName, false) ||
1788                         CharOperation.match(ERROR_PATTERN, proposalName, false))) { 
1789                         return R_EXCEPTION;
1790                 }
1791                 return R_DEFAULT;
1792         }
1793         private int computeRelevanceForExpectingType(TypeBinding proposalType){
1794                 if(expectedTypes != null && proposalType != null) {
1795                         for (int i = 0; i < expectedTypes.length; i++) {
1796                                 if(Scope.areTypesCompatible(proposalType, expectedTypes[i])) {
1797                                         return R_EXPECTED_TYPE;
1798                                 }
1799                         }
1800                 } 
1801                 return R_DEFAULT;
1802         }
1803         private int computeRelevanceForExpectingType(char[] packageName, char[] typeName){
1804                 if(expectedTypes != null) {
1805                         for (int i = 0; i < expectedTypes.length; i++) {
1806                                 if(CharOperation.equals(expectedTypes[i].qualifiedPackageName(), packageName) &&
1807                                         CharOperation.equals(expectedTypes[i].qualifiedSourceName(), typeName)) {
1808                                         return R_EXPECTED_TYPE;
1809                                 }
1810                         }
1811                 } 
1812                 return R_DEFAULT;
1813         }
1814
1815         // Helper method for findMethods(char[], MethodBinding[], Scope, ObjectVector, boolean, boolean, boolean, TypeBinding)
1816         private void findLocalMethodDeclarations(
1817                 char[] methodName,
1818                 MethodBinding[] methods,
1819                 Scope scope,
1820                 ObjectVector methodsFound,
1821                 //      boolean noVoidReturnType, how do you know?
1822                 boolean onlyStaticMethods,
1823                 boolean exactMatch,
1824                 ReferenceBinding receiverType) {
1825
1826                 // Inherited methods which are hidden by subclasses are filtered out
1827                 // No visibility checks can be performed without the scope & invocationSite
1828                 int methodLength = methodName.length;
1829                 next : for (int f = methods.length; --f >= 0;) {
1830
1831                         MethodBinding method = methods[f];
1832                         if (method.isSynthetic())       continue next;
1833                                 
1834                         if (method.isDefaultAbstract()) continue next;
1835                         
1836                         if (method.isConstructor()) continue next;
1837                                 
1838                         if (method.isFinal()) continue next;
1839
1840                         //              if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
1841                         if (onlyStaticMethods && !method.isStatic()) continue next;
1842
1843                         if (options.checkVisibility
1844                                 && !method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next;
1845
1846                         if (exactMatch) {
1847                                 if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
1848                                         ))
1849                                         continue next;
1850
1851                         } else {
1852
1853                                 if (methodLength > method.selector.length)
1854                                         continue next;
1855
1856                                 if (!CharOperation.prefixEquals(methodName, method.selector, false
1857                                         /* ignore case */
1858                                         ))
1859                                         continue next;
1860                         }
1861
1862                         for (int i = methodsFound.size; --i >= 0;) {
1863                                 MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i);
1864                                 if (method == otherMethod)
1865                                         continue next;
1866
1867                                 if (CharOperation.equals(method.selector, otherMethod.selector, true)
1868                                         && method.areParametersEqual(otherMethod)) {
1869                                         continue next;
1870                                 }
1871                         }
1872
1873                         methodsFound.add(method);
1874                         
1875                         int length = method.parameters.length;
1876                         char[][] parameterPackageNames = new char[length][];
1877                         char[][] parameterTypeNames = new char[length][];
1878                         
1879                         for (int i = 0; i < length; i++) {
1880                                 TypeBinding type = method.parameters[i];
1881                                 parameterPackageNames[i] = type.qualifiedPackageName();
1882                                 parameterTypeNames[i] = type.qualifiedSourceName();
1883                         }
1884
1885                         char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
1886                         
1887                         StringBuffer completion = new StringBuffer(10);
1888                         // flush uninteresting modifiers
1889                         int insertedModifiers = method.modifiers & ~(CompilerModifiers.AccNative | CompilerModifiers.AccAbstract);
1890
1891                         if (!exactMatch) {
1892                                 if(insertedModifiers != CompilerModifiers.AccDefault){
1893                                         completion.append(AstNode.modifiersString(insertedModifiers));
1894                                 }
1895                                 char[] returnPackageName = method.returnType.qualifiedPackageName();
1896                                 char[] returnTypeName = method.returnType.qualifiedSourceName();
1897                                 if(mustQualifyType(returnPackageName, returnTypeName)) {
1898                                         completion.append(CharOperation.concat(returnPackageName, returnTypeName,'.'));
1899                                 } else {
1900                                         completion.append(method.returnType.sourceName());
1901                                 }
1902                                 completion.append(' ');
1903                                 completion.append(method.selector);
1904                                 completion.append('(');
1905
1906                                 for(int i = 0; i < length ; i++){
1907                                         if(mustQualifyType(parameterPackageNames[i], parameterTypeNames[i])){
1908                                                 completion.append(CharOperation.concat(parameterPackageNames[i], parameterTypeNames[i], '.'));
1909                                         } else {
1910                                                 completion.append(parameterTypeNames[i]);
1911                                         }
1912                                         completion.append(' ');
1913                                         if(parameterNames != null){
1914                                                 completion.append(parameterNames[i]);
1915                                         } else {
1916                                                 completion.append('%');
1917                                         }
1918                                         if(i != (length - 1))
1919                                                 completion.append(','); 
1920                                 }
1921                                 completion.append(')');
1922                                 
1923                                 ReferenceBinding[] exceptions = method.thrownExceptions;
1924                                 
1925                                 if (exceptions != null && exceptions.length > 0){
1926                                         completion.append(' ');
1927                                         completion.append(THROWS);
1928                                         completion.append(' ');
1929                                         for(int i = 0; i < exceptions.length ; i++){
1930                                                 ReferenceBinding exception = exceptions[i];
1931
1932                                                 char[] exceptionPackageName = exception.qualifiedPackageName();
1933                                                 char[] exceptionTypeName = exception.qualifiedSourceName();
1934                                                 
1935                                                 if(i != 0){
1936                                                         completion.append(',');
1937                                                         completion.append(' ');
1938                                                 }
1939                                                 
1940                                                 if(mustQualifyType(exceptionPackageName, exceptionTypeName)){
1941                                                         completion.append(CharOperation.concat(exceptionPackageName, exceptionTypeName, '.'));
1942                                                 } else {
1943                                                         completion.append(exception.sourceName());
1944                                                 }
1945                                         }
1946                                 }
1947                         }
1948
1949                         int relevance = R_DEFAULT;
1950                         relevance += computeRelevanceForCaseMatching(methodName, method.selector);
1951
1952                         requestor.acceptMethodDeclaration(
1953                                 method.declaringClass.qualifiedPackageName(),
1954                                 method.declaringClass.qualifiedSourceName(),
1955                                 method.selector,
1956                                 parameterPackageNames,
1957                                 parameterTypeNames,
1958                                 parameterNames,
1959                                 method.returnType.qualifiedPackageName(),
1960                                 method.returnType.qualifiedSourceName(),
1961                                 completion.toString().toCharArray(),
1962                                 method.modifiers,
1963                                 startPosition - offset,
1964                                 endPosition - offset,
1965                                 relevance);
1966                 }
1967         }
1968         private void findMethods(
1969                 char[] selector,
1970                 TypeBinding[] argTypes,
1971                 ReferenceBinding receiverType,
1972                 Scope scope,
1973                 ObjectVector methodsFound,
1974                 boolean onlyStaticMethods,
1975                 boolean exactMatch,
1976                 boolean isCompletingDeclaration,
1977                 InvocationSite invocationSite,
1978                 Scope invocationScope,
1979                 boolean implicitCall) {
1980                 if (selector == null)
1981                         return;
1982                 
1983                 if(isCompletingDeclaration) {
1984                         MethodBinding[] methods = receiverType.availableMethods();
1985                         if (methods != null){
1986                                 for (int i = 0; i < methods.length; i++) {
1987                                         if(!methods[i].isDefaultAbstract()) {
1988                                                 methodsFound.add(methods[i]);
1989                                         }
1990                                 }
1991                         }
1992                 }
1993                 
1994                 ReferenceBinding currentType = receiverType;
1995                 if (receiverType.isInterface()) {
1996                         if(isCompletingDeclaration) {
1997                                 findIntefacesMethods(
1998                                         selector,
1999                                         argTypes,
2000                                         receiverType,
2001                                         currentType.superInterfaces(),
2002                                         scope,
2003                                         methodsFound,
2004                                         onlyStaticMethods,
2005                                         exactMatch,
2006                                         isCompletingDeclaration,
2007                                         invocationSite,
2008                                         invocationScope,
2009                                         implicitCall);
2010                         } else {
2011                                 findIntefacesMethods(
2012                                         selector,
2013                                         argTypes,
2014                                         receiverType,
2015                                         new ReferenceBinding[]{currentType},
2016                                         scope,
2017                                         methodsFound,
2018                                         onlyStaticMethods,
2019                                         exactMatch,
2020                                         isCompletingDeclaration,
2021                                         invocationSite,
2022                                         invocationScope,
2023                                         implicitCall);
2024                         }
2025                         
2026                         currentType = scope.getJavaLangObject();
2027                 } else {
2028                         if(isCompletingDeclaration){
2029                                 findIntefacesMethods(
2030                                         selector,
2031                                         argTypes,
2032                                         receiverType,
2033                                         currentType.superInterfaces(),
2034                                         scope,
2035                                         methodsFound,
2036                                         onlyStaticMethods,
2037                                         exactMatch,
2038                                         isCompletingDeclaration,
2039                                         invocationSite,
2040                                         invocationScope,
2041                                         implicitCall);
2042                                 
2043                                 currentType = receiverType.superclass();
2044                         }
2045                 }
2046                 boolean hasPotentialDefaultAbstractMethods = true;
2047                 while (currentType != null) {
2048                         
2049                         MethodBinding[] methods = currentType.availableMethods();
2050                         if(methods != null) {
2051                                 if(isCompletingDeclaration){
2052                                         findLocalMethodDeclarations(
2053                                                 selector,
2054                                                 methods,
2055                                                 scope,
2056                                                 methodsFound,
2057                                                 onlyStaticMethods,
2058                                                 exactMatch,
2059                                                 receiverType);
2060                                 } else{
2061                                         findLocalMethods(
2062                                                 selector,
2063                                                 argTypes,
2064                                                 methods,
2065                                                 scope,
2066                                                 methodsFound,
2067                                                 onlyStaticMethods,
2068                                                 exactMatch,
2069                                                 receiverType,
2070                                                 invocationSite,
2071                                                 invocationScope,
2072                                                 implicitCall);
2073                                 }
2074                         }
2075                         
2076                         if(hasPotentialDefaultAbstractMethods && currentType.isAbstract()){
2077                                 findIntefacesMethods(
2078                                         selector,
2079                                         argTypes,
2080                                         receiverType,
2081                                         currentType.superInterfaces(),
2082                                         scope,
2083                                         methodsFound,
2084                                         onlyStaticMethods,
2085                                         exactMatch,
2086                                         isCompletingDeclaration,
2087                                         invocationSite,
2088                                         invocationScope,
2089                                         implicitCall);
2090                         } else {
2091                                 hasPotentialDefaultAbstractMethods = false;
2092                         }
2093                         currentType = currentType.superclass();
2094                 }
2095         }
2096         private char[][] findMethodParameterNames(MethodBinding method, char[][] parameterTypeNames){
2097                 ReferenceBinding bindingType = method.declaringClass;
2098
2099                 char[][] parameterNames = null;
2100                 
2101                 int length = parameterTypeNames.length;
2102
2103                 if (length == 0){
2104                         return TypeConstants.NoCharChar;
2105                 }
2106                 // look into the corresponding unit if it is available
2107                 if (bindingType instanceof SourceTypeBinding){
2108                         SourceTypeBinding sourceType = (SourceTypeBinding) bindingType;
2109
2110                         if (sourceType.scope != null){
2111                                 TypeDeclaration parsedType;
2112
2113                                 if ((parsedType = sourceType.scope.referenceContext) != null){
2114                                         AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method);
2115
2116                                         if (methodDecl != null){
2117                                                 Argument[] arguments = methodDecl.arguments;
2118                                                 parameterNames = new char[length][];
2119
2120                                                 for(int i = 0 ; i < length ; i++){
2121                                                         parameterNames[i] = arguments[i].name;
2122                                                 }
2123                                         }
2124                                 }
2125                         }
2126                 }
2127                 // look into the model          
2128                 if(parameterNames == null){
2129                         NameEnvironmentAnswer answer = nameEnvironment.findType(bindingType.compoundName);
2130
2131                         if(answer != null){
2132                                 if(answer.isSourceType()) {
2133                                         ISourceType sourceType = answer.getSourceTypes()[0];
2134                                         ISourceMethod[] sourceMethods = sourceType.getMethods();
2135                                         int len = sourceMethods == null ? 0 : sourceMethods.length;
2136                                         for(int i = 0; i < len ; i++){
2137                                                 ISourceMethod sourceMethod = sourceMethods[i];
2138                                                 char[][] argTypeNames = sourceMethod.getArgumentTypeNames();
2139
2140                                                 if(argTypeNames != null &&
2141                                                         CharOperation.equals(method.selector,sourceMethod.getSelector()) &&
2142                                                         CharOperation.equals(argTypeNames,parameterTypeNames)){
2143                                                         parameterNames = sourceMethod.getArgumentNames();
2144                                                         break;
2145                                                 }
2146                                         }
2147                                 } 
2148                         }
2149                 }
2150                 return parameterNames;
2151         }
2152         
2153         private void findNestedTypes(
2154                 char[] typeName,
2155                 SourceTypeBinding currentType,
2156                 Scope scope) {
2157                 if (typeName == null)
2158                         return;
2159
2160                 int typeLength = typeName.length;
2161
2162                 while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found
2163
2164                         switch (scope.kind) {
2165
2166                                 case Scope.METHOD_SCOPE :
2167                                 case Scope.BLOCK_SCOPE :
2168                                         BlockScope blockScope = (BlockScope) scope;
2169
2170                                         next : for (int i = 0, length = blockScope.scopeIndex; i < length; i++) {
2171
2172                                                 if (blockScope.subscopes[i] instanceof ClassScope) {
2173                                                         SourceTypeBinding localType =
2174                                                                 ((ClassScope) blockScope.subscopes[i]).referenceContext.binding;
2175
2176                                                         if (!localType.isAnonymousType()) {
2177                                                                 if (typeLength > localType.sourceName.length)
2178                                                                         continue next;
2179                                                                 if (!CharOperation.prefixEquals(typeName, localType.sourceName, false
2180                                                                         /* ignore case */
2181                                                                         ))
2182                                                                         continue next;
2183
2184                                                                 int relevance = R_DEFAULT;
2185                                                                 relevance += computeRelevanceForCaseMatching(typeName, localType.sourceName);
2186                                                                 relevance += computeRelevanceForExpectingType(localType);
2187                                                                 relevance += computeRelevanceForClass();
2188                                                                 
2189                                                                 requestor.acceptClass(
2190                                                                         localType.qualifiedPackageName(),
2191                                                                         localType.sourceName,
2192                                                                         localType.sourceName,
2193                                                                         localType.modifiers,
2194                                                                         startPosition - offset,
2195                                                                         endPosition - offset,
2196                                                                         relevance);
2197                                                         }
2198                                                 }
2199                                         }
2200                                         break;
2201
2202                                 case Scope.CLASS_SCOPE :
2203                                         findMemberTypes(typeName, scope.enclosingSourceType(), scope, currentType);
2204                                         if (typeLength == 0)
2205                                                 return; // do not search outside the class scope if no prefix was provided
2206                                         break;
2207
2208                                 case Scope.COMPILATION_UNIT_SCOPE :
2209                                         return;
2210                         }
2211                         scope = scope.parent;
2212                 }
2213         }
2214
2215         private void findPackages(CompletionOnPackageReference packageStatement) {
2216
2217                 token = CharOperation.concatWith(packageStatement.tokens, '.');
2218                 if (token.length == 0)
2219                         return;
2220
2221                 setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
2222                 nameEnvironment.findPackages(CharOperation.toLowerCase(token), this);
2223         }
2224
2225         private void findTypesAndPackages(char[] token, Scope scope) {
2226
2227                 if (token == null)
2228                         return;
2229
2230                 if (scope.enclosingSourceType() != null)
2231                         findNestedTypes(token, scope.enclosingSourceType(), scope);
2232
2233                 if (unitScope != null) {
2234                         int typeLength = token.length;
2235                         SourceTypeBinding[] types = unitScope.topLevelTypes;
2236
2237                         for (int i = 0, length = types.length; i < length; i++) {
2238                                 SourceTypeBinding sourceType = types[i]; 
2239
2240                                 if (typeLength > sourceType.sourceName.length)  continue;
2241                                 
2242                                 if (!CharOperation.prefixEquals(token, sourceType.sourceName, false))   continue;
2243
2244                                 int relevance = R_DEFAULT;
2245                                 relevance += computeRelevanceForCaseMatching(token, sourceType.sourceName);
2246                                 relevance += computeRelevanceForExpectingType(sourceType);
2247
2248                                 if (sourceType.isClass()){
2249                                         relevance += computeRelevanceForClass();
2250                                         requestor.acceptClass(
2251                                                 sourceType.qualifiedPackageName(),
2252                                                 sourceType.sourceName(),
2253                                                 sourceType.sourceName(),
2254                                                 sourceType.modifiers,
2255                                                 startPosition - offset, 
2256                                                 endPosition - offset,
2257                                                 relevance);
2258                                 } else {
2259                                         relevance += computeRelevanceForInterface();
2260                                         requestor.acceptInterface(
2261                                                 sourceType.qualifiedPackageName(),
2262                                                 sourceType.sourceName(),
2263                                                 sourceType.sourceName(),
2264                                                 sourceType.modifiers,
2265                                                 startPosition - offset,
2266                                                 endPosition - offset,
2267                                                 relevance);
2268                                 }
2269                         }
2270                 }
2271
2272                 if (token.length == 0)
2273                         return;
2274
2275                 findKeywords(token, baseTypes, scope);
2276                 nameEnvironment.findTypes(token, this);
2277                 nameEnvironment.findPackages(token, this);
2278         }
2279
2280         private void findTypesAndSubpackages(
2281                 char[] token,
2282                 PackageBinding packageBinding) {
2283
2284                 char[] qualifiedName =
2285                         CharOperation.concatWith(packageBinding.compoundName, token, '.');
2286
2287                 if (token == null || token.length == 0) {
2288                         int length = qualifiedName.length;
2289                         System.arraycopy(
2290                                 qualifiedName,
2291                                 0,
2292                                 qualifiedName = new char[length + 1],
2293                                 0,
2294                                 length);
2295                         qualifiedName[length] = '.';
2296                 }
2297                 nameEnvironment.findTypes(qualifiedName, this);
2298                 nameEnvironment.findPackages(qualifiedName, this);
2299         }
2300
2301         private void findVariablesAndMethods(
2302                 char[] token,
2303                 Scope scope,
2304                 InvocationSite invocationSite,
2305                 Scope invocationScope) {
2306
2307                 if (token == null)
2308                         return;
2309
2310                 // Should local variables hide fields from the receiver type or any of its enclosing types?
2311                 // we know its an implicit field/method access... see BlockScope getBinding/getImplicitMethod
2312
2313                 boolean staticsOnly = false;
2314                 // need to know if we're in a static context (or inside a constructor)
2315                 int tokenLength = token.length;
2316
2317                 ObjectVector localsFound = new ObjectVector();
2318                 ObjectVector fieldsFound = new ObjectVector();
2319                 ObjectVector methodsFound = new ObjectVector();
2320
2321                 Scope currentScope = scope;
2322
2323                 done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
2324
2325                         switch (currentScope.kind) {
2326
2327                                 case Scope.METHOD_SCOPE :
2328                                         // handle the error case inside an explicit constructor call (see MethodScope>>findField)
2329                                         MethodScope methodScope = (MethodScope) currentScope;
2330                                         staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
2331
2332                                 case Scope.BLOCK_SCOPE :
2333                                         BlockScope blockScope = (BlockScope) currentScope;
2334
2335                                         next : for (int i = 0, length = blockScope.locals.length; i < length; i++) {
2336                                                 LocalVariableBinding local = blockScope.locals[i];
2337
2338                                                 if (local == null)
2339                                                         break next;
2340
2341                                                 if (tokenLength > local.name.length)
2342                                                         continue next;
2343
2344                                                 if (!CharOperation.prefixEquals(token, local.name, false /* ignore case */
2345                                                         ))
2346                                                         continue next;
2347
2348                                                 if (local.isSecret())
2349                                                         continue next;
2350
2351                                                 for (int f = 0; f < localsFound.size; f++) {
2352                                                         LocalVariableBinding otherLocal =
2353                                                                 (LocalVariableBinding) localsFound.elementAt(f);
2354                                                         if (CharOperation.equals(otherLocal.name, local.name, true))
2355                                                                 continue next;
2356                                                 }
2357                                                 localsFound.add(local);
2358
2359                                                 int relevance = R_DEFAULT;
2360                                                 relevance += computeRelevanceForCaseMatching(token, local.name);
2361                                                 relevance += computeRelevanceForExpectingType(local.type);
2362                                                 
2363                                                 requestor.acceptLocalVariable(
2364                                                         local.name,
2365                                                         local.type == null 
2366                                                                 ? NoChar
2367                                                                 : local.type.qualifiedPackageName(),
2368                                                         local.type == null
2369                                                                 ? local.declaration.type.toString().toCharArray()
2370                                                                 : local.type.qualifiedSourceName(),
2371                                                         local.modifiers,
2372                                                         startPosition - offset,
2373                                                         endPosition - offset,
2374                                                         relevance);
2375                                         }
2376                                         break;
2377
2378                                 case Scope.COMPILATION_UNIT_SCOPE :
2379                                         break done1;
2380                         }
2381                         currentScope = currentScope.parent;
2382                 }
2383
2384                 currentScope = scope;
2385
2386                 done2 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
2387
2388                         switch (currentScope.kind) {
2389
2390                                 case Scope.CLASS_SCOPE :
2391                                         ClassScope classScope = (ClassScope) currentScope;
2392                                         SourceTypeBinding enclosingType = classScope.referenceContext.binding;
2393                                         /*                              if (tokenLength == 0) { // only search inside the type itself if no prefix was provided
2394                                                                                 findFields(token, enclosingType.fields(), classScope, fieldsFound, staticsOnly);
2395                                                                                 findMethods(token, enclosingType.methods(), classScope, methodsFound, staticsOnly, false);
2396                                                                                 break done;
2397                                                                         } else { */
2398                                         findFields(
2399                                                 token,
2400                                                 enclosingType,
2401                                                 classScope,
2402                                                 fieldsFound,
2403                                                 localsFound,
2404                                                 staticsOnly,
2405                                                 invocationSite,
2406                                                 invocationScope,
2407                                                 true);
2408
2409                                         findMethods(
2410                                                 token,
2411                                                 null,
2412                                                 enclosingType,
2413                                                 classScope,
2414                                                 methodsFound,
2415                                                 staticsOnly,
2416                                                 false,
2417                                                 false,
2418                                                 invocationSite,
2419                                                 invocationScope,
2420                                                 true);
2421                                         staticsOnly |= enclosingType.isStatic();
2422                                         //                              }
2423                                         break;
2424
2425                                 case Scope.COMPILATION_UNIT_SCOPE :
2426                                         break done2;
2427                         }
2428                         currentScope = currentScope.parent;
2429                 }
2430         }
2431
2432         // Helper method for private void findVariableNames(char[] name, TypeReference type )
2433         private void findVariableName(char[] token, char[] qualifiedPackageName, char[] qualifiedSourceName, char[] sourceName, char[][] excludeNames, int dim){
2434                         if(sourceName == null || sourceName.length == 0)
2435                                 return;
2436                                 
2437                         char[] name = null;
2438                         
2439                         // compute variable name for base type
2440                         try{
2441                                 nameScanner.setSource(sourceName);
2442         nameScanner.getNextToken();  // switch (nameScanner.getNextToken()) {
2443 //                                      case TokenNameint :
2444 //                                      case TokenNamebyte :
2445 //                                      case TokenNameshort :
2446 //                                      case TokenNamechar :
2447 //                                      case TokenNamelong :
2448 //                                      case TokenNamefloat :
2449 //                                      case TokenNamedouble :
2450 //                                      case TokenNameboolean :
2451 //                                              if(token != null && token.length != 0)
2452 //                                                      return;
2453 //                                              name = computeBaseNames(sourceName[0], excludeNames);
2454 //                                              break;
2455 //                              }
2456                                 if(name != null) {
2457                                         int relevance = R_DEFAULT;
2458                                         relevance += computeRelevanceForCaseMatching(token, name);
2459                                         
2460                                         // accept result
2461                                         requestor.acceptVariableName(
2462                                                 qualifiedPackageName,
2463                                                 qualifiedSourceName,
2464                                                 name,
2465                                                 name,
2466                                                 startPosition - offset,
2467                                                 endPosition - offset,
2468                                                 relevance);
2469                                         return;
2470                                 }
2471                         } catch(InvalidInputException e){
2472                         }
2473                         
2474                         // compute variable name for non base type
2475                         char[][] names = computeNames(sourceName, dim > 0);
2476                         char[] displayName;
2477                         if (dim > 0){
2478                                 int l = qualifiedSourceName.length;
2479                                 displayName = new char[l+(2*dim)];
2480                                 System.arraycopy(qualifiedSourceName, 0, displayName, 0, l);
2481                                 for(int i = 0; i < dim; i++){
2482                                         displayName[l+(i*2)] = '[';
2483                                         displayName[l+(i*2)+1] = ']';
2484                                 }
2485                         } else {
2486                                 displayName = qualifiedSourceName;
2487                         }
2488                         next : for(int i = 0 ; i < names.length ; i++){
2489                                 name = names[i];
2490                                 
2491                                 if (!CharOperation.prefixEquals(token, name, false))
2492                                         continue next;
2493                                 
2494                                 // completion must be an identifier (not a keyword, ...).
2495                                 try{
2496                                         nameScanner.setSource(name);
2497                                         if(nameScanner.getNextToken() != TokenNameIdentifier)
2498                                                 continue next;
2499                                 } catch(InvalidInputException e){
2500                                         continue next;
2501                                 }
2502                                 
2503                                 int count = 2;
2504                                 char[] originalName = name;
2505                                 for(int j = 0 ; j < excludeNames.length ; j++){
2506                                         if(CharOperation.equals(name, excludeNames[j], false)) {
2507                                                 name = CharOperation.concat(originalName, String.valueOf(count++).toCharArray());
2508                                                 j = 0;
2509                                         }       
2510                                 }
2511                                 
2512                                 int relevance = R_DEFAULT;
2513                                 relevance += computeRelevanceForCaseMatching(token, name);
2514                                 
2515                                 // accept result
2516                                 requestor.acceptVariableName(
2517                                         qualifiedPackageName,
2518                                         displayName,
2519                                         name,
2520                                         name,
2521                                         startPosition - offset,
2522                                         endPosition - offset,
2523                                         relevance);
2524                         }
2525         }
2526
2527         private void findVariableNames(char[] name, TypeReference type , char[][] excludeNames){
2528
2529                 if(type != null &&
2530                         type.binding != null &&
2531                         type.binding.problemId() == Binding.NoError){
2532                         TypeBinding tb = type.binding;
2533                         findVariableName(
2534                                 name,
2535                                 tb.leafComponentType().qualifiedPackageName(),
2536                                 tb.leafComponentType().qualifiedSourceName(),
2537                                 tb.leafComponentType().sourceName(),
2538                                 excludeNames,
2539                                 type.dimensions());
2540                 }/*     else {
2541                         char[][] typeName = type.getTypeName();
2542                         findVariableName(
2543                                 name,
2544                                 NoChar,
2545                                 CharOperation.concatWith(typeName, '.'),
2546                                 typeName[typeName.length - 1],
2547                                 excludeNames,
2548                                 type.dimensions());
2549                 }*/
2550         }
2551         
2552         public AssistParser getParser() {
2553
2554                 return parser;
2555         }
2556
2557         protected void reset() {
2558
2559                 super.reset();
2560                 this.knownPkgs = new HashtableOfObject(10);
2561                 this.knownTypes = new HashtableOfObject(10);
2562         }
2563
2564         private void setSourceRange(int start, int end) {
2565
2566                 this.startPosition = start;
2567                 this.endPosition = end + 1;
2568         }
2569         
2570         private char[] computeBaseNames(char firstName, char[][] excludeNames){
2571                 char[] name = new char[]{firstName};
2572                 
2573                 for(int i = 0 ; i < excludeNames.length ; i++){
2574                         if(CharOperation.equals(name, excludeNames[i], false)) {
2575                                 name[0]++;
2576                                 if(name[0] > 'z')
2577                                         name[0] = 'a';
2578                                 if(name[0] == firstName)
2579                                         return null;
2580                                 i = 0;
2581                         }       
2582                 }
2583                 
2584                 return name;
2585         }
2586         private void computeExpectedTypes(AstNode parent, Scope scope){
2587                 int expectedTypeCount = 0;
2588                 expectedTypes = new TypeBinding[1];
2589                 
2590                 if(parent instanceof AbstractVariableDeclaration) {
2591                         TypeBinding binding = ((AbstractVariableDeclaration)parent).type.binding;
2592                         if(binding != null) {
2593                                 expectedTypes[expectedTypeCount++] = binding;
2594                         }
2595                 } else if(parent instanceof Assignment) {
2596                         TypeBinding binding = ((Assignment)parent).lhsType;
2597                         if(binding != null) {
2598                                 expectedTypes[expectedTypeCount++] = binding;
2599                         }
2600                 } else if(parent instanceof ReturnStatement) {
2601                         MethodBinding methodBinding = ((AbstractMethodDeclaration) scope.methodScope().referenceContext).binding;
2602                         TypeBinding binding = methodBinding  == null ? null : methodBinding.returnType;
2603                         if(binding != null) {
2604                                 expectedTypes[expectedTypeCount++] = binding;
2605                         }
2606                 }
2607                 
2608                 System.arraycopy(expectedTypes, 0, expectedTypes = new TypeBinding[expectedTypeCount], 0, expectedTypeCount);
2609         }
2610         private char[][] computeNames(char[] sourceName, boolean forArray){
2611                 char[][] names = new char[5][];
2612                 int nameCount = 0;
2613                 boolean previousIsUpperCase = false;
2614                 for(int i = sourceName.length - 1 ; i >= 0 ; i--){
2615                         boolean isUpperCase = Character.isUpperCase(sourceName[i]);
2616                         if(isUpperCase && !previousIsUpperCase){
2617                                 char[] name = CharOperation.subarray(sourceName,i,sourceName.length);
2618                                 if(name.length > 1){
2619                                         if(nameCount == names.length) {
2620                                                 System.arraycopy(names, 0, names = new char[nameCount * 2][], 0, nameCount);
2621                                         }
2622                                         name[0] = Character.toLowerCase(name[0]);
2623                                         
2624                                         if(forArray) {
2625                                                 int length = name.length;
2626                                                 if (name[length-1] == 's'){
2627                                                         System.arraycopy(name, 0, name = new char[length + 2], 0, length);
2628                                                         name[length] = 'e';
2629                                                         name[length+1] = 's';
2630                                                 } else {
2631                                                         System.arraycopy(name, 0, name = new char[length + 1], 0, length);
2632                                                         name[length] = 's';
2633                                                 }
2634                                         }                                       
2635                                         names[nameCount++] = name;
2636                                 }
2637                         }
2638                         previousIsUpperCase = isUpperCase;
2639                 }
2640                 if(nameCount == 0){
2641                         char[] name = CharOperation.toLowerCase(sourceName);
2642                         if(forArray) {
2643                                 int length = name.length;
2644                                 if (name[length-1] == 's'){
2645                                         System.arraycopy(name, 0, name = new char[length + 2], 0, length);
2646                                         name[length] = 'e';
2647                                         name[length+1] = 's';
2648                                 } else {
2649                                         System.arraycopy(name, 0, name = new char[length + 1], 0, length);
2650                                         name[length] = 's';
2651                                 }
2652                         }                                       
2653                         names[nameCount++] = name;
2654                         
2655                 }
2656                 System.arraycopy(names, 0, names = new char[nameCount][], 0, nameCount);
2657                 return names;
2658         }
2659         
2660         private char[] computePrefix(SourceTypeBinding declarationType, SourceTypeBinding invocationType, boolean isStatic){
2661                 
2662                 StringBuffer completion = new StringBuffer(10);
2663
2664                 if (isStatic) {
2665                         completion.append(declarationType.sourceName());
2666                         
2667                 } else if (declarationType == invocationType) {
2668                         completion.append(THIS);
2669                         
2670                 } else {
2671                         
2672                         if (!declarationType.isNestedType()) {
2673                                 
2674                                 completion.append(declarationType.sourceName());
2675                                 completion.append('.');
2676                                 completion.append(THIS);
2677
2678                         } else if (!declarationType.isAnonymousType()) {
2679                                 
2680                                 completion.append(declarationType.sourceName());
2681                                 completion.append('.');
2682                                 completion.append(THIS);
2683                                 
2684                         }
2685                 }
2686                 
2687                 return completion.toString().toCharArray();
2688         }
2689         
2690         private boolean isEnclosed(ReferenceBinding possibleEnclosingType, ReferenceBinding type){
2691                 if(type.isNestedType()){
2692                         ReferenceBinding enclosing = type.enclosingType();
2693                         while(enclosing != null ){
2694                                 if(possibleEnclosingType == enclosing)
2695                                         return true;
2696                                 enclosing = enclosing.enclosingType();
2697                         }
2698                 }
2699                 return false;
2700         }
2701
2702 }