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
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.codeassist;
15 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
16 import net.sourceforge.phpdt.internal.compiler.*;
17 import net.sourceforge.phpdt.internal.compiler.env.*;
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.*;
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.*;
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).
42 public final class CompletionEngine
44 implements ISearchRequestor, TypeConstants , ITerminalSymbols , RelevanceConstants {
46 public static boolean DEBUG = false;
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;
53 boolean assistNodeIsClass;
54 boolean assistNodeIsException;
55 boolean assistNodeIsInterface;
57 CompletionParser parser;
58 ICompletionRequestor requestor;
59 ProblemReporter problemReporter;
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);
70 static final char[][] mainDeclarations =
72 "package".toCharArray(),
73 "import".toCharArray(),
74 "abstract".toCharArray(),
75 "final".toCharArray(),
76 "public".toCharArray(),
77 "class".toCharArray(),
78 "interface".toCharArray()};
80 static final char[][] modifiers = // may want field, method, type & member type modifiers
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()};
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$
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$
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){}
120 * The CompletionEngine is responsible for computing source completions.
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.
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.
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.
133 * @param settings java.util.Map
134 * set of options used to configure the code assist engine.
136 public CompletionEngine(
137 ISearchableNameEnvironment nameEnvironment,
138 ICompletionRequestor requestor,
142 this.requestor = requestor;
143 this.nameEnvironment = nameEnvironment;
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);
156 new CompletionParser(problemReporter, this.compilerOptions.assertMode);
157 this.lookupEnvironment =
158 new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
160 new Scanner(false, false, false, this.compilerOptions.assertMode);
164 * One result of the search consists of a new class.
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.
171 public void acceptClass(char[] packageName, char[] className, int modifiers) {
173 char[] fullyQualifiedName = CharOperation.concat(packageName, className, '.');
174 char[] completionName = fullyQualifiedName;
176 if (this.knownTypes.containsKey(completionName)) return;
178 this.knownTypes.put(completionName, this);
180 int relevance = R_DEFAULT;
181 if (resolvingImports) {
182 completionName = CharOperation.concat(completionName, SEMICOLON);
183 relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
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
191 completionName = className;
194 relevance += computeRelevanceForCaseMatching(token, className);
195 relevance += computeRelevanceForExpectingType(packageName, className);
196 relevance += computeRelevanceForClass();
197 relevance += computeRelevanceForException(className);
200 requestor.acceptClass(
205 startPosition - offset,
206 endPosition - offset,
211 * One result of the search consists of a new interface.
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.
218 public void acceptInterface(
220 char[] interfaceName,
223 char[] fullyQualifiedName = CharOperation.concat(packageName, interfaceName, '.');
224 char[] completionName = fullyQualifiedName;
226 if (this.knownTypes.containsKey(completionName)) return;
228 this.knownTypes.put(completionName, this);
230 int relevance = R_DEFAULT;
231 if (resolvingImports) {
232 completionName = CharOperation.concat(completionName, new char[] { ';' });
233 relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
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
241 completionName = interfaceName;
244 relevance += computeRelevanceForCaseMatching(token, interfaceName);
245 relevance += computeRelevanceForExpectingType(packageName, interfaceName);
246 relevance += computeRelevanceForInterface();
249 requestor.acceptInterface(
254 startPosition - offset,
255 endPosition - offset,
260 * One result of the search consists of a new package.
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.
266 public void acceptPackage(char[] packageName) {
268 if (this.knownPkgs.containsKey(packageName)) return;
270 this.knownPkgs.put(packageName, this);
272 int relevance = R_DEFAULT;
273 relevance += computeRelevanceForCaseMatching(token, packageName);
275 requestor.acceptPackage(
278 ? CharOperation.concat(packageName, new char[] { '.', '*', ';' })
280 startPosition - offset,
281 endPosition - offset,
286 * One result of the search consists of a new type.
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.
293 public void acceptType(char[] packageName, char[] typeName) {
295 char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.');
296 char[] completionName = fullyQualifiedName;
298 if (this.knownTypes.containsKey(completionName)) return;
300 this.knownTypes.put(completionName, this);
302 int relevance = R_DEFAULT;
303 if (resolvingImports) {
304 completionName = CharOperation.concat(completionName, new char[] { ';' });
305 relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
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
313 completionName = typeName;
316 relevance += computeRelevanceForCaseMatching(token, typeName);
317 relevance += computeRelevanceForExpectingType(packageName, typeName);
320 requestor.acceptType(
324 startPosition - offset,
325 endPosition - offset,
329 private void complete(AstNode astNode, Binding qualifiedBinding, Scope scope) {
331 setSourceRange(astNode.sourceStart, astNode.sourceEnd);
333 if(parser.assistNodeParent != null) {
334 computeExpectedTypes(parser.assistNodeParent, scope);
337 // defaults... some nodes will change these
338 if (astNode instanceof CompletionOnFieldType) {
340 CompletionOnFieldType field = (CompletionOnFieldType) astNode;
341 CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type;
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);
347 if(!field.isLocalVariable && field.modifiers == CompilerModifiers.AccDefault) {
348 findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
351 if(astNode instanceof CompletionOnMethodReturnType) {
353 CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode;
354 SingleTypeReference type = (CompletionOnSingleTypeReference) method.returnType;
356 setSourceRange(type.sourceStart, type.sourceEnd);
357 findTypesAndPackages(token, scope);
359 if(method.modifiers == CompilerModifiers.AccDefault) {
360 findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
364 if (astNode instanceof CompletionOnSingleNameReference) {
366 token = ((CompletionOnSingleNameReference) astNode).token;
367 findVariablesAndMethods(
370 (CompletionOnSingleNameReference) astNode,
372 // can be the start of a qualified type name
373 findTypesAndPackages(token, scope);
377 if (astNode instanceof CompletionOnSingleTypeReference) {
379 token = ((CompletionOnSingleTypeReference) astNode).token;
381 assistNodeIsClass = astNode instanceof CompletionOnClassReference;
382 assistNodeIsException = astNode instanceof CompletionOnExceptionReference;
383 assistNodeIsInterface = astNode instanceof CompletionOnInterfaceReference;
385 // can be the start of a qualified type name
386 if (qualifiedBinding == null) {
387 findTypesAndPackages(token, scope);
391 (ReferenceBinding) qualifiedBinding,
393 scope.enclosingSourceType());
397 if (astNode instanceof CompletionOnQualifiedNameReference) {
399 insideQualifiedReference = true;
400 CompletionOnQualifiedNameReference ref =
401 (CompletionOnQualifiedNameReference) astNode;
402 token = ref.completionIdentifier;
403 long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
405 if (qualifiedBinding instanceof VariableBinding) {
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);
415 if (qualifiedBinding instanceof ReferenceBinding) {
417 ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
418 setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
420 findMemberTypes(token, receiverType, scope, scope.enclosingSourceType());
422 findClassField(token, (TypeBinding) qualifiedBinding, scope);
450 if (qualifiedBinding instanceof PackageBinding) {
452 setSourceRange(astNode.sourceStart, (int) completionPosition);
453 // replace to the end of the completion identifier
454 findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
461 if (astNode instanceof CompletionOnQualifiedTypeReference) {
463 insideQualifiedReference = true;
465 assistNodeIsClass = astNode instanceof CompletionOnQualifiedClassReference;
466 assistNodeIsException = astNode instanceof CompletionOnQualifiedExceptionReference;
467 assistNodeIsInterface = astNode instanceof CompletionOnQualifiedInterfaceReference;
469 CompletionOnQualifiedTypeReference ref =
470 (CompletionOnQualifiedTypeReference) astNode;
471 token = ref.completionIdentifier;
472 long completionPosition = ref.sourcePositions[ref.tokens.length];
474 // get the source positions of the completion identifier
475 if (qualifiedBinding instanceof ReferenceBinding) {
477 setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
480 (ReferenceBinding) qualifiedBinding,
482 scope.enclosingSourceType());
486 if (qualifiedBinding instanceof PackageBinding) {
488 setSourceRange(astNode.sourceStart, (int) completionPosition);
489 // replace to the end of the completion identifier
490 findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
496 if (astNode instanceof CompletionOnMemberAccess) {
498 CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode;
499 long completionPosition = access.nameSourcePosition;
500 setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
502 token = access.token;
504 findFieldsAndMethods(
506 (TypeBinding) qualifiedBinding,
514 if (astNode instanceof CompletionOnMessageSend) {
516 CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
517 TypeBinding[] argTypes =
518 computeTypes(messageSend.arguments, (BlockScope) scope);
519 token = messageSend.selector;
520 if (qualifiedBinding == null) {
522 findImplicitMessageSends(token, argTypes, scope, messageSend, scope);
528 (ReferenceBinding) qualifiedBinding,
541 if (astNode instanceof CompletionOnExplicitConstructorCall) {
543 CompletionOnExplicitConstructorCall constructorCall =
544 (CompletionOnExplicitConstructorCall) astNode;
545 TypeBinding[] argTypes =
546 computeTypes(constructorCall.arguments, (BlockScope) scope);
548 (ReferenceBinding) qualifiedBinding,
556 if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
558 CompletionOnQualifiedAllocationExpression allocExpression =
559 (CompletionOnQualifiedAllocationExpression) astNode;
560 TypeBinding[] argTypes =
561 computeTypes(allocExpression.arguments, (BlockScope) scope);
563 ReferenceBinding ref = (ReferenceBinding) qualifiedBinding;
565 if(!ref.isAbstract()) {
584 if (astNode instanceof CompletionOnClassLiteralAccess) {
585 CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode;
586 setSourceRange(access.classStart, access.sourceEnd);
588 token = access.completionIdentifier;
590 findClassField(token, (TypeBinding) qualifiedBinding, scope);
592 if(astNode instanceof CompletionOnMethodName) {
593 CompletionOnMethodName method = (CompletionOnMethodName) astNode;
595 setSourceRange(method.sourceStart, method.selectorEnd);
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;
603 token = method.selector;
605 findVariableNames(token, method.returnType, excludeNames);
607 if (astNode instanceof CompletionOnFieldName) {
608 CompletionOnFieldName field = (CompletionOnFieldName) astNode;
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;
616 token = field.realName;
618 findVariableNames(field.realName, field.type, excludeNames);
620 if (astNode instanceof CompletionOnLocalName ||
621 astNode instanceof CompletionOnArgumentName){
622 LocalDeclaration variable = (LocalDeclaration) astNode;
624 LocalVariableBinding[] locals = ((BlockScope)scope).locals;
625 char[][] excludeNames = new char[locals.length][];
627 for(int i = 0 ; i < locals.length ; i++){
628 if(locals[i] != null) {
629 excludeNames[localCount++] = locals[i].name;
632 System.arraycopy(excludeNames, 0, excludeNames = new char[localCount][], 0, localCount);
634 if(variable instanceof CompletionOnLocalName){
635 token = ((CompletionOnLocalName) variable).realName;
637 token = ((CompletionOnArgumentName) variable).realName;
639 findVariableNames(token, variable.type, excludeNames);
656 // public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
657 // TypeConverter converter = new TypeConverter();
659 // IType topLevelType = type;
660 // while(topLevelType.getDeclaringType() != null) {
661 // topLevelType = topLevelType.getDeclaringType();
664 // CompilationResult compilationResult = new CompilationResult((topLevelType.getElementName() + ".java").toCharArray(), 1, 1, this.compilerOptions.maxProblemsPerUnit); //$NON-NLS-1$
666 // CompilationUnitDeclaration compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, 0);
669 // TypeDeclaration typeDeclaration = converter.buildTypeDeclaration(type, compilationUnit, compilationResult, problemReporter);
671 // if(typeDeclaration != null) {
672 // // build AST from snippet
673 // Initializer fakeInitializer = parseSnippeInitializer(snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
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;
683 // System.out.println("SNIPPET COMPLETION AST :"); //$NON-NLS-1$
684 // System.out.println(compilationUnit.toString());
687 // if (compilationUnit.types != null) {
689 // lookupEnvironment.buildTypeBindings(compilationUnit);
691 // if ((unitScope = compilationUnit.scope) != null) {
692 // lookupEnvironment.completeTypeBindings(compilationUnit, true);
693 // compilationUnit.scope.faultInTypes();
694 // compilationUnit.resolve();
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);
705 // } catch(JavaModelException e) {
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$
714 // prefix.append("static "); //$NON-NLS-1$
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(';');
726 // char[] fakeSource = CharOperation.concat(prefix.toString().toCharArray(), snippet, "}}".toCharArray());//$NON-NLS-1$
727 // offset = prefix.length();
729 // String encoding = JavaCore.getOption(JavaCore.CORE_ENCODING);
730 // BasicCompilationUnit fakeUnit = new BasicCompilationUnit(
733 // "FakeType.java", //$NON-NLS-1$
736 // actualCompletionPosition = prefix.length() + position - 1;
738 // CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
739 // CompilationUnitDeclaration fakeAST = parser.dietParse(fakeUnit, fakeResult, actualCompletionPosition);
741 // parseMethod(fakeAST, actualCompletionPosition);
743 // return (Initializer)fakeAST.types[0].fields[0];
747 * Ask the engine to compute a completion at the specified position
748 * of the given compilation unit.
751 * completion results are answered through a requestor.
753 * @param sourceUnit net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit
754 * the source of the current compilation unit.
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.
760 public void complete(ICompilationUnit sourceUnit, int completionPosition, int offset) {
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());
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);
777 // boolean completionNodeFound = false;
778 if (parsedUnit != null) {
780 System.out.println("COMPLETION - Diet AST :"); //$NON-NLS-1$
781 System.out.println(parsedUnit.toString());
784 // scan the package & import statements first
785 if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
786 findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
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);
801 if (parsedUnit.types != null) {
803 lookupEnvironment.buildTypeBindings(parsedUnit);
805 if ((unitScope = parsedUnit.scope) != null) {
806 source = sourceUnit.getContents();
807 lookupEnvironment.completeTypeBindings(parsedUnit, true);
808 parsedUnit.scope.faultInTypes();
809 parseMethod(parsedUnit, actualCompletionPosition);
811 System.out.println("COMPLETION - AST :"); //$NON-NLS-1$
812 System.out.println(parsedUnit.toString());
814 parsedUnit.resolve();
816 } catch (CompletionNodeFound e) {
817 // completionNodeFound = true;
818 if (e.astNode != null) {
820 System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
821 System.out.println(e.astNode.toString());
823 // if null then we found a problem in the completion node
824 complete(e.astNode, e.qualifiedBinding, e.scope);
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);
838 // currently have no way to know if extends/implements are possible keywords
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
850 private TypeBinding[] computeTypes(Expression[] arguments, BlockScope scope) {
852 if (arguments == null)
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);
862 private void findAnonymousType(
863 ReferenceBinding currentType,
864 TypeBinding[] argTypes,
866 InvocationSite invocationSite) {
868 if (currentType.isInterface()) {
869 char[] completion = TypeConstants.NoChar;
870 // nothing to insert - do not want to replace the existing selector & arguments
872 || source.length <= endPosition
873 || source[endPosition] != ')')
874 completion = new char[] { ')' };
876 requestor.acceptAnonymousType(
877 currentType.qualifiedPackageName(),
878 currentType.qualifiedSourceName(),
879 TypeConstants.NoCharChar,
880 TypeConstants.NoCharChar,
881 TypeConstants.NoCharChar,
883 IConstants.AccPublic,
884 endPosition - offset,
885 endPosition - offset,
897 private void findClassField(char[] token, TypeBinding receiverType, Scope scope) {
902 if (token.length <= classField.length
903 && CharOperation.prefixEquals(token, classField, false /* ignore case */
905 int relevance = R_DEFAULT;
906 relevance += computeRelevanceForCaseMatching(token, classField);
907 relevance += computeRelevanceForExpectingType(scope.getJavaLangClass());
909 requestor.acceptField(
916 CompilerModifiers.AccStatic | CompilerModifiers.AccPublic,
917 startPosition - offset,
918 endPosition - offset,
923 private void findConstructors(
924 ReferenceBinding currentType,
925 TypeBinding[] argTypes,
927 InvocationSite invocationSite,
928 boolean forAnonymousType) {
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()) {
938 if (constructor.isSynthetic()) continue next;
940 if (options.checkVisibility
941 && !constructor.canBeSeenBy(invocationSite, scope)) continue next;
943 TypeBinding[] parameters = constructor.parameters;
944 int paramLength = parameters.length;
945 if (minArgLength > paramLength)
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]))
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();
959 char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames);
961 char[] completion = TypeConstants.NoChar;
962 // nothing to insert - do not want to replace the existing selector & arguments
964 || source.length <= endPosition
965 || source[endPosition] != ')')
966 completion = new char[] { ')' };
968 if(forAnonymousType){
969 requestor.acceptAnonymousType(
970 currentType.qualifiedPackageName(),
971 currentType.qualifiedSourceName(),
972 parameterPackageNames,
976 constructor.modifiers,
977 endPosition - offset,
978 endPosition - offset,
981 requestor.acceptMethod(
982 currentType.qualifiedPackageName(),
983 currentType.qualifiedSourceName(),
984 currentType.sourceName(),
985 parameterPackageNames,
988 TypeConstants.NoChar,
989 TypeConstants.NoChar,
991 constructor.modifiers,
992 endPosition - offset,
993 endPosition - offset,
1001 // Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
1002 private void findFields(
1004 FieldBinding[] fields,
1006 ObjectVector fieldsFound,
1007 ObjectVector localsFound,
1008 boolean onlyStaticFields,
1009 ReferenceBinding receiverType,
1010 InvocationSite invocationSite,
1011 Scope invocationScope,
1012 boolean implicitCall) {
1014 // Inherited fields which are hidden by subclasses are filtered out
1015 // No visibility checks can be performed without the scope & invocationSite
1017 int fieldLength = fieldName.length;
1018 next : for (int f = fields.length; --f >= 0;) {
1019 FieldBinding field = fields[f];
1021 if (field.isSynthetic()) continue next;
1023 if (onlyStaticFields && !field.isStatic()) continue next;
1025 if (fieldLength > field.name.length) continue next;
1027 if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */)) continue next;
1029 if (options.checkVisibility
1030 && !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
1032 boolean prefixRequired = false;
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)
1040 if (CharOperation.equals(field.name, otherField.name, true)) {
1041 if (field.declaringClass.isSuperclassOf(otherField.declaringClass))
1043 if (otherField.declaringClass.isInterface())
1044 if (field.declaringClass.implementsInterface(otherField.declaringClass, true))
1046 if (field.declaringClass.isInterface())
1047 if (otherField.declaringClass.implementsInterface(field.declaringClass, true))
1049 prefixRequired = true;
1053 for (int l = localsFound.size; --l >= 0;) {
1054 LocalVariableBinding local = (LocalVariableBinding) localsFound.elementAt(l);
1056 if (CharOperation.equals(field.name, local.name, true)) {
1057 SourceTypeBinding declarationType = scope.enclosingSourceType();
1058 if (declarationType.isAnonymousType() && declarationType != invocationScope.enclosingSourceType()) {
1061 prefixRequired = true;
1066 fieldsFound.add(new Object[]{field, receiverType});
1068 char[] completion = field.name;
1070 if(prefixRequired || options.forceImplicitQualification){
1071 char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), field.isStatic());
1072 completion = CharOperation.concat(prefix,completion,'.');
1075 int relevance = R_DEFAULT;
1076 relevance += computeRelevanceForCaseMatching(fieldName, field.name);
1077 relevance += computeRelevanceForExpectingType(field.type);
1081 field.declaringClass.qualifiedPackageName(),
1082 field.declaringClass.qualifiedSourceName(),
1084 field.type.qualifiedPackageName(),
1085 field.type.qualifiedSourceName(),
1087 // may include some qualification to resolve ambiguities
1088 field.modifiers, startPosition - offset, endPosition - offset,
1093 private void findFields(
1095 ReferenceBinding receiverType,
1097 ObjectVector fieldsFound,
1098 ObjectVector localsFound,
1099 boolean onlyStaticFields,
1100 InvocationSite invocationSite,
1101 Scope invocationScope,
1102 boolean implicitCall) {
1104 if (fieldName == null)
1107 ReferenceBinding currentType = receiverType;
1108 ReferenceBinding[][] interfacesToVisit = null;
1109 int lastPosition = -1;
1112 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1113 if (itsInterfaces != NoSuperInterfaces) {
1115 if (interfacesToVisit == null)
1116 interfacesToVisit = new ReferenceBinding[5][];
1118 if (++lastPosition == interfacesToVisit.length)
1122 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1125 interfacesToVisit[lastPosition] = itsInterfaces;
1128 FieldBinding[] fields = currentType.availableFields();
1129 if(fields != null) {
1142 currentType = currentType.superclass();
1143 } while (currentType != null);
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++) {
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;
1155 FieldBinding[] fields = anInterface.availableFields();
1156 if(fields != null) {
1170 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
1171 if (itsInterfaces != NoSuperInterfaces) {
1172 if (++lastPosition == interfacesToVisit.length)
1176 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1179 interfacesToVisit[lastPosition] = itsInterfaces;
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;
1194 private void findFieldsAndMethods(
1196 TypeBinding receiverType,
1198 InvocationSite invocationSite,
1199 Scope invocationScope,
1200 boolean implicitCall) {
1205 if (receiverType.isBaseType())
1206 return; // nothing else is possible with base types
1208 if (receiverType.isArrayType()) {
1209 if (token.length <= lengthField.length
1210 && CharOperation.prefixEquals(token, lengthField, false /* ignore case */
1213 int relevance = R_DEFAULT;
1214 relevance += computeRelevanceForCaseMatching(token,lengthField);
1215 relevance += computeRelevanceForExpectingType(BaseTypes.IntBinding);
1217 requestor.acceptField(
1224 CompilerModifiers.AccPublic,
1225 startPosition - offset,
1226 endPosition - offset,
1229 receiverType = scope.getJavaLangObject();
1234 (ReferenceBinding) receiverType,
1246 (ReferenceBinding) receiverType,
1257 private void findImports(CompletionOnImportReference importReference) {
1258 char[][] tokens = importReference.tokens;
1260 char[] importName = CharOperation.concatWith(tokens, '.');
1262 if (importName.length == 0)
1265 char[] lastToken = tokens[tokens.length - 1];
1266 if(lastToken != null && lastToken.length == 0)
1267 importName = CharOperation.concat(importName, new char[]{'.'});
1269 resolvingImports = true;
1271 importReference.sourceStart,
1272 importReference.declarationSourceEnd);
1275 // want to replace the existing .*;
1276 nameEnvironment.findPackages(importName, this);
1277 nameEnvironment.findTypes(importName, this);
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) {
1284 int length = keyword.length;
1286 for (int i = 0; i < choices.length; i++)
1287 if (length <= choices[i].length
1288 && CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */
1290 int relevance = R_DEFAULT;
1291 relevance += computeRelevanceForCaseMatching(keyword, choices[i]);
1293 requestor.acceptKeyword(choices[i], startPosition - offset, endPosition - offset,relevance);
1297 // Helper method for findMemberTypes(char[], ReferenceBinding, Scope)
1298 private void findMemberTypes(
1300 ReferenceBinding[] memberTypes,
1301 ObjectVector typesFound,
1302 ReferenceBinding receiverType,
1303 SourceTypeBinding invocationType) {
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)
1315 if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false
1320 if (options.checkVisibility
1321 && !memberType.canBeSeenBy(receiverType, invocationType))
1324 for (int i = typesFound.size; --i >= 0;) {
1325 ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i);
1327 if (memberType == otherType)
1330 if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)) {
1332 if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType()))
1335 if (otherType.enclosingType().isInterface())
1336 if (memberType.enclosingType()
1337 .implementsInterface(otherType.enclosingType(), true))
1340 if (memberType.enclosingType().isInterface())
1341 if (otherType.enclosingType()
1342 .implementsInterface(memberType.enclosingType(), true))
1347 typesFound.add(memberType);
1349 int relevance = R_DEFAULT;
1350 relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName);
1351 relevance += computeRelevanceForExpectingType(memberType);
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,
1365 relevance += computeRelevanceForInterface();
1366 requestor.acceptInterface(
1367 memberType.qualifiedPackageName(),
1368 memberType.qualifiedSourceName(),
1369 memberType.sourceName(),
1370 memberType.modifiers,
1371 startPosition - offset,
1372 endPosition - offset,
1378 private void findMemberTypes(
1380 ReferenceBinding receiverType,
1382 SourceTypeBinding typeInvocation) {
1384 ReferenceBinding currentType = receiverType;
1385 if (typeName == null)
1388 if (currentType.superInterfaces() == null)
1389 return; // we're trying to find a supertype
1391 ObjectVector typesFound = new ObjectVector();
1392 if (insideQualifiedReference
1393 || typeName.length == 0) { // do not search up the hierarchy
1397 currentType.memberTypes(),
1404 ReferenceBinding[][] interfacesToVisit = null;
1405 int lastPosition = -1;
1409 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1410 if (itsInterfaces != NoSuperInterfaces) {
1412 if (interfacesToVisit == null)
1413 interfacesToVisit = new ReferenceBinding[5][];
1415 if (++lastPosition == interfacesToVisit.length)
1419 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1422 interfacesToVisit[lastPosition] = itsInterfaces;
1427 currentType.memberTypes(),
1431 currentType = currentType.superclass();
1433 } while (currentType != null);
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++) {
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;
1447 anInterface.memberTypes(),
1452 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
1453 if (itsInterfaces != NoSuperInterfaces) {
1455 if (++lastPosition == interfacesToVisit.length)
1459 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1462 interfacesToVisit[lastPosition] = itsInterfaces;
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;
1477 private void findIntefacesMethods(
1479 TypeBinding[] argTypes,
1480 ReferenceBinding receiverType,
1481 ReferenceBinding[] itsInterfaces,
1483 ObjectVector methodsFound,
1484 boolean onlyStaticMethods,
1486 boolean isCompletingDeclaration,
1487 InvocationSite invocationSite,
1488 Scope invocationScope,
1489 boolean implicitCall) {
1491 if (selector == null)
1494 if (itsInterfaces != NoSuperInterfaces) {
1495 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
1496 int lastPosition = 0;
1497 interfacesToVisit[lastPosition] = itsInterfaces;
1499 for (int i = 0; i <= lastPosition; i++) {
1500 ReferenceBinding[] interfaces = interfacesToVisit[i];
1502 for (int j = 0, length = interfaces.length; j < length; j++) {
1503 ReferenceBinding currentType = interfaces[j];
1505 if ((currentType.tagBits & TagBits.InterfaceVisited) == 0) {
1506 // if interface as not already been visited
1507 currentType.tagBits |= TagBits.InterfaceVisited;
1509 MethodBinding[] methods = currentType.availableMethods();
1510 if(methods != null) {
1511 if(isCompletingDeclaration){
1513 findLocalMethodDeclarations(
1539 itsInterfaces = currentType.superInterfaces();
1540 if (itsInterfaces != NoSuperInterfaces) {
1542 if (++lastPosition == interfacesToVisit.length)
1546 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
1549 interfacesToVisit[lastPosition] = itsInterfaces;
1555 // bit reinitialization
1556 for (int i = 0; i <= lastPosition; i++) {
1557 ReferenceBinding[] interfaces = interfacesToVisit[i];
1559 for (int j = 0, length = interfaces.length; j < length; j++){
1560 interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
1566 private void findImplicitMessageSends(
1568 TypeBinding[] argTypes,
1570 InvocationSite invocationSite,
1571 Scope invocationScope) {
1576 boolean staticsOnly = false;
1577 // need to know if we're in a static context (or inside a constructor)
1578 ObjectVector methodsFound = new ObjectVector();
1580 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1582 switch (scope.kind) {
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;
1590 case Scope.CLASS_SCOPE :
1591 ClassScope classScope = (ClassScope) scope;
1592 SourceTypeBinding enclosingType = classScope.referenceContext.binding;
1605 staticsOnly |= enclosingType.isStatic();
1608 case Scope.COMPILATION_UNIT_SCOPE :
1611 scope = scope.parent;
1615 // Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean)
1616 private void findLocalMethods(
1618 TypeBinding[] argTypes,
1619 MethodBinding[] methods,
1621 ObjectVector methodsFound,
1622 boolean onlyStaticMethods,
1624 ReferenceBinding receiverType,
1625 InvocationSite invocationSite,
1626 Scope invocationScope,
1627 boolean implicitCall) {
1629 // Inherited methods which are hidden by subclasses are filtered out
1630 // No visibility checks can be performed without the scope & invocationSite
1632 int methodLength = methodName.length;
1633 int minArgLength = argTypes == null ? 0 : argTypes.length;
1635 next : for (int f = methods.length; --f >= 0;) {
1636 MethodBinding method = methods[f];
1638 if (method.isSynthetic()) continue next;
1640 if (method.isDefaultAbstract()) continue next;
1642 if (method.isConstructor()) continue next;
1644 // if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
1645 if (onlyStaticMethods && !method.isStatic()) continue next;
1647 if (options.checkVisibility
1648 && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
1651 if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
1657 if (methodLength > method.selector.length)
1660 if (!CharOperation.prefixEquals(methodName, method.selector, false
1665 if (minArgLength > method.parameters.length)
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])) {
1676 boolean prefixRequired = false;
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)
1685 if (CharOperation.equals(method.selector, otherMethod.selector, true)
1686 && method.areParametersEqual(otherMethod)) {
1688 if (method.declaringClass.isSuperclassOf(otherMethod.declaringClass))
1691 if (otherMethod.declaringClass.isInterface())
1694 .implementsInterface(otherMethod.declaringClass, true))
1697 if (method.declaringClass.isInterface())
1700 .implementsInterface(method.declaringClass,true))
1702 prefixRequired = true;
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][];
1711 for (int i = 0; i < length; i++) {
1712 TypeBinding type = method.parameters[i];
1713 parameterPackageNames[i] = type.qualifiedPackageName();
1714 parameterTypeNames[i] = type.qualifiedSourceName();
1716 char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
1718 char[] completion = TypeConstants.NoChar;
1720 int previousStartPosition = startPosition;
1722 // nothing to insert - do not want to replace the existing selector & arguments
1725 && source.length > endPosition
1726 && source[endPosition] == '(')
1727 completion = method.selector;
1729 completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
1731 if(prefixRequired && (source != null)) {
1732 completion = CharOperation.subarray(source, startPosition, endPosition);
1734 startPosition = endPosition;
1738 if(prefixRequired || options.forceImplicitQualification){
1739 char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), method.isStatic());
1740 completion = CharOperation.concat(prefix,completion,'.');
1743 int relevance = R_DEFAULT;
1744 relevance += computeRelevanceForCaseMatching(methodName, method.selector);
1745 relevance += computeRelevanceForExpectingType(method.returnType);
1747 requestor.acceptMethod(
1748 method.declaringClass.qualifiedPackageName(),
1749 method.declaringClass.qualifiedSourceName(),
1751 parameterPackageNames,
1754 method.returnType.qualifiedPackageName(),
1755 method.returnType.qualifiedSourceName(),
1758 startPosition - offset,
1759 endPosition - offset,
1761 startPosition = previousStartPosition;
1765 private int computeRelevanceForCaseMatching(char[] token, char[] proposalName){
1766 if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) {
1772 private int computeRelevanceForClass(){
1773 if(assistNodeIsClass) {
1778 private int computeRelevanceForInterface(){
1779 if(assistNodeIsInterface) {
1784 private int computeRelevanceForException(char[] proposalName){
1786 if(assistNodeIsException &&
1787 (CharOperation.match(EXCEPTION_PATTERN, proposalName, false) ||
1788 CharOperation.match(ERROR_PATTERN, proposalName, false))) {
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;
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;
1815 // Helper method for findMethods(char[], MethodBinding[], Scope, ObjectVector, boolean, boolean, boolean, TypeBinding)
1816 private void findLocalMethodDeclarations(
1818 MethodBinding[] methods,
1820 ObjectVector methodsFound,
1821 // boolean noVoidReturnType, how do you know?
1822 boolean onlyStaticMethods,
1824 ReferenceBinding receiverType) {
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;) {
1831 MethodBinding method = methods[f];
1832 if (method.isSynthetic()) continue next;
1834 if (method.isDefaultAbstract()) continue next;
1836 if (method.isConstructor()) continue next;
1838 if (method.isFinal()) continue next;
1840 // if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
1841 if (onlyStaticMethods && !method.isStatic()) continue next;
1843 if (options.checkVisibility
1844 && !method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next;
1847 if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
1853 if (methodLength > method.selector.length)
1856 if (!CharOperation.prefixEquals(methodName, method.selector, false
1862 for (int i = methodsFound.size; --i >= 0;) {
1863 MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i);
1864 if (method == otherMethod)
1867 if (CharOperation.equals(method.selector, otherMethod.selector, true)
1868 && method.areParametersEqual(otherMethod)) {
1873 methodsFound.add(method);
1875 int length = method.parameters.length;
1876 char[][] parameterPackageNames = new char[length][];
1877 char[][] parameterTypeNames = new char[length][];
1879 for (int i = 0; i < length; i++) {
1880 TypeBinding type = method.parameters[i];
1881 parameterPackageNames[i] = type.qualifiedPackageName();
1882 parameterTypeNames[i] = type.qualifiedSourceName();
1885 char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
1887 StringBuffer completion = new StringBuffer(10);
1888 // flush uninteresting modifiers
1889 int insertedModifiers = method.modifiers & ~(CompilerModifiers.AccNative | CompilerModifiers.AccAbstract);
1892 if(insertedModifiers != CompilerModifiers.AccDefault){
1893 completion.append(AstNode.modifiersString(insertedModifiers));
1895 char[] returnPackageName = method.returnType.qualifiedPackageName();
1896 char[] returnTypeName = method.returnType.qualifiedSourceName();
1897 if(mustQualifyType(returnPackageName, returnTypeName)) {
1898 completion.append(CharOperation.concat(returnPackageName, returnTypeName,'.'));
1900 completion.append(method.returnType.sourceName());
1902 completion.append(' ');
1903 completion.append(method.selector);
1904 completion.append('(');
1906 for(int i = 0; i < length ; i++){
1907 if(mustQualifyType(parameterPackageNames[i], parameterTypeNames[i])){
1908 completion.append(CharOperation.concat(parameterPackageNames[i], parameterTypeNames[i], '.'));
1910 completion.append(parameterTypeNames[i]);
1912 completion.append(' ');
1913 if(parameterNames != null){
1914 completion.append(parameterNames[i]);
1916 completion.append('%');
1918 if(i != (length - 1))
1919 completion.append(',');
1921 completion.append(')');
1923 ReferenceBinding[] exceptions = method.thrownExceptions;
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];
1932 char[] exceptionPackageName = exception.qualifiedPackageName();
1933 char[] exceptionTypeName = exception.qualifiedSourceName();
1936 completion.append(',');
1937 completion.append(' ');
1940 if(mustQualifyType(exceptionPackageName, exceptionTypeName)){
1941 completion.append(CharOperation.concat(exceptionPackageName, exceptionTypeName, '.'));
1943 completion.append(exception.sourceName());
1949 int relevance = R_DEFAULT;
1950 relevance += computeRelevanceForCaseMatching(methodName, method.selector);
1952 requestor.acceptMethodDeclaration(
1953 method.declaringClass.qualifiedPackageName(),
1954 method.declaringClass.qualifiedSourceName(),
1956 parameterPackageNames,
1959 method.returnType.qualifiedPackageName(),
1960 method.returnType.qualifiedSourceName(),
1961 completion.toString().toCharArray(),
1963 startPosition - offset,
1964 endPosition - offset,
1968 private void findMethods(
1970 TypeBinding[] argTypes,
1971 ReferenceBinding receiverType,
1973 ObjectVector methodsFound,
1974 boolean onlyStaticMethods,
1976 boolean isCompletingDeclaration,
1977 InvocationSite invocationSite,
1978 Scope invocationScope,
1979 boolean implicitCall) {
1980 if (selector == null)
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]);
1994 ReferenceBinding currentType = receiverType;
1995 if (receiverType.isInterface()) {
1996 if(isCompletingDeclaration) {
1997 findIntefacesMethods(
2001 currentType.superInterfaces(),
2006 isCompletingDeclaration,
2011 findIntefacesMethods(
2015 new ReferenceBinding[]{currentType},
2020 isCompletingDeclaration,
2026 currentType = scope.getJavaLangObject();
2028 if(isCompletingDeclaration){
2029 findIntefacesMethods(
2033 currentType.superInterfaces(),
2038 isCompletingDeclaration,
2043 currentType = receiverType.superclass();
2046 boolean hasPotentialDefaultAbstractMethods = true;
2047 while (currentType != null) {
2049 MethodBinding[] methods = currentType.availableMethods();
2050 if(methods != null) {
2051 if(isCompletingDeclaration){
2052 findLocalMethodDeclarations(
2076 if(hasPotentialDefaultAbstractMethods && currentType.isAbstract()){
2077 findIntefacesMethods(
2081 currentType.superInterfaces(),
2086 isCompletingDeclaration,
2091 hasPotentialDefaultAbstractMethods = false;
2093 currentType = currentType.superclass();
2096 private char[][] findMethodParameterNames(MethodBinding method, char[][] parameterTypeNames){
2097 ReferenceBinding bindingType = method.declaringClass;
2099 char[][] parameterNames = null;
2101 int length = parameterTypeNames.length;
2104 return TypeConstants.NoCharChar;
2106 // look into the corresponding unit if it is available
2107 if (bindingType instanceof SourceTypeBinding){
2108 SourceTypeBinding sourceType = (SourceTypeBinding) bindingType;
2110 if (sourceType.scope != null){
2111 TypeDeclaration parsedType;
2113 if ((parsedType = sourceType.scope.referenceContext) != null){
2114 AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method);
2116 if (methodDecl != null){
2117 Argument[] arguments = methodDecl.arguments;
2118 parameterNames = new char[length][];
2120 for(int i = 0 ; i < length ; i++){
2121 parameterNames[i] = arguments[i].name;
2127 // look into the model
2128 if(parameterNames == null){
2129 NameEnvironmentAnswer answer = nameEnvironment.findType(bindingType.compoundName);
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();
2140 if(argTypeNames != null &&
2141 CharOperation.equals(method.selector,sourceMethod.getSelector()) &&
2142 CharOperation.equals(argTypeNames,parameterTypeNames)){
2143 parameterNames = sourceMethod.getArgumentNames();
2150 return parameterNames;
2153 private void findNestedTypes(
2155 SourceTypeBinding currentType,
2157 if (typeName == null)
2160 int typeLength = typeName.length;
2162 while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found
2164 switch (scope.kind) {
2166 case Scope.METHOD_SCOPE :
2167 case Scope.BLOCK_SCOPE :
2168 BlockScope blockScope = (BlockScope) scope;
2170 next : for (int i = 0, length = blockScope.scopeIndex; i < length; i++) {
2172 if (blockScope.subscopes[i] instanceof ClassScope) {
2173 SourceTypeBinding localType =
2174 ((ClassScope) blockScope.subscopes[i]).referenceContext.binding;
2176 if (!localType.isAnonymousType()) {
2177 if (typeLength > localType.sourceName.length)
2179 if (!CharOperation.prefixEquals(typeName, localType.sourceName, false
2184 int relevance = R_DEFAULT;
2185 relevance += computeRelevanceForCaseMatching(typeName, localType.sourceName);
2186 relevance += computeRelevanceForExpectingType(localType);
2187 relevance += computeRelevanceForClass();
2189 requestor.acceptClass(
2190 localType.qualifiedPackageName(),
2191 localType.sourceName,
2192 localType.sourceName,
2193 localType.modifiers,
2194 startPosition - offset,
2195 endPosition - offset,
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
2208 case Scope.COMPILATION_UNIT_SCOPE :
2211 scope = scope.parent;
2215 private void findPackages(CompletionOnPackageReference packageStatement) {
2217 token = CharOperation.concatWith(packageStatement.tokens, '.');
2218 if (token.length == 0)
2221 setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
2222 nameEnvironment.findPackages(CharOperation.toLowerCase(token), this);
2225 private void findTypesAndPackages(char[] token, Scope scope) {
2230 if (scope.enclosingSourceType() != null)
2231 findNestedTypes(token, scope.enclosingSourceType(), scope);
2233 if (unitScope != null) {
2234 int typeLength = token.length;
2235 SourceTypeBinding[] types = unitScope.topLevelTypes;
2237 for (int i = 0, length = types.length; i < length; i++) {
2238 SourceTypeBinding sourceType = types[i];
2240 if (typeLength > sourceType.sourceName.length) continue;
2242 if (!CharOperation.prefixEquals(token, sourceType.sourceName, false)) continue;
2244 int relevance = R_DEFAULT;
2245 relevance += computeRelevanceForCaseMatching(token, sourceType.sourceName);
2246 relevance += computeRelevanceForExpectingType(sourceType);
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,
2259 relevance += computeRelevanceForInterface();
2260 requestor.acceptInterface(
2261 sourceType.qualifiedPackageName(),
2262 sourceType.sourceName(),
2263 sourceType.sourceName(),
2264 sourceType.modifiers,
2265 startPosition - offset,
2266 endPosition - offset,
2272 if (token.length == 0)
2275 findKeywords(token, baseTypes, scope);
2276 nameEnvironment.findTypes(token, this);
2277 nameEnvironment.findPackages(token, this);
2280 private void findTypesAndSubpackages(
2282 PackageBinding packageBinding) {
2284 char[] qualifiedName =
2285 CharOperation.concatWith(packageBinding.compoundName, token, '.');
2287 if (token == null || token.length == 0) {
2288 int length = qualifiedName.length;
2292 qualifiedName = new char[length + 1],
2295 qualifiedName[length] = '.';
2297 nameEnvironment.findTypes(qualifiedName, this);
2298 nameEnvironment.findPackages(qualifiedName, this);
2301 private void findVariablesAndMethods(
2304 InvocationSite invocationSite,
2305 Scope invocationScope) {
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
2313 boolean staticsOnly = false;
2314 // need to know if we're in a static context (or inside a constructor)
2315 int tokenLength = token.length;
2317 ObjectVector localsFound = new ObjectVector();
2318 ObjectVector fieldsFound = new ObjectVector();
2319 ObjectVector methodsFound = new ObjectVector();
2321 Scope currentScope = scope;
2323 done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
2325 switch (currentScope.kind) {
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;
2332 case Scope.BLOCK_SCOPE :
2333 BlockScope blockScope = (BlockScope) currentScope;
2335 next : for (int i = 0, length = blockScope.locals.length; i < length; i++) {
2336 LocalVariableBinding local = blockScope.locals[i];
2341 if (tokenLength > local.name.length)
2344 if (!CharOperation.prefixEquals(token, local.name, false /* ignore case */
2348 if (local.isSecret())
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))
2357 localsFound.add(local);
2359 int relevance = R_DEFAULT;
2360 relevance += computeRelevanceForCaseMatching(token, local.name);
2361 relevance += computeRelevanceForExpectingType(local.type);
2363 requestor.acceptLocalVariable(
2367 : local.type.qualifiedPackageName(),
2369 ? local.declaration.type.toString().toCharArray()
2370 : local.type.qualifiedSourceName(),
2372 startPosition - offset,
2373 endPosition - offset,
2378 case Scope.COMPILATION_UNIT_SCOPE :
2381 currentScope = currentScope.parent;
2384 currentScope = scope;
2386 done2 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
2388 switch (currentScope.kind) {
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);
2421 staticsOnly |= enclosingType.isStatic();
2425 case Scope.COMPILATION_UNIT_SCOPE :
2428 currentScope = currentScope.parent;
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)
2439 // compute variable name for base type
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)
2453 // name = computeBaseNames(sourceName[0], excludeNames);
2457 int relevance = R_DEFAULT;
2458 relevance += computeRelevanceForCaseMatching(token, name);
2461 requestor.acceptVariableName(
2462 qualifiedPackageName,
2463 qualifiedSourceName,
2466 startPosition - offset,
2467 endPosition - offset,
2471 } catch(InvalidInputException e){
2474 // compute variable name for non base type
2475 char[][] names = computeNames(sourceName, 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] = ']';
2486 displayName = qualifiedSourceName;
2488 next : for(int i = 0 ; i < names.length ; i++){
2491 if (!CharOperation.prefixEquals(token, name, false))
2494 // completion must be an identifier (not a keyword, ...).
2496 nameScanner.setSource(name);
2497 if(nameScanner.getNextToken() != TokenNameIdentifier)
2499 } catch(InvalidInputException e){
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());
2512 int relevance = R_DEFAULT;
2513 relevance += computeRelevanceForCaseMatching(token, name);
2516 requestor.acceptVariableName(
2517 qualifiedPackageName,
2521 startPosition - offset,
2522 endPosition - offset,
2527 private void findVariableNames(char[] name, TypeReference type , char[][] excludeNames){
2530 type.binding != null &&
2531 type.binding.problemId() == Binding.NoError){
2532 TypeBinding tb = type.binding;
2535 tb.leafComponentType().qualifiedPackageName(),
2536 tb.leafComponentType().qualifiedSourceName(),
2537 tb.leafComponentType().sourceName(),
2541 char[][] typeName = type.getTypeName();
2545 CharOperation.concatWith(typeName, '.'),
2546 typeName[typeName.length - 1],
2552 public AssistParser getParser() {
2557 protected void reset() {
2560 this.knownPkgs = new HashtableOfObject(10);
2561 this.knownTypes = new HashtableOfObject(10);
2564 private void setSourceRange(int start, int end) {
2566 this.startPosition = start;
2567 this.endPosition = end + 1;
2570 private char[] computeBaseNames(char firstName, char[][] excludeNames){
2571 char[] name = new char[]{firstName};
2573 for(int i = 0 ; i < excludeNames.length ; i++){
2574 if(CharOperation.equals(name, excludeNames[i], false)) {
2578 if(name[0] == firstName)
2586 private void computeExpectedTypes(AstNode parent, Scope scope){
2587 int expectedTypeCount = 0;
2588 expectedTypes = new TypeBinding[1];
2590 if(parent instanceof AbstractVariableDeclaration) {
2591 TypeBinding binding = ((AbstractVariableDeclaration)parent).type.binding;
2592 if(binding != null) {
2593 expectedTypes[expectedTypeCount++] = binding;
2595 } else if(parent instanceof Assignment) {
2596 TypeBinding binding = ((Assignment)parent).lhsType;
2597 if(binding != null) {
2598 expectedTypes[expectedTypeCount++] = binding;
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;
2608 System.arraycopy(expectedTypes, 0, expectedTypes = new TypeBinding[expectedTypeCount], 0, expectedTypeCount);
2610 private char[][] computeNames(char[] sourceName, boolean forArray){
2611 char[][] names = new char[5][];
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);
2622 name[0] = Character.toLowerCase(name[0]);
2625 int length = name.length;
2626 if (name[length-1] == 's'){
2627 System.arraycopy(name, 0, name = new char[length + 2], 0, length);
2629 name[length+1] = 's';
2631 System.arraycopy(name, 0, name = new char[length + 1], 0, length);
2635 names[nameCount++] = name;
2638 previousIsUpperCase = isUpperCase;
2641 char[] name = CharOperation.toLowerCase(sourceName);
2643 int length = name.length;
2644 if (name[length-1] == 's'){
2645 System.arraycopy(name, 0, name = new char[length + 2], 0, length);
2647 name[length+1] = 's';
2649 System.arraycopy(name, 0, name = new char[length + 1], 0, length);
2653 names[nameCount++] = name;
2656 System.arraycopy(names, 0, names = new char[nameCount][], 0, nameCount);
2660 private char[] computePrefix(SourceTypeBinding declarationType, SourceTypeBinding invocationType, boolean isStatic){
2662 StringBuffer completion = new StringBuffer(10);
2665 completion.append(declarationType.sourceName());
2667 } else if (declarationType == invocationType) {
2668 completion.append(THIS);
2672 if (!declarationType.isNestedType()) {
2674 completion.append(declarationType.sourceName());
2675 completion.append('.');
2676 completion.append(THIS);
2678 } else if (!declarationType.isAnonymousType()) {
2680 completion.append(declarationType.sourceName());
2681 completion.append('.');
2682 completion.append(THIS);
2687 return completion.toString().toCharArray();
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)
2696 enclosing = enclosing.enclosingType();