package org.eclipse.jdt.internal.codeassist;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
import java.util.*;

import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.env.*;

import org.eclipse.jdt.internal.codeassist.impl.*;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompletionRequestor;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.codeassist.complete.*;

import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.parser.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.*;
import org.eclipse.jdt.internal.core.BasicCompilationUnit;
import org.eclipse.jdt.internal.core.TypeConverter;
import org.eclipse.jdt.internal.compiler.impl.*;

/**
 * This class is the entry point for source completions.
 * It contains two public APIs used to call CodeAssist on a given source with
 * a given environment, assisting position and storage (and possibly options).
 */
public final class CompletionEngine
	extends Engine
	implements ISearchRequestor, TypeConstants , ITerminalSymbols , RelevanceConstants {
	
	public static boolean DEBUG = false;

	private final static char[] ERROR_PATTERN = "*error*".toCharArray();  //$NON-NLS-1$
	private final static char[] EXCEPTION_PATTERN = "*exception*".toCharArray();  //$NON-NLS-1$
	private final static char[] SEMICOLON = new char[] { ';' };
	TypeBinding[] expectedTypes;
	
	boolean assistNodeIsClass;
	boolean assistNodeIsException;
	boolean assistNodeIsInterface;
	
	AssistOptions options;
	CompletionParser parser;
	ICompletionRequestor requestor;
	ProblemReporter problemReporter;
	char[] source;
	char[] token;
	boolean resolvingImports = false;
	boolean insideQualifiedReference = false;
	int startPosition, actualCompletionPosition, endPosition, offset;
	HashtableOfObject knownPkgs = new HashtableOfObject(10);
	HashtableOfObject knownTypes = new HashtableOfObject(10);
	Scanner nameScanner;

	/*
		static final char[][] mainDeclarations =
			new char[][] {
				"package".toCharArray(),
				"import".toCharArray(),
				"abstract".toCharArray(),
				"final".toCharArray(),
				"public".toCharArray(),
				"class".toCharArray(),
				"interface".toCharArray()};
	
		static final char[][] modifiers = // may want field, method, type & member type modifiers
			new char[][] {
				"abstract".toCharArray(),
				"final".toCharArray(),
				"native".toCharArray(),
				"public".toCharArray(),
				"protected".toCharArray(),
				"private".toCharArray(),
				"static".toCharArray(),
				"strictfp".toCharArray(),
				"synchronized".toCharArray(),
				"transient".toCharArray(),
				"volatile".toCharArray()};
	*/
	static final char[][] baseTypes = new char[][] { 
		"boolean".toCharArray(), //$NON-NLS-1$
		"byte".toCharArray(), //$NON-NLS-1$
		"char".toCharArray(), //$NON-NLS-1$
		"double".toCharArray(), //$NON-NLS-1$
		"float".toCharArray(), //$NON-NLS-1$
		"int".toCharArray(), //$NON-NLS-1$
		"long".toCharArray(), //$NON-NLS-1$
		"short".toCharArray(), //$NON-NLS-1$
		"void".toCharArray(), //$NON-NLS-1$
	};
		
	static final char[] classField = "class".toCharArray();  //$NON-NLS-1$
	static final char[] lengthField = "length".toCharArray();  //$NON-NLS-1$
	static final char[] THIS = "this".toCharArray();  //$NON-NLS-1$
	static final char[] THROWS = "throws".toCharArray();  //$NON-NLS-1$
	
	static InvocationSite FakeInvocationSite = new InvocationSite(){
		public boolean isSuperAccess(){ return false; }
		public boolean isTypeAccess(){ return false; }
		public void setActualReceiverType(ReferenceBinding receiverType) {}
		public void setDepth(int depth){}
		public void setFieldIndex(int depth){}
	};

	/**
	 * The CompletionEngine is responsible for computing source completions.
	 *
	 * It requires a searchable name environment, which supports some
	 * specific search APIs, and a requestor to feed back the results to a UI.
	 *
	 *  @param nameEnvironment org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment
	 *      used to resolve type/package references and search for types/packages
	 *      based on partial names.
	 *
	 *  @param requestor org.eclipse.jdt.internal.codeassist.ICompletionRequestor
	 *      since the engine might produce answers of various forms, the engine 
	 *      is associated with a requestor able to accept all possible completions.
	 *
	 *  @param settings java.util.Map
	 *		set of options used to configure the code assist engine.
	 */
	public CompletionEngine(
		ISearchableNameEnvironment nameEnvironment,
		ICompletionRequestor requestor,
		Map settings) {

		this.requestor = requestor;
		this.nameEnvironment = nameEnvironment;

		options = new AssistOptions(settings);
		CompilerOptions compilerOptions = new CompilerOptions(settings);

		problemReporter = new ProblemReporter(
				DefaultErrorHandlingPolicies.proceedWithAllProblems(),
				compilerOptions,
				new DefaultProblemFactory(Locale.getDefault()) {
					public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
						if (problem.isError() && (problem.getID() & IProblem.Syntax) != 0) {
							CompletionEngine.this.requestor.acceptError(problem);
						}
					}
				});
		this.parser =
			new CompletionParser(problemReporter, compilerOptions.assertMode);
		this.lookupEnvironment =
			new LookupEnvironment(this, compilerOptions, problemReporter, nameEnvironment);
		this.nameScanner =
			new Scanner(false, false, false, compilerOptions.assertMode);
	}

	/**
	 * One result of the search consists of a new class.
	 *
	 * NOTE - All package and type names are presented in their readable form:
	 *    Package names are in the form "a.b.c".
	 *    Nested type names are in the qualified form "A.M".
	 *    The default package is represented by an empty array.
	 */
	public void acceptClass(char[] packageName, char[] className, int modifiers) {

		char[] fullyQualifiedName = CharOperation.concat(packageName, className, '.');
		char[] completionName = fullyQualifiedName;
		
		if (this.knownTypes.containsKey(completionName)) return;

		this.knownTypes.put(completionName, this);
		
		int relevance = R_DEFAULT;
		if (resolvingImports) {
			completionName = CharOperation.concat(completionName, SEMICOLON);
			relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
		} else {
			if (!insideQualifiedReference) {
				if (mustQualifyType(packageName, className)) {
					if (packageName == null || packageName.length == 0)
						if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
							return; // ignore types from the default package from outside it
				} else {
					completionName = className;
				}
			}
			relevance += computeRelevanceForCaseMatching(token, className);
			relevance += computeRelevanceForExpectingType(packageName, className);
			relevance += computeRelevanceForClass();
			relevance += computeRelevanceForException(className);
		}

		requestor.acceptClass(
			packageName,
			className,
			completionName,
			modifiers,
			startPosition - offset,
			endPosition - offset,
			relevance);
	}
	
	/**
	 * One result of the search consists of a new interface.
	 *
	 * NOTE - All package and type names are presented in their readable form:
	 *    Package names are in the form "a.b.c".
	 *    Nested type names are in the qualified form "A.I".
	 *    The default package is represented by an empty array.
	 */
	public void acceptInterface(
		char[] packageName,
		char[] interfaceName,
		int modifiers) {

		char[] fullyQualifiedName = CharOperation.concat(packageName, interfaceName, '.');
		char[] completionName = fullyQualifiedName;

		if (this.knownTypes.containsKey(completionName)) return;

		this.knownTypes.put(completionName, this);

		int relevance = R_DEFAULT;
		if (resolvingImports) {
			completionName = CharOperation.concat(completionName, new char[] { ';' });
			relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
		} else {
			if (!insideQualifiedReference) {
				if (mustQualifyType(packageName, interfaceName)) {
					if (packageName == null || packageName.length == 0)
						if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
							return; // ignore types from the default package from outside it
				} else {
					completionName = interfaceName;
				}
			}
			relevance += computeRelevanceForCaseMatching(token, interfaceName);
			relevance += computeRelevanceForExpectingType(packageName, interfaceName);
			relevance += computeRelevanceForInterface();
		}
		
		requestor.acceptInterface(
			packageName,
			interfaceName,
			completionName,
			modifiers,
			startPosition - offset,
			endPosition - offset,
			relevance);
	}

	/**
	 * One result of the search consists of a new package.
	 *
	 * NOTE - All package names are presented in their readable form:
	 *    Package names are in the form "a.b.c".
	 *    The default package is represented by an empty array.
	 */
	public void acceptPackage(char[] packageName) {

		if (this.knownPkgs.containsKey(packageName)) return;

		this.knownPkgs.put(packageName, this);
		
		int relevance = R_DEFAULT;
		relevance += computeRelevanceForCaseMatching(token, packageName);

		requestor.acceptPackage(
			packageName,
			resolvingImports
				? CharOperation.concat(packageName, new char[] { '.', '*', ';' })
				: packageName,
			startPosition - offset,
			endPosition - offset,
			relevance);
	}

	/**
	 * One result of the search consists of a new type.
	 *
	 * NOTE - All package and type names are presented in their readable form:
	 *    Package names are in the form "a.b.c".
	 *    Nested type names are in the qualified form "A.M".
	 *    The default package is represented by an empty array.
	 */
	public void acceptType(char[] packageName, char[] typeName) {

		char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.');
		char[] completionName = fullyQualifiedName;
		
		if (this.knownTypes.containsKey(completionName)) return;

		this.knownTypes.put(completionName, this);

		int relevance = R_DEFAULT;
		if (resolvingImports) {
			completionName = CharOperation.concat(completionName, new char[] { ';' });
			relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
		} else {
			if (!insideQualifiedReference) {
				if (mustQualifyType(packageName, typeName)) {
					if (packageName == null || packageName.length == 0)
						if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
							return; // ignore types from the default package from outside it
				} else {
					completionName = typeName;
				}
			}
			relevance += computeRelevanceForCaseMatching(token, typeName);
			relevance += computeRelevanceForExpectingType(packageName, typeName);
		}
		
		requestor.acceptType(
			packageName,
			typeName,
			completionName,
			startPosition - offset,
			endPosition - offset,
			relevance);
	}

	private void complete(AstNode astNode, Binding qualifiedBinding, Scope scope) {

		setSourceRange(astNode.sourceStart, astNode.sourceEnd);
		
		if(parser.assistNodeParent != null) {
			computeExpectedTypes(parser.assistNodeParent, scope);
		}

		// defaults... some nodes will change these
		if (astNode instanceof CompletionOnFieldType) {

			CompletionOnFieldType field = (CompletionOnFieldType) astNode;
			CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type;
			token = type.token;
			setSourceRange(type.sourceStart, type.sourceEnd);
			//		findKeywords(token, modifiers, scope); // could be the start of a field, method or member type
			findTypesAndPackages(token, scope);
			
			if(!field.isLocalVariable && field.modifiers == CompilerModifiers.AccDefault) {
				findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
			}
		} else {
			if(astNode instanceof CompletionOnMethodReturnType) {
				
				CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode;
				SingleTypeReference type = (CompletionOnSingleTypeReference) method.returnType;
				token = type.token;
				setSourceRange(type.sourceStart, type.sourceEnd);
				findTypesAndPackages(token, scope);
				
				if(method.modifiers == CompilerModifiers.AccDefault) {
					findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
				}
			} else {
				
				if (astNode instanceof CompletionOnSingleNameReference) {
	
					token = ((CompletionOnSingleNameReference) astNode).token;
					findVariablesAndMethods(
						token,
						scope,
						(CompletionOnSingleNameReference) astNode,
						scope);
					// can be the start of a qualified type name
					findTypesAndPackages(token, scope);
	
				} else {
	
					if (astNode instanceof CompletionOnSingleTypeReference) {
	
						token = ((CompletionOnSingleTypeReference) astNode).token;
						
						assistNodeIsClass = astNode instanceof CompletionOnClassReference;
						assistNodeIsException = astNode instanceof CompletionOnExceptionReference;
						assistNodeIsInterface = astNode instanceof CompletionOnInterfaceReference;
	
						// can be the start of a qualified type name
						if (qualifiedBinding == null) {
							findTypesAndPackages(token, scope);
							} else {
								findMemberTypes(
								token,
								(ReferenceBinding) qualifiedBinding,
								scope,
								scope.enclosingSourceType());
						}
					} else {
						
						if (astNode instanceof CompletionOnQualifiedNameReference) {
	
							insideQualifiedReference = true;
							CompletionOnQualifiedNameReference ref =
								(CompletionOnQualifiedNameReference) astNode;
							token = ref.completionIdentifier;
							long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
	
							if (qualifiedBinding instanceof VariableBinding) {
	
								setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
								TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type;
								if (receiverType != null) {
									findFieldsAndMethods(token, receiverType, scope, ref, scope,false);
								}
	
							} else {
	
								if (qualifiedBinding instanceof ReferenceBinding) {
	
									ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
									setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
	
									findMemberTypes(token, receiverType, scope, scope.enclosingSourceType());
	
									findClassField(token, (TypeBinding) qualifiedBinding, scope);
	
									findFields(
										token,
										receiverType,
										scope,
										new ObjectVector(),
										new ObjectVector(),
										true,
										ref,
										scope,
										false);
	
									findMethods(
										token,
										null,
										receiverType,
										scope,
										new ObjectVector(),
										true,
										false,
										false,
										ref,
										scope,
										false);
	
								} else {
	
									if (qualifiedBinding instanceof PackageBinding) {
	
										setSourceRange(astNode.sourceStart, (int) completionPosition);
										// replace to the end of the completion identifier
										findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
									}
								}
							}
	
						} else {
	
								if (astNode instanceof CompletionOnQualifiedTypeReference) {
	
								insideQualifiedReference = true;
								
								assistNodeIsClass = astNode instanceof CompletionOnQualifiedClassReference;
								assistNodeIsException = astNode instanceof CompletionOnQualifiedExceptionReference;
								assistNodeIsInterface = astNode instanceof CompletionOnQualifiedInterfaceReference;
								
								CompletionOnQualifiedTypeReference ref =
									(CompletionOnQualifiedTypeReference) astNode;
								token = ref.completionIdentifier;
								long completionPosition = ref.sourcePositions[ref.tokens.length];
	
								// get the source positions of the completion identifier
								if (qualifiedBinding instanceof ReferenceBinding) {
	
									setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
									findMemberTypes(
										token,
										(ReferenceBinding) qualifiedBinding,
										scope,
										scope.enclosingSourceType());
	
								} else {
	
									if (qualifiedBinding instanceof PackageBinding) {
	
										setSourceRange(astNode.sourceStart, (int) completionPosition);
										// replace to the end of the completion identifier
										findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
									}
								}
	
							} else {
	
								if (astNode instanceof CompletionOnMemberAccess) {
	
									CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode;
									long completionPosition = access.nameSourcePosition;
									setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
					
									token = access.token;
	
									findFieldsAndMethods(
										token,
										(TypeBinding) qualifiedBinding,
										scope,
										access,
										scope,
										false);
	
								} else {
	
									if (astNode instanceof CompletionOnMessageSend) {
	
										CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
										TypeBinding[] argTypes =
											computeTypes(messageSend.arguments, (BlockScope) scope);
										token = messageSend.selector;
										if (qualifiedBinding == null) {
											
											findImplicitMessageSends(token, argTypes, scope, messageSend, scope);
										} else {
	
											findMethods(
												token,
												argTypes,
												(ReferenceBinding) qualifiedBinding,
												scope,
												new ObjectVector(),
												false,
												true,
												false,
												messageSend,
												scope,
												false);
										}
	
									} else {
	
										if (astNode instanceof CompletionOnExplicitConstructorCall) {
	
											CompletionOnExplicitConstructorCall constructorCall =
												(CompletionOnExplicitConstructorCall) astNode;
											TypeBinding[] argTypes =
												computeTypes(constructorCall.arguments, (BlockScope) scope);
											findConstructors(
												(ReferenceBinding) qualifiedBinding,
												argTypes,
												scope,
												constructorCall,
												false);
	
										} else {
	
											if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
	
												CompletionOnQualifiedAllocationExpression allocExpression =
													(CompletionOnQualifiedAllocationExpression) astNode;
												TypeBinding[] argTypes =
													computeTypes(allocExpression.arguments, (BlockScope) scope);
												
												ReferenceBinding ref = (ReferenceBinding) qualifiedBinding;
												if(ref.isClass()) {
													if(!ref.isAbstract()) {
														findConstructors(
															ref,
															argTypes,
															scope,
															allocExpression,
															false);
													}
												}
												if(!ref.isFinal()){
													findAnonymousType(
														ref,
														argTypes,
														scope,
														allocExpression);
												}
	
											} else {
	
												if (astNode instanceof CompletionOnClassLiteralAccess) {
													CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode;
													setSourceRange(access.classStart, access.sourceEnd);
									
													token = access.completionIdentifier;
									
													findClassField(token, (TypeBinding) qualifiedBinding, scope);
												} else {
													if(astNode instanceof CompletionOnMethodName) {
														CompletionOnMethodName method = (CompletionOnMethodName) astNode;
															
														setSourceRange(method.sourceStart, method.selectorEnd);
															
														FieldBinding[] fields = scope.enclosingSourceType().fields();
														char[][] excludeNames = new char[fields.length][];
														for(int i = 0 ; i < fields.length ; i++){
															excludeNames[i] = fields[i].name;
														}
														
														token = method.selector;
														
														findVariableNames(token, method.returnType, excludeNames);
													} else {
														if (astNode instanceof CompletionOnFieldName) {
															CompletionOnFieldName field = (CompletionOnFieldName) astNode;
															
															FieldBinding[] fields = scope.enclosingSourceType().fields();
															char[][] excludeNames = new char[fields.length][];
															for(int i = 0 ; i < fields.length ; i++){
																excludeNames[i] = fields[i].name;
															}
															
															token = field.realName;
															
															findVariableNames(field.realName, field.type, excludeNames);
														} else {
															if (astNode instanceof CompletionOnLocalName ||
																astNode instanceof CompletionOnArgumentName){
																LocalDeclaration variable = (LocalDeclaration) astNode;
																
																LocalVariableBinding[] locals = ((BlockScope)scope).locals;
																char[][] excludeNames = new char[locals.length][];
																int localCount = 0;
																for(int i = 0 ; i < locals.length ; i++){
																	if(locals[i] != null) {
																		excludeNames[localCount++] = locals[i].name;
																	}
																}
																System.arraycopy(excludeNames, 0, excludeNames = new char[localCount][], 0, localCount);
																
																if(variable instanceof CompletionOnLocalName){
																	token = ((CompletionOnLocalName) variable).realName;
																} else {
																	token = ((CompletionOnArgumentName) variable).realName;
																}
																findVariableNames(token, variable.type, excludeNames);
															}
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	
	public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){	
		TypeConverter converter = new TypeConverter();
		
		IType topLevelType = type;
		while(topLevelType.getDeclaringType() != null) {
			topLevelType = topLevelType.getDeclaringType();
		}
		
		CompilationResult compilationResult = new CompilationResult((topLevelType.getElementName() + ".java").toCharArray(), 1, 1); //$NON-NLS-1$
	
		CompilationUnitDeclaration compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, 0);
	
		try {
			TypeDeclaration typeDeclaration = converter.buildTypeDeclaration(type, compilationUnit, compilationResult, problemReporter);
		
			if(typeDeclaration != null) {	
				// build AST from snippet
				Initializer fakeInitializer = parseSnippeInitializer(snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
				
				// merge AST
				FieldDeclaration[] oldFields = typeDeclaration.fields;
				FieldDeclaration[] newFields = new FieldDeclaration[oldFields.length + 1];
				System.arraycopy(oldFields, 0, newFields, 0, oldFields.length);
				newFields[oldFields.length] = fakeInitializer;
				typeDeclaration.fields = newFields;
		
				if(DEBUG) {
					System.out.println("SNIPPET COMPLETION AST :"); //$NON-NLS-1$
					System.out.println(compilationUnit.toString());
				}
				
				if (compilationUnit.types != null) {
					try {
						lookupEnvironment.buildTypeBindings(compilationUnit);
				
						if ((unitScope = compilationUnit.scope) != null) {
							lookupEnvironment.completeTypeBindings(compilationUnit, true);
							compilationUnit.scope.faultInTypes();
							compilationUnit.resolve();
						}
					} catch (CompletionNodeFound e) {
						//					completionNodeFound = true;
						if (e.astNode != null) {
							// if null then we found a problem in the completion node
							complete(e.astNode, e.qualifiedBinding, e.scope);
						}
					}
				}
			}
		} catch(JavaModelException e) {
			// Do nothing
		}
	}
	
	private Initializer parseSnippeInitializer(char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
		StringBuffer prefix = new StringBuffer();
		prefix.append("public class FakeType {\n "); //$NON-NLS-1$
		if(isStatic) {
			prefix.append("static "); //$NON-NLS-1$
		}
		prefix.append("{\n"); //$NON-NLS-1$
		for (int i = 0; i < localVariableTypeNames.length; i++) {
			prefix.append(AstNode.modifiersString(localVariableModifiers[i]));
			prefix.append(' ');
			prefix.append(localVariableTypeNames[i]);
			prefix.append(' ');
			prefix.append(localVariableNames[i]);
			prefix.append(';');
		}
		
		char[] fakeSource = CharOperation.concat(prefix.toString().toCharArray(), snippet, "}}".toCharArray());//$NON-NLS-1$ 
		offset = prefix.length();
		
		String encoding = (String) JavaCore.getOptions().get(CompilerOptions.OPTION_Encoding);
		if ("".equals(encoding)) encoding = null; //$NON-NLS-1$
		BasicCompilationUnit fakeUnit = new BasicCompilationUnit(
			fakeSource, 
			null,
			"FakeType.java", //$NON-NLS-1$
			encoding); 
			
		actualCompletionPosition = prefix.length() + position - 1;
			
		CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1);
		CompilationUnitDeclaration fakeAST = parser.dietParse(fakeUnit, fakeResult, actualCompletionPosition);
		
		parseMethod(fakeAST, actualCompletionPosition);
		
		return (Initializer)fakeAST.types[0].fields[0];
	}

	/**
	 * Ask the engine to compute a completion at the specified position
	 * of the given compilation unit.
	 *
	 *  @return void
	 *      completion results are answered through a requestor.
	 *
	 *  @param sourceUnit org.eclipse.jdt.internal.compiler.env.ICompilationUnit
	 *      the source of the current compilation unit.
	 *
	 *  @param completionPosition int
	 *      a position in the source where the completion is taking place. 
	 *      This position is relative to the source provided.
	 */
	public void complete(ICompilationUnit sourceUnit, int completionPosition, int offset) {

		if(DEBUG) {
			System.out.print("COMPLETION IN "); //$NON-NLS-1$
			System.out.print(sourceUnit.getFileName());
			System.out.print(" AT POSITION "); //$NON-NLS-1$
			System.out.println(completionPosition);
			System.out.println("COMPLETION - Source :"); //$NON-NLS-1$
			System.out.println(sourceUnit.getContents());
		}
		try {
			actualCompletionPosition = completionPosition - 1;
			this.offset = offset;
			// for now until we can change the UI.
			CompilationResult result = new CompilationResult(sourceUnit, 1, 1);
			CompilationUnitDeclaration parsedUnit = parser.dietParse(sourceUnit, result, actualCompletionPosition);

			//		boolean completionNodeFound = false;
			if (parsedUnit != null) {
				if(DEBUG) {
					System.out.println("COMPLETION - Diet AST :"); //$NON-NLS-1$
					System.out.println(parsedUnit.toString());
				}

				// scan the package & import statements first
				if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
					findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
					return;
				}

				ImportReference[] imports = parsedUnit.imports;
				if (imports != null) {
					for (int i = 0, length = imports.length; i < length; i++) {
						ImportReference importReference = imports[i];
						if (importReference instanceof CompletionOnImportReference) {
							findImports((CompletionOnImportReference) importReference);
							return;
						}
					}
				}

				if (parsedUnit.types != null) {
					try {
						lookupEnvironment.buildTypeBindings(parsedUnit);

						if ((unitScope = parsedUnit.scope) != null) {
							source = sourceUnit.getContents();
							lookupEnvironment.completeTypeBindings(parsedUnit, true);
							parsedUnit.scope.faultInTypes();
							parseMethod(parsedUnit, actualCompletionPosition);
							if(DEBUG) {
								System.out.println("COMPLETION - AST :"); //$NON-NLS-1$
								System.out.println(parsedUnit.toString());
							}
							parsedUnit.resolve();
						}
					} catch (CompletionNodeFound e) {
						//					completionNodeFound = true;
						if (e.astNode != null) {
							if(DEBUG) {
								System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
								System.out.println(e.astNode.toString());
							}
							// if null then we found a problem in the completion node
							complete(e.astNode, e.qualifiedBinding, e.scope);
						}
					}
				}
			}

			/* Ignore package, import, class & interface keywords for now...
					if (!completionNodeFound) {
						if (parsedUnit == null || parsedUnit.types == null) {
							// this is not good enough... can still be trying to define a second type
							CompletionScanner scanner = (CompletionScanner) parser.scanner;
							setSourceRange(scanner.completedIdentifierStart, scanner.completedIdentifierEnd);
							findKeywords(scanner.completionIdentifier, mainDeclarations, null);
						}
						// currently have no way to know if extends/implements are possible keywords
					}
			*/
		} catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
		} catch (InvalidCursorLocation e) { // may eventually report a usefull error
		} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
		} catch (CompletionNodeFound e){ // internal failure - bugs 5618
		} finally {
			reset();
		}
	}

	private TypeBinding[] computeTypes(Expression[] arguments, BlockScope scope) {

		if (arguments == null)
			return null;

		int argsLength = arguments.length;
		TypeBinding[] argTypes = new TypeBinding[argsLength];
		for (int a = argsLength; --a >= 0;)
			argTypes[a] = arguments[a].resolveType(scope);
		return argTypes;
	}
	
	private void findAnonymousType(
		ReferenceBinding currentType,
		TypeBinding[] argTypes,
		Scope scope,
		InvocationSite invocationSite) {

		if (currentType.isInterface()) {
			char[] completion = TypeConstants.NoChar;
			// nothing to insert - do not want to replace the existing selector & arguments
			if (source == null
				|| source.length <= endPosition
				|| source[endPosition] != ')')
				completion = new char[] { ')' };
			
			requestor.acceptAnonymousType(
				currentType.qualifiedPackageName(),
				currentType.qualifiedSourceName(),
				TypeConstants.NoCharChar,
				TypeConstants.NoCharChar,
				TypeConstants.NoCharChar,
				completion,
				IConstants.AccPublic,
				endPosition - offset,
				endPosition - offset,
				R_DEFAULT);
		} else {
			findConstructors(
				currentType,
				argTypes,
				scope,
				invocationSite,
				true);
		}
	}

	private void findClassField(char[] token, TypeBinding receiverType, Scope scope) {

		if (token == null)
			return;

		if (token.length <= classField.length
			&& CharOperation.prefixEquals(token, classField, false /* ignore case */
		)) {
			int relevance = R_DEFAULT;
			relevance += computeRelevanceForCaseMatching(token, classField);
			relevance += computeRelevanceForExpectingType(scope.getJavaLangClass());
				
			requestor.acceptField(
				NoChar,
				NoChar,
				classField,
				NoChar,
				NoChar,
				classField,
				CompilerModifiers.AccStatic | CompilerModifiers.AccPublic,
				startPosition - offset,
				endPosition - offset,
				relevance);
		}
	}

	private void findConstructors(
		ReferenceBinding currentType,
		TypeBinding[] argTypes,
		Scope scope,
		InvocationSite invocationSite,
		boolean forAnonymousType) {

		// No visibility checks can be performed without the scope & invocationSite
		MethodBinding[] methods = currentType.availableMethods();
		if(methods != null) {
			int minArgLength = argTypes == null ? 0 : argTypes.length;
			next : for (int f = methods.length; --f >= 0;) {
				MethodBinding constructor = methods[f];
				if (constructor.isConstructor()) {
					
					if (constructor.isSynthetic()) continue next;
						
					if (options.checkVisibility
						&& !constructor.canBeSeenBy(invocationSite, scope)) continue next;
	
					TypeBinding[] parameters = constructor.parameters;
					int paramLength = parameters.length;
					if (minArgLength > paramLength)
						continue next;
					for (int a = minArgLength; --a >= 0;)
						if (argTypes[a] != null) // can be null if it could not be resolved properly
							if (!scope.areTypesCompatible(argTypes[a], constructor.parameters[a]))
								continue next;
	
					char[][] parameterPackageNames = new char[paramLength][];
					char[][] parameterTypeNames = new char[paramLength][];
					for (int i = 0; i < paramLength; i++) {
						TypeBinding type = parameters[i];
						parameterPackageNames[i] = type.qualifiedPackageName();
						parameterTypeNames[i] = type.qualifiedSourceName();
					}
					char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames);
					
					char[] completion = TypeConstants.NoChar;
					// nothing to insert - do not want to replace the existing selector & arguments
					if (source == null
						|| source.length <= endPosition
						|| source[endPosition] != ')')
						completion = new char[] { ')' };
					
					if(forAnonymousType){
						requestor.acceptAnonymousType(
							currentType.qualifiedPackageName(),
							currentType.qualifiedSourceName(),
							parameterPackageNames,
							parameterTypeNames,
							parameterNames,
							completion,
							constructor.modifiers,
							endPosition - offset,
							endPosition - offset,
							R_DEFAULT);
					} else {
						requestor.acceptMethod(
							currentType.qualifiedPackageName(),
							currentType.qualifiedSourceName(),
							currentType.sourceName(),
							parameterPackageNames,
							parameterTypeNames,
							parameterNames,
							TypeConstants.NoChar,
							TypeConstants.NoChar,
							completion,
							constructor.modifiers,
							endPosition - offset,
							endPosition - offset,
							R_DEFAULT);
					}
				}
			}
		}
	}
	
	// Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
	private void findFields(
		char[] fieldName,
		FieldBinding[] fields,
		Scope scope,
		ObjectVector fieldsFound,
		ObjectVector localsFound,
		boolean onlyStaticFields,
		ReferenceBinding receiverType,
		InvocationSite invocationSite,
		Scope invocationScope,
		boolean implicitCall) {

		// Inherited fields which are hidden by subclasses are filtered out
		// No visibility checks can be performed without the scope & invocationSite
		
		int fieldLength = fieldName.length;
		next : for (int f = fields.length; --f >= 0;) {			
			FieldBinding field = fields[f];

			if (field.isSynthetic())	continue next;

			if (onlyStaticFields && !field.isStatic()) continue next;

			if (fieldLength > field.name.length) continue next;

			if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */))	continue next;

			if (options.checkVisibility
				&& !field.canBeSeenBy(receiverType, invocationSite, scope))	continue next;

			boolean prefixRequired = false;

			for (int i = fieldsFound.size; --i >= 0;) {
				Object[] other = (Object[])fieldsFound.elementAt(i);
				FieldBinding otherField = (FieldBinding) other[0];
				ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
				if (field == otherField && receiverType == otherReceiverType)
					continue next;
				if (CharOperation.equals(field.name, otherField.name, true)) {
					if (field.declaringClass.isSuperclassOf(otherField.declaringClass))
						continue next;
					if (otherField.declaringClass.isInterface())
						if (field.declaringClass.implementsInterface(otherField.declaringClass, true))
							continue next;
					prefixRequired = true;
				}
			}

			for (int l = localsFound.size; --l >= 0;) {
				LocalVariableBinding local = (LocalVariableBinding) localsFound.elementAt(l);	

				if (CharOperation.equals(field.name, local.name, true)) {
					SourceTypeBinding declarationType = scope.enclosingSourceType();
					if (declarationType.isAnonymousType() && declarationType != invocationScope.enclosingSourceType()) {
						continue next;
					}
					prefixRequired = true;
					break;
				}
			}
			
			fieldsFound.add(new Object[]{field, receiverType});
			
			char[] completion = field.name;
			
			if(prefixRequired || options.forceImplicitQualification){
				char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), field.isStatic());
				completion = CharOperation.concat(prefix,completion,'.');
			}

			int relevance = R_DEFAULT;
			relevance += computeRelevanceForCaseMatching(fieldName, field.name);
			relevance += computeRelevanceForExpectingType(field.type);

			requestor
				.acceptField(
					field.declaringClass.qualifiedPackageName(),
					field.declaringClass.qualifiedSourceName(),
					field.name,
					field.type.qualifiedPackageName(),
					field.type.qualifiedSourceName(),
					completion,
			// may include some qualification to resolve ambiguities
			field.modifiers, startPosition - offset, endPosition - offset,
			relevance);
		}
	}

	private void findFields(
		char[] fieldName,
		ReferenceBinding receiverType,
		Scope scope,
		ObjectVector fieldsFound,
		ObjectVector localsFound,
		boolean onlyStaticFields,
		InvocationSite invocationSite,
		Scope invocationScope,
		boolean implicitCall) {

		if (fieldName == null)
			return;

		ReferenceBinding currentType = receiverType;
		ReferenceBinding[][] interfacesToVisit = null;
		int lastPosition = -1;
		do {

			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
			if (itsInterfaces != NoSuperInterfaces) {

				if (interfacesToVisit == null)
					interfacesToVisit = new ReferenceBinding[5][];

				if (++lastPosition == interfacesToVisit.length)
					System.arraycopy(
						interfacesToVisit,
						0,
						interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
						0,
						lastPosition);
				interfacesToVisit[lastPosition] = itsInterfaces;
			}

			FieldBinding[] fields = currentType.availableFields();
			if(fields != null) {
				findFields(
					fieldName,
					fields,
					scope,
					fieldsFound,
					localsFound,
					onlyStaticFields,
					receiverType,
					invocationSite,
					invocationScope,
					implicitCall);
			}
			currentType = currentType.superclass();
		} while (currentType != null);

		if (interfacesToVisit != null) {
			for (int i = 0; i <= lastPosition; i++) {
				ReferenceBinding[] interfaces = interfacesToVisit[i];
				for (int j = 0, length = interfaces.length; j < length; j++) {

					ReferenceBinding anInterface = interfaces[j];
					if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) {
						// if interface as not already been visited
						anInterface.tagBits |= TagBits.InterfaceVisited;

						FieldBinding[] fields = anInterface.availableFields();
						if(fields !=  null) {
							findFields(
								fieldName,
								fields,
								scope,
								fieldsFound,
								localsFound,
								onlyStaticFields,
								receiverType,
								invocationSite,
								invocationScope,
								implicitCall);
						}

						ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
						if (itsInterfaces != NoSuperInterfaces) {
							if (++lastPosition == interfacesToVisit.length)
								System.arraycopy(
									interfacesToVisit,
									0,
									interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
									0,
									lastPosition);
							interfacesToVisit[lastPosition] = itsInterfaces;
						}
					}
				}
			}

			// bit reinitialization
			for (int i = 0; i <= lastPosition; i++) {
				ReferenceBinding[] interfaces = interfacesToVisit[i];
				for (int j = 0, length = interfaces.length; j < length; j++)
					interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
			}
		}
	}

	private void findFieldsAndMethods(
		char[] token,
		TypeBinding receiverType,
		Scope scope,
		InvocationSite invocationSite,
		Scope invocationScope,
		boolean implicitCall) {

		if (token == null)
			return;

		if (receiverType.isBaseType())
			return; // nothing else is possible with base types

		if (receiverType.isArrayType()) {
			if (token.length <= lengthField.length
				&& CharOperation.prefixEquals(token, lengthField, false /* ignore case */
			)) {
				
				int relevance = R_DEFAULT;
				relevance += computeRelevanceForCaseMatching(token,lengthField);
				relevance += computeRelevanceForExpectingType(BaseTypes.IntBinding);
				
				requestor.acceptField(
					NoChar,
					NoChar,
					lengthField,
					NoChar,
					NoChar,
					lengthField,
					CompilerModifiers.AccPublic,
					startPosition - offset,
					endPosition - offset,
					relevance);
			}
			receiverType = scope.getJavaLangObject();
		}

		findFields(
			token,
			(ReferenceBinding) receiverType,
			scope,
			new ObjectVector(),
			new ObjectVector(),
			false,
			invocationSite,
			invocationScope,
			implicitCall);

		findMethods(
			token,
			null,
			(ReferenceBinding) receiverType,
			scope,
			new ObjectVector(),
			false,
			false,
			false,
			invocationSite,
			invocationScope,
			implicitCall);
	}

	private void findImports(CompletionOnImportReference importReference) {
		char[][] tokens = importReference.tokens;
			
		char[] importName = CharOperation.concatWith(tokens, '.');
		
		if (importName.length == 0)
			return;
			
		char[] lastToken = tokens[tokens.length - 1];
		if(lastToken != null && lastToken.length == 0)
			importName = CharOperation.concat(importName, new char[]{'.'});

		resolvingImports = true;
		setSourceRange(
			importReference.sourceStart,
			importReference.declarationSourceEnd);
			
		token =  importName;
		// want to replace the existing .*;
		nameEnvironment.findPackages(importName, this);
		nameEnvironment.findTypes(importName, this);
	}

	// what about onDemand types? Ignore them since it does not happen!
	// import p1.p2.A.*;
	private void findKeywords(char[] keyword, char[][] choices, Scope scope) {

		int length = keyword.length;
		if (length > 0)
			for (int i = 0; i < choices.length; i++)
				if (length <= choices[i].length
					&& CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */
				)){
					int relevance = R_DEFAULT;
					relevance += computeRelevanceForCaseMatching(keyword, choices[i]);
					
					requestor.acceptKeyword(choices[i], startPosition - offset, endPosition - offset,relevance);
				}
	}

	// Helper method for findMemberTypes(char[], ReferenceBinding, Scope)
	private void findMemberTypes(
		char[] typeName,
		ReferenceBinding[] memberTypes,
		ObjectVector typesFound,
		ReferenceBinding receiverType,
		SourceTypeBinding invocationType) {

		// Inherited member types which are hidden by subclasses are filtered out
		// No visibility checks can be performed without the scope & invocationSite
		int typeLength = typeName.length;
		next : for (int m = memberTypes.length; --m >= 0;) {
			ReferenceBinding memberType = memberTypes[m];
			//		if (!wantClasses && memberType.isClass()) continue next;
			//		if (!wantInterfaces && memberType.isInterface()) continue next;
			if (typeLength > memberType.sourceName.length)
				continue next;

			if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false
				/* ignore case */
				))
				continue next;

			if (options.checkVisibility
				&& !memberType.canBeSeenBy(receiverType, invocationType))
				continue next;

			for (int i = typesFound.size; --i >= 0;) {
				ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i);

				if (memberType == otherType)
					continue next;

				if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)) {

					if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType()))
						continue next;

					if (otherType.enclosingType().isInterface())

						if (memberType.enclosingType()
							.implementsInterface(otherType.enclosingType(), true))
							continue next;
				}
			}

			typesFound.add(memberType);

			int relevance = R_DEFAULT;
			relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName);
			relevance += computeRelevanceForExpectingType(memberType);

			if (memberType.isClass()) {
				relevance += computeRelevanceForClass();
				requestor.acceptClass(
					memberType.qualifiedPackageName(),
					memberType.qualifiedSourceName(),
					memberType.sourceName(),
					memberType.modifiers,
					startPosition - offset,
					endPosition - offset,
					relevance);

			} else {
				relevance += computeRelevanceForInterface();
				requestor.acceptInterface(
					memberType.qualifiedPackageName(),
					memberType.qualifiedSourceName(),
					memberType.sourceName(),
					memberType.modifiers,
					startPosition - offset,
					endPosition - offset,
					relevance);
			}
		}
	}

	private void findMemberTypes(
		char[] typeName,
		ReferenceBinding receiverType,
		Scope scope,
		SourceTypeBinding typeInvocation) {

		ReferenceBinding currentType = receiverType;
		if (typeName == null)
			return;

		if (currentType.superInterfaces() == null)
			return; // we're trying to find a supertype

		ObjectVector typesFound = new ObjectVector();
		if (insideQualifiedReference
			|| typeName.length == 0) { // do not search up the hierarchy

			findMemberTypes(
				typeName,
				currentType.memberTypes(),
				typesFound,
				receiverType,
				typeInvocation);
			return;
		}

		ReferenceBinding[][] interfacesToVisit = null;
		int lastPosition = -1;

		do {

			ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
			if (itsInterfaces != NoSuperInterfaces) {

				if (interfacesToVisit == null)
					interfacesToVisit = new ReferenceBinding[5][];

				if (++lastPosition == interfacesToVisit.length)
					System.arraycopy(
						interfacesToVisit,
						0,
						interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
						0,
						lastPosition);
				interfacesToVisit[lastPosition] = itsInterfaces;
			}

			findMemberTypes(
				typeName,
				currentType.memberTypes(),
				typesFound,
				receiverType,
				typeInvocation);
			currentType = currentType.superclass();

		} while (currentType != null);

		if (interfacesToVisit != null) {
			for (int i = 0; i <= lastPosition; i++) {
				ReferenceBinding[] interfaces = interfacesToVisit[i];
				for (int j = 0, length = interfaces.length; j < length; j++) {

					ReferenceBinding anInterface = interfaces[j];
					if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) {
						// if interface as not already been visited
						anInterface.tagBits |= TagBits.InterfaceVisited;

						findMemberTypes(
							typeName,
							anInterface.memberTypes(),
							typesFound,
							receiverType,
							typeInvocation);

						ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
						if (itsInterfaces != NoSuperInterfaces) {

							if (++lastPosition == interfacesToVisit.length)
								System.arraycopy(
									interfacesToVisit,
									0,
									interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
									0,
									lastPosition);
							interfacesToVisit[lastPosition] = itsInterfaces;
						}
					}
				}
			}

			// bit reinitialization
			for (int i = 0; i <= lastPosition; i++) {
				ReferenceBinding[] interfaces = interfacesToVisit[i];
				for (int j = 0, length = interfaces.length; j < length; j++)
					interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
			}
		}
	}

	private void findIntefacesMethods(
		char[] selector,
		TypeBinding[] argTypes,
		ReferenceBinding receiverType,
		ReferenceBinding[] itsInterfaces,
		Scope scope,
		ObjectVector methodsFound,
		boolean onlyStaticMethods,
		boolean exactMatch,
		boolean isCompletingDeclaration,
		InvocationSite invocationSite,
		Scope invocationScope,
		boolean implicitCall) {

		if (selector == null)
			return;

		if (itsInterfaces != NoSuperInterfaces) {
			ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
			int lastPosition = 0;
			interfacesToVisit[lastPosition] = itsInterfaces;
			
			for (int i = 0; i <= lastPosition; i++) {
				ReferenceBinding[] interfaces = interfacesToVisit[i];

				for (int j = 0, length = interfaces.length; j < length; j++) {
					ReferenceBinding currentType = interfaces[j];

					if ((currentType.tagBits & TagBits.InterfaceVisited) == 0) {
						// if interface as not already been visited
						currentType.tagBits |= TagBits.InterfaceVisited;

						MethodBinding[] methods = currentType.availableMethods();
						if(methods != null) {
							if(isCompletingDeclaration){
	
								findLocalMethodDeclarations(
									selector,
									methods,
									scope,
									methodsFound,
									onlyStaticMethods,
									exactMatch,
									receiverType);
	
							} else {
	
								findLocalMethods(
									selector,
									argTypes,
									methods,
									scope,
									methodsFound,
									onlyStaticMethods,
									exactMatch,
									receiverType,
									invocationSite,
									invocationScope,
									implicitCall);
							}
						}

						itsInterfaces = currentType.superInterfaces();
						if (itsInterfaces != NoSuperInterfaces) {

							if (++lastPosition == interfacesToVisit.length)
								System.arraycopy(
									interfacesToVisit,
									0,
									interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
									0,
									lastPosition);
							interfacesToVisit[lastPosition] = itsInterfaces;
						}
					}
				}
			}

			// bit reinitialization
			for (int i = 0; i <= lastPosition; i++) {
				ReferenceBinding[] interfaces = interfacesToVisit[i];

				for (int j = 0, length = interfaces.length; j < length; j++){
					interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
				}
			}
		}
	}
	
	private void findImplicitMessageSends(
		char[] token,
		TypeBinding[] argTypes,
		Scope scope,
		InvocationSite invocationSite,
		Scope invocationScope) {

		if (token == null)
			return;

		boolean staticsOnly = false;
		// need to know if we're in a static context (or inside a constructor)
		ObjectVector methodsFound = new ObjectVector();

		done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found

			switch (scope.kind) {

				case Scope.METHOD_SCOPE :
					// handle the error case inside an explicit constructor call (see MethodScope>>findField)
					MethodScope methodScope = (MethodScope) scope;
					staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
					break;

				case Scope.CLASS_SCOPE :
					ClassScope classScope = (ClassScope) scope;
					SourceTypeBinding enclosingType = classScope.referenceContext.binding;
					findMethods(
						token,
						argTypes,
						enclosingType,
						classScope,
						methodsFound,
						staticsOnly,
						true,
						false,
						invocationSite,
						invocationScope,
						true);
					staticsOnly |= enclosingType.isStatic();
					break;

				case Scope.COMPILATION_UNIT_SCOPE :
					break done;
			}
			scope = scope.parent;
		}
	}

	// Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean)
	private void findLocalMethods(
		char[] methodName,
		TypeBinding[] argTypes,
		MethodBinding[] methods,
		Scope scope,
		ObjectVector methodsFound,
		boolean onlyStaticMethods,
		boolean exactMatch,
		ReferenceBinding receiverType,
		InvocationSite invocationSite,
		Scope invocationScope,
		boolean implicitCall) {

		// Inherited methods which are hidden by subclasses are filtered out
		// No visibility checks can be performed without the scope & invocationSite

		int methodLength = methodName.length;
		int minArgLength = argTypes == null ? 0 : argTypes.length;

		next : for (int f = methods.length; --f >= 0;) {
			MethodBinding method = methods[f];

			if (method.isSynthetic()) continue next;

			if (method.isDefaultAbstract())	continue next;

			if (method.isConstructor()) continue next;

			//		if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
			if (onlyStaticMethods && !method.isStatic()) continue next;

			if (options.checkVisibility
				&& !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;

			if (exactMatch) {
				if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
					))
					continue next;

			} else {

				if (methodLength > method.selector.length)
					continue next;

				if (!CharOperation.prefixEquals(methodName, method.selector, false
					/* ignore case */
					))
					continue next;
			}
			if (minArgLength > method.parameters.length)
				continue next;

			for (int a = minArgLength; --a >= 0;){
				if (argTypes[a] != null){ // can be null if it could not be resolved properly
					if (!scope.areTypesCompatible(argTypes[a], method.parameters[a])) {
						continue next;
					}
				}
			}
			
			boolean prefixRequired = false;
			
			for (int i = methodsFound.size; --i >= 0;) {
				Object[] other = (Object[]) methodsFound.elementAt(i);
				MethodBinding otherMethod = (MethodBinding) other[0];
				ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
				if (method == otherMethod && receiverType == otherReceiverType)
					continue next;

				if (CharOperation.equals(method.selector, otherMethod.selector, true)
					&& method.areParametersEqual(otherMethod)) {

					if (method.declaringClass.isSuperclassOf(otherMethod.declaringClass))
						continue next;

					if (otherMethod.declaringClass.isInterface())
						if (method
							.declaringClass
							.implementsInterface(otherMethod.declaringClass, true))
							continue next;

					if (method.declaringClass.isInterface())
						if(otherMethod
							.declaringClass
							.implementsInterface(method.declaringClass,true))
							continue next;
					prefixRequired = true;
				}
			}

			methodsFound.add(new Object[]{method, receiverType});
			int length = method.parameters.length;
			char[][] parameterPackageNames = new char[length][];
			char[][] parameterTypeNames = new char[length][];

			for (int i = 0; i < length; i++) {
				TypeBinding type = method.parameters[i];
				parameterPackageNames[i] = type.qualifiedPackageName();
				parameterTypeNames[i] = type.qualifiedSourceName();
			}
			char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);

			char[] completion = TypeConstants.NoChar;
			
			int previousStartPosition = startPosition;
			
			// nothing to insert - do not want to replace the existing selector & arguments
			if (!exactMatch) {
				if (source != null
					&& source.length > endPosition
					&& source[endPosition] == '(')
					completion = method.selector;
				else
					completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
			} else {
				if(prefixRequired && (source != null)) {
					completion = CharOperation.subarray(source, startPosition, endPosition);
				} else {
					startPosition = endPosition;
				}
			}
			
			if(prefixRequired || options.forceImplicitQualification){
				char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), method.isStatic());
				completion = CharOperation.concat(prefix,completion,'.');
			}

			int relevance = R_DEFAULT;
			relevance += computeRelevanceForCaseMatching(methodName, method.selector);
			relevance += computeRelevanceForExpectingType(method.returnType);

			requestor.acceptMethod(
				method.declaringClass.qualifiedPackageName(),
				method.declaringClass.qualifiedSourceName(),
				method.selector,
				parameterPackageNames,
				parameterTypeNames,
				parameterNames,
				method.returnType.qualifiedPackageName(),
				method.returnType.qualifiedSourceName(),
				completion,
				method.modifiers,
				startPosition - offset,
				endPosition - offset,
				relevance);
			startPosition = previousStartPosition;
		}
	}
	
	private int computeRelevanceForCaseMatching(char[] token, char[] proposalName){
		if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) {
			return  R_CASE;
		} else {
			return R_DEFAULT;
		}
	}
	private int computeRelevanceForClass(){
		if(assistNodeIsClass) {
			return R_CLASS;
		}
		return 0;
	}
	private int computeRelevanceForInterface(){
		if(assistNodeIsInterface) {
			return R_INTERFACE;
		}
		return R_DEFAULT;
	}
	private int computeRelevanceForException(char[] proposalName){
		
		if(assistNodeIsException &&
			(CharOperation.match(EXCEPTION_PATTERN, proposalName, false) ||
			CharOperation.match(ERROR_PATTERN, proposalName, false))) { 
			return R_EXCEPTION;
		}
		return R_DEFAULT;
	}
	private int computeRelevanceForExpectingType(TypeBinding proposalType){
		if(expectedTypes != null && proposalType != null) {
			for (int i = 0; i < expectedTypes.length; i++) {
				if(Scope.areTypesCompatible(proposalType, expectedTypes[i])) {
					return R_EXPECTED_TYPE;
				}
			}
		} 
		return R_DEFAULT;
	}
	private int computeRelevanceForExpectingType(char[] packageName, char[] typeName){
		if(expectedTypes != null) {
			for (int i = 0; i < expectedTypes.length; i++) {
				if(CharOperation.equals(expectedTypes[i].qualifiedPackageName(), packageName) &&
					CharOperation.equals(expectedTypes[i].qualifiedSourceName(), typeName)) {
					return R_EXPECTED_TYPE;
				}
			}
		} 
		return R_DEFAULT;
	}

	// Helper method for findMethods(char[], MethodBinding[], Scope, ObjectVector, boolean, boolean, boolean, TypeBinding)
	private void findLocalMethodDeclarations(
		char[] methodName,
		MethodBinding[] methods,
		Scope scope,
		ObjectVector methodsFound,
		//	boolean noVoidReturnType, how do you know?
		boolean onlyStaticMethods,
		boolean exactMatch,
		ReferenceBinding receiverType) {

		// Inherited methods which are hidden by subclasses are filtered out
		// No visibility checks can be performed without the scope & invocationSite
		int methodLength = methodName.length;
		next : for (int f = methods.length; --f >= 0;) {

			MethodBinding method = methods[f];
			if (method.isSynthetic())	continue next;
				
			if (method.isDefaultAbstract()) continue next;
			
			if (method.isConstructor()) continue next;
				
			if (method.isFinal()) continue next;

			//		if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
			if (onlyStaticMethods && !method.isStatic()) continue next;

			if (options.checkVisibility
				&& !method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next;

			if (exactMatch) {
				if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
					))
					continue next;

			} else {

				if (methodLength > method.selector.length)
					continue next;

				if (!CharOperation.prefixEquals(methodName, method.selector, false
					/* ignore case */
					))
					continue next;
			}

			for (int i = methodsFound.size; --i >= 0;) {
				MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i);
				if (method == otherMethod)
					continue next;

				if (CharOperation.equals(method.selector, otherMethod.selector, true)
					&& method.areParametersEqual(otherMethod)) {
					continue next;
				}
			}

			methodsFound.add(method);
			
			int length = method.parameters.length;
			char[][] parameterPackageNames = new char[length][];
			char[][] parameterTypeNames = new char[length][];
			
			for (int i = 0; i < length; i++) {
				TypeBinding type = method.parameters[i];
				parameterPackageNames[i] = type.qualifiedPackageName();
				parameterTypeNames[i] = type.qualifiedSourceName();
			}

			char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
			
			StringBuffer completion = new StringBuffer(10);
			// flush uninteresting modifiers
			int insertedModifiers = method.modifiers & ~(CompilerModifiers.AccNative | CompilerModifiers.AccAbstract);

			if (!exactMatch) {
				if(insertedModifiers != CompilerModifiers.AccDefault){
					completion.append(AstNode.modifiersString(insertedModifiers));
				}
				char[] returnPackageName = method.returnType.qualifiedPackageName();
				char[] returnTypeName = method.returnType.qualifiedSourceName();
				if(mustQualifyType(returnPackageName, returnTypeName)) {
					completion.append(CharOperation.concat(returnPackageName, returnTypeName,'.'));
				} else {
					completion.append(method.returnType.sourceName());
				}
				completion.append(' ');
				completion.append(method.selector);
				completion.append('(');

				for(int i = 0; i < length ; i++){
					if(mustQualifyType(parameterPackageNames[i], parameterTypeNames[i])){
						completion.append(CharOperation.concat(parameterPackageNames[i], parameterTypeNames[i], '.'));
					} else {
						completion.append(parameterTypeNames[i]);
					}
					completion.append(' ');
					if(parameterNames != null){
						completion.append(parameterNames[i]);
					} else {
						completion.append('%');
					}
					if(i != (length - 1))
						completion.append(',');	
				}
				completion.append(')');
				
				ReferenceBinding[] exceptions = method.thrownExceptions;
				
				if (exceptions != null && exceptions.length > 0){
					completion.append(' ');
					completion.append(THROWS);
					completion.append(' ');
					for(int i = 0; i < exceptions.length ; i++){
						ReferenceBinding exception = exceptions[i];

						char[] exceptionPackageName = exception.qualifiedPackageName();
						char[] exceptionTypeName = exception.qualifiedSourceName();
						
						if(i != 0){
							completion.append(',');
							completion.append(' ');
						}
						
						if(mustQualifyType(exceptionPackageName, exceptionTypeName)){
							completion.append(CharOperation.concat(exceptionPackageName, exceptionTypeName, '.'));
						} else {
							completion.append(exception.sourceName());
						}
					}
				}
			}

			int relevance = R_DEFAULT;
			relevance += computeRelevanceForCaseMatching(methodName, method.selector);

			requestor.acceptMethodDeclaration(
				method.declaringClass.qualifiedPackageName(),
				method.declaringClass.qualifiedSourceName(),
				method.selector,
				parameterPackageNames,
				parameterTypeNames,
				parameterNames,
				method.returnType.qualifiedPackageName(),
				method.returnType.qualifiedSourceName(),
				completion.toString().toCharArray(),
				method.modifiers,
				startPosition - offset,
				endPosition - offset,
				relevance);
		}
	}
	private void findMethods(
		char[] selector,
		TypeBinding[] argTypes,
		ReferenceBinding receiverType,
		Scope scope,
		ObjectVector methodsFound,
		boolean onlyStaticMethods,
		boolean exactMatch,
		boolean isCompletingDeclaration,
		InvocationSite invocationSite,
		Scope invocationScope,
		boolean implicitCall) {
		if (selector == null)
			return;
		
		if(isCompletingDeclaration) {
			MethodBinding[] methods = receiverType.availableMethods();
			if (methods != null){
				for (int i = 0; i < methods.length; i++) {
					if(!methods[i].isDefaultAbstract()) {
						methodsFound.add(methods[i]);
					}
				}
			}
		}
		
		ReferenceBinding currentType = receiverType;
		if (receiverType.isInterface()) {
			if(isCompletingDeclaration) {
				findIntefacesMethods(
					selector,
					argTypes,
					receiverType,
					currentType.superInterfaces(),
					scope,
					methodsFound,
					onlyStaticMethods,
					exactMatch,
					isCompletingDeclaration,
					invocationSite,
					invocationScope,
					implicitCall);
			} else {
				findIntefacesMethods(
					selector,
					argTypes,
					receiverType,
					new ReferenceBinding[]{currentType},
					scope,
					methodsFound,
					onlyStaticMethods,
					exactMatch,
					isCompletingDeclaration,
					invocationSite,
					invocationScope,
					implicitCall);
			}
			
			currentType = scope.getJavaLangObject();
		} else {
			if(isCompletingDeclaration){
				findIntefacesMethods(
					selector,
					argTypes,
					receiverType,
					currentType.superInterfaces(),
					scope,
					methodsFound,
					onlyStaticMethods,
					exactMatch,
					isCompletingDeclaration,
					invocationSite,
					invocationScope,
					implicitCall);
				
				currentType = receiverType.superclass();
			}
		}
		boolean hasPotentialDefaultAbstractMethods = true;
		while (currentType != null) {
			
			MethodBinding[] methods = currentType.availableMethods();
			if(methods != null) {
				if(isCompletingDeclaration){
					findLocalMethodDeclarations(
						selector,
						methods,
						scope,
						methodsFound,
						onlyStaticMethods,
						exactMatch,
						receiverType);
				} else{
					findLocalMethods(
						selector,
						argTypes,
						methods,
						scope,
						methodsFound,
						onlyStaticMethods,
						exactMatch,
						receiverType,
						invocationSite,
						invocationScope,
						implicitCall);
				}
			}
			
			if(hasPotentialDefaultAbstractMethods && currentType.isAbstract()){
				findIntefacesMethods(
					selector,
					argTypes,
					receiverType,
					currentType.superInterfaces(),
					scope,
					methodsFound,
					onlyStaticMethods,
					exactMatch,
					isCompletingDeclaration,
					invocationSite,
					invocationScope,
					implicitCall);
			} else {
				hasPotentialDefaultAbstractMethods = false;
			}
			currentType = currentType.superclass();
		}
	}
	private char[][] findMethodParameterNames(MethodBinding method, char[][] parameterTypeNames){
		ReferenceBinding bindingType = method.declaringClass;

		char[][] parameterNames = null;
		
		int length = parameterTypeNames.length;

		if (length == 0){
			return TypeConstants.NoCharChar;
		}
		// look into the corresponding unit if it is available
		if (bindingType instanceof SourceTypeBinding){
			SourceTypeBinding sourceType = (SourceTypeBinding) bindingType;

			if (sourceType.scope != null){
				TypeDeclaration parsedType;

				if ((parsedType = sourceType.scope.referenceContext) != null){
					AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method);

					if (methodDecl != null){
						Argument[] arguments = methodDecl.arguments;
						parameterNames = new char[length][];

						for(int i = 0 ; i < length ; i++){
							parameterNames[i] = arguments[i].name;
						}
					}
				}
			}
		}
		// look into the model		
		if(parameterNames == null){
			NameEnvironmentAnswer answer = nameEnvironment.findType(bindingType.compoundName);

			if(answer != null){
				if(answer.isSourceType()) {
					ISourceType sourceType = answer.getSourceTypes()[0];
					ISourceMethod[] sourceMethods = sourceType.getMethods();
					int len = sourceMethods == null ? 0 : sourceMethods.length;
					for(int i = 0; i < len ; i++){
						ISourceMethod sourceMethod = sourceMethods[i];
						char[][] argTypeNames = sourceMethod.getArgumentTypeNames();

						if(argTypeNames != null &&
							CharOperation.equals(method.selector,sourceMethod.getSelector()) &&
							CharOperation.equals(argTypeNames,parameterTypeNames)){
							parameterNames = sourceMethod.getArgumentNames();
							break;
						}
					}
				} 
			}
		}
		return parameterNames;
	}
	
	private void findNestedTypes(
		char[] typeName,
		SourceTypeBinding currentType,
		Scope scope) {
		if (typeName == null)
			return;

		int typeLength = typeName.length;

		while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found

			switch (scope.kind) {

				case Scope.METHOD_SCOPE :
				case Scope.BLOCK_SCOPE :
					BlockScope blockScope = (BlockScope) scope;

					next : for (int i = 0, length = blockScope.scopeIndex; i < length; i++) {

						if (blockScope.subscopes[i] instanceof ClassScope) {
							SourceTypeBinding localType =
								((ClassScope) blockScope.subscopes[i]).referenceContext.binding;

							if (!localType.isAnonymousType()) {
								if (typeLength > localType.sourceName.length)
									continue next;
								if (!CharOperation.prefixEquals(typeName, localType.sourceName, false
									/* ignore case */
									))
									continue next;

								int relevance = R_DEFAULT;
								relevance += computeRelevanceForCaseMatching(typeName, localType.sourceName);
								relevance += computeRelevanceForExpectingType(localType);
								relevance += computeRelevanceForClass();
								
								requestor.acceptClass(
									localType.qualifiedPackageName(),
									localType.sourceName,
									localType.sourceName,
									localType.modifiers,
									startPosition - offset,
									endPosition - offset,
									relevance);
							}
						}
					}
					break;

				case Scope.CLASS_SCOPE :
					findMemberTypes(typeName, scope.enclosingSourceType(), scope, currentType);
					if (typeLength == 0)
						return; // do not search outside the class scope if no prefix was provided
					break;

				case Scope.COMPILATION_UNIT_SCOPE :
					return;
			}
			scope = scope.parent;
		}
	}

	private void findPackages(CompletionOnPackageReference packageStatement) {

		token = CharOperation.concatWith(packageStatement.tokens, '.');
		if (token.length == 0)
			return;

		setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
		nameEnvironment.findPackages(CharOperation.toLowerCase(token), this);
	}

	private void findTypesAndPackages(char[] token, Scope scope) {

		if (token == null)
			return;

		if (scope.enclosingSourceType() != null)
			findNestedTypes(token, scope.enclosingSourceType(), scope);

		if (unitScope != null) {
			int typeLength = token.length;
			SourceTypeBinding[] types = unitScope.topLevelTypes;

			for (int i = 0, length = types.length; i < length; i++) {
				SourceTypeBinding sourceType = types[i]; 

				if (typeLength > sourceType.sourceName.length)	continue;
				
				if (!CharOperation.prefixEquals(token, sourceType.sourceName, false))	continue;

				int relevance = R_DEFAULT;
				relevance += computeRelevanceForCaseMatching(token, sourceType.sourceName);
				relevance += computeRelevanceForExpectingType(sourceType);

				if (sourceType.isClass()){
					relevance += computeRelevanceForClass();
					requestor.acceptClass(
						sourceType.qualifiedPackageName(),
						sourceType.sourceName(),
						sourceType.sourceName(),
						sourceType.modifiers,
						startPosition - offset, 
						endPosition - offset,
						relevance);
				} else {
					relevance += computeRelevanceForInterface();
					requestor.acceptInterface(
						sourceType.qualifiedPackageName(),
						sourceType.sourceName(),
						sourceType.sourceName(),
						sourceType.modifiers,
						startPosition - offset,
						endPosition - offset,
						relevance);
				}
			}
		}

		if (token.length == 0)
			return;

		findKeywords(token, baseTypes, scope);
		nameEnvironment.findTypes(token, this);
		nameEnvironment.findPackages(token, this);
	}

	private void findTypesAndSubpackages(
		char[] token,
		PackageBinding packageBinding) {

		char[] qualifiedName =
			CharOperation.concatWith(packageBinding.compoundName, token, '.');

		if (token == null || token.length == 0) {
			int length = qualifiedName.length;
			System.arraycopy(
				qualifiedName,
				0,
				qualifiedName = new char[length + 1],
				0,
				length);
			qualifiedName[length] = '.';
		}
		nameEnvironment.findTypes(qualifiedName, this);
		nameEnvironment.findPackages(qualifiedName, this);
	}

	private void findVariablesAndMethods(
		char[] token,
		Scope scope,
		InvocationSite invocationSite,
		Scope invocationScope) {

		if (token == null)
			return;

		// Should local variables hide fields from the receiver type or any of its enclosing types?
		// we know its an implicit field/method access... see BlockScope getBinding/getImplicitMethod

		boolean staticsOnly = false;
		// need to know if we're in a static context (or inside a constructor)
		int tokenLength = token.length;

		ObjectVector localsFound = new ObjectVector();
		ObjectVector fieldsFound = new ObjectVector();
		ObjectVector methodsFound = new ObjectVector();

		Scope currentScope = scope;

		done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found

			switch (currentScope.kind) {

				case Scope.METHOD_SCOPE :
					// handle the error case inside an explicit constructor call (see MethodScope>>findField)
					MethodScope methodScope = (MethodScope) currentScope;
					staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;

				case Scope.BLOCK_SCOPE :
					BlockScope blockScope = (BlockScope) currentScope;

					next : for (int i = 0, length = blockScope.locals.length; i < length; i++) {
						LocalVariableBinding local = blockScope.locals[i];

						if (local == null)
							break next;

						if (tokenLength > local.name.length)
							continue next;

						if (!CharOperation.prefixEquals(token, local.name, false /* ignore case */
							))
							continue next;

						if (local.isSecret())
							continue next;

						for (int f = 0; f < localsFound.size; f++) {
							LocalVariableBinding otherLocal =
								(LocalVariableBinding) localsFound.elementAt(f);
							if (CharOperation.equals(otherLocal.name, local.name, false /* ignore case */
								))
								continue next;
						}
						localsFound.add(local);

						int relevance = R_DEFAULT;
						relevance += computeRelevanceForCaseMatching(token, local.name);
						relevance += computeRelevanceForExpectingType(local.type);
						
						requestor.acceptLocalVariable(
							local.name,
							NoChar,
							local.type == null
								? local.declaration.type.toString().toCharArray()
								: local.type.qualifiedSourceName(),
							local.modifiers,
							startPosition - offset,
							endPosition - offset,
							relevance);
					}
					break;

				case Scope.COMPILATION_UNIT_SCOPE :
					break done1;
			}
			currentScope = currentScope.parent;
		}

		currentScope = scope;

		done2 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found

			switch (currentScope.kind) {

				case Scope.CLASS_SCOPE :
					ClassScope classScope = (ClassScope) currentScope;
					SourceTypeBinding enclosingType = classScope.referenceContext.binding;
					/*				if (tokenLength == 0) { // only search inside the type itself if no prefix was provided
										findFields(token, enclosingType.fields(), classScope, fieldsFound, staticsOnly);
										findMethods(token, enclosingType.methods(), classScope, methodsFound, staticsOnly, false);
										break done;
									} else { */
					findFields(
						token,
						enclosingType,
						classScope,
						fieldsFound,
						localsFound,
						staticsOnly,
						invocationSite,
						invocationScope,
						true);

					findMethods(
						token,
						null,
						enclosingType,
						classScope,
						methodsFound,
						staticsOnly,
						false,
						false,
						invocationSite,
						invocationScope,
						true);
					staticsOnly |= enclosingType.isStatic();
					//				}
					break;

				case Scope.COMPILATION_UNIT_SCOPE :
					break done2;
			}
			currentScope = currentScope.parent;
		}
	}

	// Helper method for private void findVariableNames(char[] name, TypeReference type )
	private void findVariableName(char[] token, char[] qualifiedPackageName, char[] qualifiedSourceName, char[] sourceName, char[][] excludeNames, int dim){
			if(sourceName == null || sourceName.length == 0)
				return;
				
			char[] name = null;
			
			// compute variable name for base type
			try{
				nameScanner.setSource(sourceName);
				switch (nameScanner.getNextToken()) {
					case TokenNameint :
					case TokenNamebyte :
					case TokenNameshort :
					case TokenNamechar :
					case TokenNamelong :
					case TokenNamefloat :
					case TokenNamedouble :
					case TokenNameboolean :
						if(token != null && token.length != 0)
							return;
						name = computeBaseNames(sourceName[0], excludeNames);
						break;
				}
				if(name != null) {
					int relevance = R_DEFAULT;
					relevance += computeRelevanceForCaseMatching(token, name);
					
					// accept result
					requestor.acceptVariableName(
						qualifiedPackageName,
						qualifiedSourceName,
						name,
						name,
						startPosition - offset,
						endPosition - offset,
						relevance);
					return;
				}
			} catch(InvalidInputException e){
			}
			
			// compute variable name for non base type
			char[][] names = computeNames(sourceName, dim > 0);
			char[] displayName;
			if (dim > 0){
				int l = qualifiedSourceName.length;
				displayName = new char[l+(2*dim)];
				System.arraycopy(qualifiedSourceName, 0, displayName, 0, l);
				for(int i = 0; i < dim; i++){
					displayName[l+(i*2)] = '[';
					displayName[l+(i*2)+1] = ']';
				}
			} else {
				displayName = qualifiedSourceName;
			}
			next : for(int i = 0 ; i < names.length ; i++){
				name = names[i];
				
				if (!CharOperation.prefixEquals(token, name, false))
					continue next;
				
				// completion must be an identifier (not a keyword, ...).
				try{
					nameScanner.setSource(name);
					if(nameScanner.getNextToken() != TokenNameIdentifier)
						continue next;
				} catch(InvalidInputException e){
					continue next;
				}
				
				int count = 2;
				char[] originalName = name;
				for(int j = 0 ; j < excludeNames.length ; j++){
					if(CharOperation.equals(name, excludeNames[j], false)) {
						name = CharOperation.concat(originalName, String.valueOf(count++).toCharArray());
						j = 0;
					}	
				}
				
				int relevance = R_DEFAULT;
				relevance += computeRelevanceForCaseMatching(token, name);
				
				// accept result
				requestor.acceptVariableName(
					qualifiedPackageName,
					displayName,
					name,
					name,
					startPosition - offset,
					endPosition - offset,
					relevance);
			}
	}

	private void findVariableNames(char[] name, TypeReference type , char[][] excludeNames){

		if(type != null &&
			type.binding != null &&
			type.binding.problemId() == Binding.NoError){
			TypeBinding tb = type.binding;
			findVariableName(
				name,
				tb.leafComponentType().qualifiedPackageName(),
				tb.leafComponentType().qualifiedSourceName(),
				tb.leafComponentType().sourceName(),
				excludeNames,
				type.dimensions());
		}/*	else {
			char[][] typeName = type.getTypeName();
			findVariableName(
				name,
				NoChar,
				CharOperation.concatWith(typeName, '.'),
				typeName[typeName.length - 1],
				excludeNames,
				type.dimensions());
		}*/
	}
	
	public AssistParser getParser() {

		return parser;
	}

	protected void reset() {

		super.reset();
		this.knownPkgs = new HashtableOfObject(10);
		this.knownTypes = new HashtableOfObject(10);
	}

	private void setSourceRange(int start, int end) {

		this.startPosition = start;
		this.endPosition = end + 1;
	}
	
	private char[] computeBaseNames(char firstName, char[][] excludeNames){
		char[] name = new char[]{firstName};
		
		for(int i = 0 ; i < excludeNames.length ; i++){
			if(CharOperation.equals(name, excludeNames[i], false)) {
				name[0]++;
				if(name[0] > 'z')
					name[0] = 'a';
				if(name[0] == firstName)
					return null;
				i = 0;
			}	
		}
		
		return name;
	}
	private void computeExpectedTypes(AstNode parent, Scope scope){
		int expectedTypeCount = 0;
		expectedTypes = new TypeBinding[1];
		
		if(parent instanceof AbstractVariableDeclaration) {
			TypeBinding binding = ((AbstractVariableDeclaration)parent).type.binding;
			if(binding != null) {
				expectedTypes[expectedTypeCount++] = binding;
			}
		} else if(parent instanceof Assignment) {
			TypeBinding binding = ((Assignment)parent).lhsType;
			if(binding != null) {
				expectedTypes[expectedTypeCount++] = binding;
			}
		} else if(parent instanceof ReturnStatement) {
			MethodBinding methodBinding = ((AbstractMethodDeclaration) scope.methodScope().referenceContext).binding;
			TypeBinding binding = methodBinding  == null ? null : methodBinding.returnType;
			if(binding != null) {
				expectedTypes[expectedTypeCount++] = binding;
			}
		}
		
		System.arraycopy(expectedTypes, 0, expectedTypes = new TypeBinding[expectedTypeCount], 0, expectedTypeCount);
	}
	private char[][] computeNames(char[] sourceName, boolean forArray){
		char[][] names = new char[5][];
		int nameCount = 0;
		boolean previousIsUpperCase = false;
		for(int i = sourceName.length - 1 ; i >= 0 ; i--){
			boolean isUpperCase = Character.isUpperCase(sourceName[i]);
			if(isUpperCase && !previousIsUpperCase){
				char[] name = CharOperation.subarray(sourceName,i,sourceName.length);
				if(name.length > 1){
					if(nameCount == names.length) {
						System.arraycopy(names, 0, names = new char[nameCount * 2][], 0, nameCount);
					}
					name[0] = Character.toLowerCase(name[0]);
					
					if(forArray) {
						int length = name.length;
						if (name[length-1] == 's'){
							System.arraycopy(name, 0, name = new char[length + 2], 0, length);
							name[length] = 'e';
							name[length+1] = 's';
						} else {
							System.arraycopy(name, 0, name = new char[length + 1], 0, length);
							name[length] = 's';
						}
					}					
					names[nameCount++] = name;
				}
			}
			previousIsUpperCase = isUpperCase;
		}
		if(nameCount == 0){
			char[] name = CharOperation.toLowerCase(sourceName);
			if(forArray) {
				int length = name.length;
				if (name[length-1] == 's'){
					System.arraycopy(name, 0, name = new char[length + 2], 0, length);
					name[length] = 'e';
					name[length+1] = 's';
				} else {
					System.arraycopy(name, 0, name = new char[length + 1], 0, length);
					name[length] = 's';
				}
			}					
			names[nameCount++] = name;
			
		}
		System.arraycopy(names, 0, names = new char[nameCount][], 0, nameCount);
		return names;
	}
	
	private char[] computePrefix(SourceTypeBinding declarationType, SourceTypeBinding invocationType, boolean isStatic){
		
		StringBuffer completion = new StringBuffer(10);

		if (isStatic) {
			completion.append(declarationType.sourceName());
			
		} else if (declarationType == invocationType) {
			completion.append(THIS);
			
		} else {
			
			if (!declarationType.isNestedType()) {
				
				completion.append(declarationType.sourceName());
				completion.append('.');
				completion.append(THIS);

			} else if (!declarationType.isAnonymousType()) {
				
				completion.append(declarationType.sourceName());
				completion.append('.');
				completion.append(THIS);
				
			}
		}
		
		return completion.toString().toCharArray();
	}
	
	private boolean isEnclosed(ReferenceBinding possibleEnclosingType, ReferenceBinding type){
		if(type.isNestedType()){
			ReferenceBinding enclosing = type.enclosingType();
			while(enclosing != null ){
				if(possibleEnclosingType == enclosing)
					return true;
				enclosing = enclosing.enclosingType();
			}
		}
		return false;
	}

}
