diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index fe8b2e0..88d37bc 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -1,1003 +1,1002 @@
-package org.eclipse.jdt.internal.codeassist;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import java.util.Locale;
-
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.codeassist.impl.*;
-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.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 {
-	CompletionParser parser;
-	ISearchableNameEnvironment nameEnvironment;
-	ICompletionRequestor requestor;
-
-	CompilationUnitScope unitScope;
-	char[] source;
-	boolean resolvingImports = false;
-	boolean insideQualifiedReference = false;
-	int startPosition, endPosition;
-	HashtableOfObject knownPkgs = new HashtableOfObject(10);
-/*
-	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"/*nonNLS*/.toCharArray(),
-			"byte"/*nonNLS*/.toCharArray(),
-			"char"/*nonNLS*/.toCharArray(),
-			"double"/*nonNLS*/.toCharArray(),
-			"float"/*nonNLS*/.toCharArray(),
-			"int"/*nonNLS*/.toCharArray(),
-			"long"/*nonNLS*/.toCharArray(),
-			"short"/*nonNLS*/.toCharArray(),
-			"void"/*nonNLS*/.toCharArray()}; 
-
-	static final char[] classField = "class"/*nonNLS*/.toCharArray();
-	static final char[] lengthField = "length"/*nonNLS*/.toCharArray();
-/**
- * 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 environment com.ibm.codeassist.java.api.ISearchableNameEnvironment
- *      used to resolve type/package references and search for types/packages
- *      based on partial names.
- *
- *  @param requestor com.ibm.codeassist.java.api.ICompletionRequestor
- *      since the engine might produce answers of various forms, the engine 
- *      is associated with a requestor able to accept all possible completions.
- *
- *  @param options com.ibm.compiler.java.api.ConfigurableOptions
- *		set of options used to configure the code assist engine.
- */
-
-public CompletionEngine(
-	ISearchableNameEnvironment nameEnvironment, ICompletionRequestor requestor, ConfigurableOption[] settings) {
-
-	this.requestor = requestor;
-	this.nameEnvironment = nameEnvironment;
-
-	CompilerOptions options = new CompilerOptions(settings);
-	ProblemReporter problemReporter =
-		new ProblemReporter(
-			DefaultErrorHandlingPolicies.proceedWithAllProblems(),
-			options,
-			new DefaultProblemFactory(Locale.getDefault())) {
-				public void record(IProblem problem, CompilationResult unitResult) {
-					if (problem.getID() != ProblemIrritants.UnmatchedBracket) {
-						unitResult.record(problem);
-						CompletionEngine.this.requestor.acceptError(problem);
-					}
-				}
-			};
-
-	this.parser = new CompletionParser(problemReporter);
-	this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, nameEnvironment);
-}
-/**
- * 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[] completionName = CharOperation.concat(packageName, className, '.');
-	if (resolvingImports) {
-		completionName = CharOperation.concat(completionName, new char[] {';'});
-	} else if (!insideQualifiedReference) {
-		if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
-	 		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;
-		}
-	}
-
-	requestor.acceptClass(
-		packageName,
-		className,
-		completionName,
-		modifiers,
-		startPosition,
-		endPosition);
-}
-/**
- * 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[] completionName = CharOperation.concat(packageName, interfaceName, '.');
-	if (resolvingImports) {
-		completionName = CharOperation.concat(completionName, new char[] {';'});
-	} else if (!insideQualifiedReference) {
-		if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
-	 		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;
-		}
-	}
-
-	requestor.acceptInterface(
-		packageName,
-		interfaceName,
-		completionName,
-		modifiers,
-		startPosition,
-		endPosition);
-}
-/**
- * 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);
-	requestor.acceptPackage(
-		packageName,
-		resolvingImports ? CharOperation.concat(packageName, new char[] {'.', '*', ';'}) : packageName,
-		startPosition,
-		endPosition);
-}
-/**
- * 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[] completionName = CharOperation.concat(packageName, typeName, '.');
-	if (resolvingImports) {
-		completionName = CharOperation.concat(completionName, new char[] {';'});
-	} else if (!insideQualifiedReference) {
-		if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
-	 		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;
-		}
-	}
-
-	requestor.acceptType(
-		packageName,
-		typeName,
-		completionName,
-		startPosition,
-		endPosition);
-}
-private void complete(AstNode astNode, Binding qualifiedBinding, Scope scope) {
-	setSourceRange(astNode.sourceStart, astNode.sourceEnd); // defaults... some nodes will change these
-
-	if (astNode instanceof CompletionOnFieldType) {
-		CompletionOnSingleTypeReference type =
-			(CompletionOnSingleTypeReference) ((CompletionOnFieldType) astNode).type;
-		char[] 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);
-	} else if (astNode instanceof CompletionOnSingleNameReference) {
-		char[] token = ((CompletionOnSingleNameReference) astNode).token;
-		findVariablesAndMethods(token, scope);
-		findTypesAndPackages(token, scope); // can be the start of a qualified type name
-	} else if (astNode instanceof CompletionOnSingleTypeReference) {
-		char[] token = ((CompletionOnSingleTypeReference) astNode).token;
-		if (qualifiedBinding == null)
-			findTypesAndPackages(token, scope); // can be the start of a qualified type name
-		else
-			findMemberTypes(token, (ReferenceBinding) qualifiedBinding, scope);
-	} else if (astNode instanceof CompletionOnQualifiedNameReference) {
-		insideQualifiedReference = true;
-		CompletionOnQualifiedNameReference ref = (CompletionOnQualifiedNameReference) astNode;
-		char[] 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);
-		} else if (qualifiedBinding instanceof ReferenceBinding) {
-			ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
-			setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
-			findMemberTypes(token, receiverType, scope);
-			findClassField(token, (TypeBinding) qualifiedBinding);
-			findFields(token, receiverType, scope, new ObjectVector(), true);
-			findMethods(token, null, receiverType, scope, new ObjectVector(), true, 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;
-		CompletionOnQualifiedTypeReference ref = (CompletionOnQualifiedTypeReference) astNode;
-		char[] 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);
-		} 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);
-		findFieldsAndMethods(access.token, (TypeBinding) qualifiedBinding, scope);
-	} else if (astNode instanceof CompletionOnMessageSend) {
-		CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
-		TypeBinding[] argTypes = computeTypes(messageSend.arguments, (BlockScope) scope);
-		if (qualifiedBinding == null)
-			findMessageSends(messageSend.selector, argTypes, scope);
-		else
-			findMethods(messageSend.selector, argTypes, (ReferenceBinding) qualifiedBinding, scope, new ObjectVector(), false, true);
-	} else if (astNode instanceof CompletionOnExplicitConstructorCall) {
-		CompletionOnExplicitConstructorCall constructorCall = (CompletionOnExplicitConstructorCall) astNode;
-		TypeBinding[] argTypes = computeTypes(constructorCall.arguments, (BlockScope) scope);
-		findConstructors((ReferenceBinding) qualifiedBinding, argTypes, scope);
-	} else if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
-		CompletionOnQualifiedAllocationExpression allocExpression = (CompletionOnQualifiedAllocationExpression) astNode;
-		TypeBinding[] argTypes = computeTypes(allocExpression.arguments, (BlockScope) scope);
-		findConstructors((ReferenceBinding) qualifiedBinding, argTypes, scope);
-	} else if (astNode instanceof CompletionOnClassLiteralAccess) {
-		char[] token = ((CompletionOnClassLiteralAccess) astNode).completionIdentifier;
-		findClassField(token, (TypeBinding) qualifiedBinding);
-	}
-}
-/**
- * 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 unit com.ibm.compiler.java.api.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) {
-	try {
-		int actualCompletionPosition = completionPosition - 1; // 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) {
-			// 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);
-							parsedUnit.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);
-				}
-			}
-		}
-
-/* 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
-	} 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 findClassField(char[] token, TypeBinding receiverType) {
-	if (token == null) return;
-
-	if (token.length <= classField.length && CharOperation.prefixEquals(token, classField, false /* ignore case */))
-		requestor.acceptField(
-			NoChar,
-			NoChar,
-			classField,
-			NoChar,
-			NoChar,
-			classField,
-			CompilerModifiers.AccStatic | CompilerModifiers.AccPublic,
-			startPosition,
-			endPosition);
-}
-private void findConstructors(ReferenceBinding currentType, TypeBinding[] argTypes, Scope scope) {
-	// No visibility checks can be performed without the scope & invocationSite
-	MethodBinding[] methods = currentType.methods();
-	int minArgLength = argTypes == null ? 0 : argTypes.length;
-	next : for (int f = methods.length; --f >= 0;) {
-		MethodBinding constructor = methods[f];
-		if (constructor.isConstructor()) {
-			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[] 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.acceptMethod(
-				currentType.qualifiedPackageName(),
-				currentType.qualifiedSourceName(),
-				currentType.sourceName(),
-				parameterPackageNames,
-				parameterTypeNames,
-				TypeConstants.NoChar,
-				TypeConstants.NoChar,
-				completion,
-				constructor.modifiers,
-				endPosition,
-				endPosition);
-		}
-	}
-}
-// Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
-
-private void findFields(
-	char[] fieldName,
-	FieldBinding[] fields,
-	Scope scope,
-	ObjectVector fieldsFound,
-	boolean onlyStaticFields) {
-
-	// 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 (onlyStaticFields && !field.isStatic()) continue next;
-		if (fieldLength > field.name.length) continue next;
-		if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */)) continue next;
-
-		for (int i = fieldsFound.size; --i >= 0;) {
-			FieldBinding otherField = (FieldBinding) fieldsFound.elementAt(i);
-			if (field == otherField) 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;
-			}
-		}
-
-		fieldsFound.add(field);
-		requestor.acceptField(
-			field.declaringClass.qualifiedPackageName(),
-			field.declaringClass.qualifiedSourceName(),
-			field.name,
-			field.type.qualifiedPackageName(),
-			field.type.qualifiedSourceName(),
-			field.name, // may include some qualification to resolve ambiguities
-			field.modifiers,
-			startPosition,
-			endPosition);
-	}
-}
-private void findFields(
-	char[] fieldName,
-	ReferenceBinding receiverType,
-	Scope scope,
-	ObjectVector fieldsFound,
-	boolean onlyStaticFields) {
-
-	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;
-		}
-
-		findFields(fieldName, currentType.fields(), scope, fieldsFound, onlyStaticFields);
-		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;
-
-					findFields(fieldName, anInterface.fields(), scope, fieldsFound, onlyStaticFields);
-
-					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) {
-	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 */))
-			requestor.acceptField(
-				NoChar,
-				NoChar,
-				lengthField,
-				NoChar,
-				NoChar,
-				lengthField,
-				CompilerModifiers.AccPublic,
-				startPosition,
-				endPosition);
-
-		receiverType = scope.getJavaLangObject();
-	}
-
-	findFields(token, (ReferenceBinding) receiverType, scope, new ObjectVector(), false);
-	findMethods(token, null, (ReferenceBinding) receiverType, scope, new ObjectVector(), false, false);
-}
-private void findImports(CompletionOnImportReference importReference) {
-	char[] importName = CharOperation.concatWith(importReference.tokens, '.');
-	if (importName.length == 0) return;
-	resolvingImports = true;
-	setSourceRange(importReference.sourceStart, importReference.declarationSourceEnd); // 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 */))
-				requestor.acceptKeyword(choices[i], startPosition, endPosition);
-}
-// Helper method for findMemberTypes(char[], ReferenceBinding, Scope)
-
-private void findMemberTypes(char[] typeName, ReferenceBinding[] memberTypes, ObjectVector typesFound) {
-
-	// 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;
-
-		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);
-		if (memberType.isClass())
-			requestor.acceptClass(
-				memberType.qualifiedPackageName(),
-				memberType.qualifiedSourceName(),
-				memberType.sourceName(),
-				memberType.modifiers,
-				startPosition,
-				endPosition);
-		else
-			requestor.acceptInterface(
-				memberType.qualifiedPackageName(),
-				memberType.qualifiedSourceName(),
-				memberType.sourceName(),
-				memberType.modifiers,
-				startPosition,
-				endPosition);
-	}
-}
-private void findMemberTypes(char[] typeName, ReferenceBinding currentType, Scope scope) {
-	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);
-		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);
-		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);
-
-					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 findMessageSends(char[] token, TypeBinding[] argTypes, Scope scope) {
-	if (token == null) return;
-
-	boolean staticsOnly = false; // need to know if we're in a static context (or inside a constructor)
-	int tokenLength = token.length;
-	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);
-				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)
-
-private void findMethods(
-	char[] methodName,
-	TypeBinding[] argTypes,
-	MethodBinding[] methods,
-	Scope scope,
-	ObjectVector methodsFound,
-//	boolean noVoidReturnType, how do you know?
-	boolean onlyStaticMethods,
-	boolean exactMatch) {
-
-	// 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.isConstructor()) continue next;
-//		if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
-		if (onlyStaticMethods && !method.isStatic()) 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;
-
-		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)) {
-				if (method.declaringClass.isSuperclassOf(otherMethod.declaringClass)) continue next;
-				if (otherMethod.declaringClass.isInterface())
-					if (method.declaringClass.implementsInterface(otherMethod.declaringClass, true)) 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[] completion = TypeConstants.NoChar; // 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[] {'(', ')'});
-		}
-		requestor.acceptMethod(
-			method.declaringClass.qualifiedPackageName(),
-			method.declaringClass.qualifiedSourceName(),
-			method.selector,
-			parameterPackageNames,
-			parameterTypeNames,
-			method.returnType.qualifiedPackageName(),
-			method.returnType.qualifiedSourceName(),
-			completion,
-			method.modifiers,
-			startPosition,
-			endPosition);
-	}
-}
-private void findMethods(
-	char[] selector,
-	TypeBinding[] argTypes,
-	ReferenceBinding receiverType,
-	Scope scope,
-	ObjectVector methodsFound,
-	boolean onlyStaticMethods,
-	boolean exactMatch) {
-
-	if (selector == null) return;
-
-	ReferenceBinding currentType = receiverType;
-	if (currentType.isInterface()) {
-		findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
-
-		ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
-		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++) {
-					currentType = interfaces[j];
-					if ((currentType.tagBits & TagBits.InterfaceVisited) == 0) { // if interface as not already been visited
-						currentType.tagBits |= TagBits.InterfaceVisited;
-
-						findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
-
-						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;
-			}
-		}
-		currentType = scope.getJavaLangObject();
-	}
-
-	while (currentType != null) {
-		findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
-		currentType = currentType.superclass();
-	}
-}
-private void findNestedTypes(char[] typeName, ReferenceBinding 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;
-
-							requestor.acceptClass(
-								localType.qualifiedPackageName(),
-								localType.sourceName,
-								localType.sourceName,
-								localType.modifiers,
-								startPosition,
-								endPosition);
-						}
-					}
-				}
-				break;
-			case Scope.CLASS_SCOPE :
-				findMemberTypes(typeName, scope.enclosingSourceType(), scope);
-				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) {
-	char[] packageName = CharOperation.concatWith(packageStatement.tokens, '.');
-	if (packageName.length == 0) return;
-
-	setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
-	nameEnvironment.findPackages(CharOperation.toLowerCase(packageName), 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 /* ignore case */)) continue;
-
-			requestor.acceptType(
-				sourceType.qualifiedPackageName(),
-				sourceType.sourceName(),
-				sourceType.sourceName(),
-				startPosition,
-				endPosition);
-		}
-	}
-
-	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) {
-	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)
-	char[][] found = null;
-	int lastPosition = -1;
-	int tokenLength = token.length;
-	ObjectVector fieldsFound = new ObjectVector();
-	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;
-			case Scope.BLOCK_SCOPE :
-				BlockScope blockScope = (BlockScope) scope;
-				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;
-
-					if (found == null) {
-						found = new char[5][];
-					} else {
-						for (int f = 0; f < found.length; f++) {
-							char[] name = found[f];
-							if (name == null) break;
-							if (CharOperation.equals(name, local.name, false /* ignore case */)) continue next;
-						}
-					}
-					if (++lastPosition == found.length)
-						System.arraycopy(found, 0, found = new char[lastPosition * 2][], 0, lastPosition);
-					found[lastPosition] = local.name;
-
-					requestor.acceptLocalVariable(
-						local.name,
-						NoChar,
-						local.type == null ? local.declaration.type.toString().toCharArray() : local.type.qualifiedSourceName(),
-						local.modifiers,
-						startPosition,
-						endPosition);
-				}
-				break;
-			case Scope.CLASS_SCOPE :
-				ClassScope classScope = (ClassScope) scope;
-				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, staticsOnly);
-					findMethods(token, null, enclosingType, classScope, methodsFound, staticsOnly, false);
-					staticsOnly |= enclosingType.isStatic();
-//				}
-				break;
-			case Scope.COMPILATION_UNIT_SCOPE :
-				break done;
-		}
-		scope = scope.parent;
-	}
-}
-public AssistParser getParser(){
-	return parser;
-}
-private boolean mustQualifyType(char[][] packageName, char[] readableTypeName) {
-	// If there are no types defined into the current CU yet.
-	if (unitScope == null)
-		return true;
-	if (CharOperation.equals(unitScope.fPackage.compoundName, packageName))
-		return false;
-
-	ImportBinding[] imports = unitScope.imports;
-	for (int i = 0, length = imports.length; i < length; i++) {
-		if (imports[i].onDemand) {
-			if (CharOperation.equals(imports[i].compoundName, packageName))
-				return false; // how do you match p1.p2.A.* ?
-		} else if (CharOperation.equals(imports[i].readableName(), readableTypeName)) {
-			return false;
-		}
-	}
-	return true;
-}
-protected void reset() {
-	super.reset();
-	this.knownPkgs = new HashtableOfObject(10);
-}
-private void setSourceRange(int start, int end) {
-	this.startPosition = start;
-	this.endPosition = end + 1; // Add 1 for now
-}
-}
+package org.eclipse.jdt.internal.codeassist;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import java.util.Locale;
+
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.codeassist.impl.*;
+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.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+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 {
+	CompletionParser parser;
+	ISearchableNameEnvironment nameEnvironment;
+	ICompletionRequestor requestor;
+
+	CompilationUnitScope unitScope;
+	char[] source;
+	boolean resolvingImports = false;
+	boolean insideQualifiedReference = false;
+	int startPosition, endPosition;
+	HashtableOfObject knownPkgs = new HashtableOfObject(10);
+/*
+	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"/*nonNLS*/.toCharArray(),
+			"byte"/*nonNLS*/.toCharArray(),
+			"char"/*nonNLS*/.toCharArray(),
+			"double"/*nonNLS*/.toCharArray(),
+			"float"/*nonNLS*/.toCharArray(),
+			"int"/*nonNLS*/.toCharArray(),
+			"long"/*nonNLS*/.toCharArray(),
+			"short"/*nonNLS*/.toCharArray(),
+			"void"/*nonNLS*/.toCharArray()}; 
+
+	static final char[] classField = "class"/*nonNLS*/.toCharArray();
+	static final char[] lengthField = "length"/*nonNLS*/.toCharArray();
+/**
+ * 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 environment com.ibm.codeassist.java.api.ISearchableNameEnvironment
+ *      used to resolve type/package references and search for types/packages
+ *      based on partial names.
+ *
+ *  @param requestor com.ibm.codeassist.java.api.ICompletionRequestor
+ *      since the engine might produce answers of various forms, the engine 
+ *      is associated with a requestor able to accept all possible completions.
+ *
+ *  @param options com.ibm.compiler.java.api.ConfigurableOptions
+ *		set of options used to configure the code assist engine.
+ */
+
+public CompletionEngine(
+	ISearchableNameEnvironment nameEnvironment, ICompletionRequestor requestor, ConfigurableOption[] settings) {
+
+	this.requestor = requestor;
+	this.nameEnvironment = nameEnvironment;
+
+	CompilerOptions options = new CompilerOptions(settings);
+	ProblemReporter problemReporter =
+		new ProblemReporter(
+			DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+			options,
+			new DefaultProblemFactory(Locale.getDefault())) {
+				public void record(IProblem problem, CompilationResult unitResult) {
+					if (problem.getID() != ProblemIrritants.UnmatchedBracket) {
+						unitResult.record(problem);
+						CompletionEngine.this.requestor.acceptError(problem);
+					}
+				}
+			};
+
+	this.parser = new CompletionParser(problemReporter);
+	this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, nameEnvironment);
+}
+/**
+ * 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[] completionName = CharOperation.concat(packageName, className, '.');
+	if (resolvingImports) {
+		completionName = CharOperation.concat(completionName, new char[] {';'});
+	} else if (!insideQualifiedReference) {
+		if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
+	 		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;
+		}
+	}
+
+	requestor.acceptClass(
+		packageName,
+		className,
+		completionName,
+		modifiers,
+		startPosition,
+		endPosition);
+}
+/**
+ * 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[] completionName = CharOperation.concat(packageName, interfaceName, '.');
+	if (resolvingImports) {
+		completionName = CharOperation.concat(completionName, new char[] {';'});
+	} else if (!insideQualifiedReference) {
+		if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
+	 		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;
+		}
+	}
+
+	requestor.acceptInterface(
+		packageName,
+		interfaceName,
+		completionName,
+		modifiers,
+		startPosition,
+		endPosition);
+}
+/**
+ * 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);
+	requestor.acceptPackage(
+		packageName,
+		resolvingImports ? CharOperation.concat(packageName, new char[] {'.', '*', ';'}) : packageName,
+		startPosition,
+		endPosition);
+}
+/**
+ * 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[] completionName = CharOperation.concat(packageName, typeName, '.');
+	if (resolvingImports) {
+		completionName = CharOperation.concat(completionName, new char[] {';'});
+	} else if (!insideQualifiedReference) {
+		if (mustQualifyType(CharOperation.splitOn('.', packageName), completionName)) {
+	 		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;
+		}
+	}
+
+	requestor.acceptType(
+		packageName,
+		typeName,
+		completionName,
+		startPosition,
+		endPosition);
+}
+private void complete(AstNode astNode, Binding qualifiedBinding, Scope scope) {
+	setSourceRange(astNode.sourceStart, astNode.sourceEnd); // defaults... some nodes will change these
+
+	if (astNode instanceof CompletionOnFieldType) {
+		CompletionOnSingleTypeReference type =
+			(CompletionOnSingleTypeReference) ((CompletionOnFieldType) astNode).type;
+		char[] 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);
+	} else if (astNode instanceof CompletionOnSingleNameReference) {
+		char[] token = ((CompletionOnSingleNameReference) astNode).token;
+		findVariablesAndMethods(token, scope);
+		findTypesAndPackages(token, scope); // can be the start of a qualified type name
+	} else if (astNode instanceof CompletionOnSingleTypeReference) {
+		char[] token = ((CompletionOnSingleTypeReference) astNode).token;
+		if (qualifiedBinding == null)
+			findTypesAndPackages(token, scope); // can be the start of a qualified type name
+		else
+			findMemberTypes(token, (ReferenceBinding) qualifiedBinding, scope);
+	} else if (astNode instanceof CompletionOnQualifiedNameReference) {
+		insideQualifiedReference = true;
+		CompletionOnQualifiedNameReference ref = (CompletionOnQualifiedNameReference) astNode;
+		char[] 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);
+		} else if (qualifiedBinding instanceof ReferenceBinding) {
+			ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
+			setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+			findMemberTypes(token, receiverType, scope);
+			findClassField(token, (TypeBinding) qualifiedBinding);
+			findFields(token, receiverType, scope, new ObjectVector(), true);
+			findMethods(token, null, receiverType, scope, new ObjectVector(), true, 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;
+		CompletionOnQualifiedTypeReference ref = (CompletionOnQualifiedTypeReference) astNode;
+		char[] 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);
+		} 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);
+		findFieldsAndMethods(access.token, (TypeBinding) qualifiedBinding, scope);
+	} else if (astNode instanceof CompletionOnMessageSend) {
+		CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
+		TypeBinding[] argTypes = computeTypes(messageSend.arguments, (BlockScope) scope);
+		if (qualifiedBinding == null)
+			findMessageSends(messageSend.selector, argTypes, scope);
+		else
+			findMethods(messageSend.selector, argTypes, (ReferenceBinding) qualifiedBinding, scope, new ObjectVector(), false, true);
+	} else if (astNode instanceof CompletionOnExplicitConstructorCall) {
+		CompletionOnExplicitConstructorCall constructorCall = (CompletionOnExplicitConstructorCall) astNode;
+		TypeBinding[] argTypes = computeTypes(constructorCall.arguments, (BlockScope) scope);
+		findConstructors((ReferenceBinding) qualifiedBinding, argTypes, scope);
+	} else if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
+		CompletionOnQualifiedAllocationExpression allocExpression = (CompletionOnQualifiedAllocationExpression) astNode;
+		TypeBinding[] argTypes = computeTypes(allocExpression.arguments, (BlockScope) scope);
+		findConstructors((ReferenceBinding) qualifiedBinding, argTypes, scope);
+	} else if (astNode instanceof CompletionOnClassLiteralAccess) {
+		char[] token = ((CompletionOnClassLiteralAccess) astNode).completionIdentifier;
+		findClassField(token, (TypeBinding) qualifiedBinding);
+	}
+}
+/**
+ * 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 unit com.ibm.compiler.java.api.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) {
+	try {
+		int actualCompletionPosition = completionPosition - 1; // 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) {
+			// 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);
+							parsedUnit.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);
+				}
+			}
+		}
+
+/* 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
+	} 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 findClassField(char[] token, TypeBinding receiverType) {
+	if (token == null) return;
+
+	if (token.length <= classField.length && CharOperation.prefixEquals(token, classField, false /* ignore case */))
+		requestor.acceptField(
+			NoChar,
+			NoChar,
+			classField,
+			NoChar,
+			NoChar,
+			classField,
+			CompilerModifiers.AccStatic | CompilerModifiers.AccPublic,
+			startPosition,
+			endPosition);
+}
+private void findConstructors(ReferenceBinding currentType, TypeBinding[] argTypes, Scope scope) {
+	// No visibility checks can be performed without the scope & invocationSite
+	MethodBinding[] methods = currentType.methods();
+	int minArgLength = argTypes == null ? 0 : argTypes.length;
+	next : for (int f = methods.length; --f >= 0;) {
+		MethodBinding constructor = methods[f];
+		if (constructor.isConstructor()) {
+			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[] 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.acceptMethod(
+				currentType.qualifiedPackageName(),
+				currentType.qualifiedSourceName(),
+				currentType.sourceName(),
+				parameterPackageNames,
+				parameterTypeNames,
+				TypeConstants.NoChar,
+				TypeConstants.NoChar,
+				completion,
+				constructor.modifiers,
+				endPosition,
+				endPosition);
+		}
+	}
+}
+// Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
+
+private void findFields(
+	char[] fieldName,
+	FieldBinding[] fields,
+	Scope scope,
+	ObjectVector fieldsFound,
+	boolean onlyStaticFields) {
+
+	// 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 (onlyStaticFields && !field.isStatic()) continue next;
+		if (fieldLength > field.name.length) continue next;
+		if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */)) continue next;
+
+		for (int i = fieldsFound.size; --i >= 0;) {
+			FieldBinding otherField = (FieldBinding) fieldsFound.elementAt(i);
+			if (field == otherField) 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;
+			}
+		}
+
+		fieldsFound.add(field);
+		requestor.acceptField(
+			field.declaringClass.qualifiedPackageName(),
+			field.declaringClass.qualifiedSourceName(),
+			field.name,
+			field.type.qualifiedPackageName(),
+			field.type.qualifiedSourceName(),
+			field.name, // may include some qualification to resolve ambiguities
+			field.modifiers,
+			startPosition,
+			endPosition);
+	}
+}
+private void findFields(
+	char[] fieldName,
+	ReferenceBinding receiverType,
+	Scope scope,
+	ObjectVector fieldsFound,
+	boolean onlyStaticFields) {
+
+	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;
+		}
+
+		findFields(fieldName, currentType.fields(), scope, fieldsFound, onlyStaticFields);
+		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;
+
+					findFields(fieldName, anInterface.fields(), scope, fieldsFound, onlyStaticFields);
+
+					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) {
+	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 */))
+			requestor.acceptField(
+				NoChar,
+				NoChar,
+				lengthField,
+				NoChar,
+				NoChar,
+				lengthField,
+				CompilerModifiers.AccPublic,
+				startPosition,
+				endPosition);
+
+		receiverType = scope.getJavaLangObject();
+	}
+
+	findFields(token, (ReferenceBinding) receiverType, scope, new ObjectVector(), false);
+	findMethods(token, null, (ReferenceBinding) receiverType, scope, new ObjectVector(), false, false);
+}
+private void findImports(CompletionOnImportReference importReference) {
+	char[] importName = CharOperation.concatWith(importReference.tokens, '.');
+	if (importName.length == 0) return;
+	resolvingImports = true;
+	setSourceRange(importReference.sourceStart, importReference.declarationSourceEnd); // 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 */))
+				requestor.acceptKeyword(choices[i], startPosition, endPosition);
+}
+// Helper method for findMemberTypes(char[], ReferenceBinding, Scope)
+
+private void findMemberTypes(char[] typeName, ReferenceBinding[] memberTypes, ObjectVector typesFound) {
+
+	// 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;
+
+		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);
+		if (memberType.isClass())
+			requestor.acceptClass(
+				memberType.qualifiedPackageName(),
+				memberType.qualifiedSourceName(),
+				memberType.sourceName(),
+				memberType.modifiers,
+				startPosition,
+				endPosition);
+		else
+			requestor.acceptInterface(
+				memberType.qualifiedPackageName(),
+				memberType.qualifiedSourceName(),
+				memberType.sourceName(),
+				memberType.modifiers,
+				startPosition,
+				endPosition);
+	}
+}
+private void findMemberTypes(char[] typeName, ReferenceBinding currentType, Scope scope) {
+	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);
+		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);
+		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);
+
+					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 findMessageSends(char[] token, TypeBinding[] argTypes, Scope scope) {
+	if (token == null) return;
+
+	boolean staticsOnly = false; // need to know if we're in a static context (or inside a constructor)
+	int tokenLength = token.length;
+	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);
+				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)
+
+private void findMethods(
+	char[] methodName,
+	TypeBinding[] argTypes,
+	MethodBinding[] methods,
+	Scope scope,
+	ObjectVector methodsFound,
+//	boolean noVoidReturnType, how do you know?
+	boolean onlyStaticMethods,
+	boolean exactMatch) {
+
+	// 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.isConstructor()) continue next;
+//		if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
+		if (onlyStaticMethods && !method.isStatic()) 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;
+
+		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)) {
+				if (method.declaringClass.isSuperclassOf(otherMethod.declaringClass)) continue next;
+				if (otherMethod.declaringClass.isInterface())
+					if (method.declaringClass.implementsInterface(otherMethod.declaringClass, true)) 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[] completion = TypeConstants.NoChar; // 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[] {'(', ')'});
+		}
+		requestor.acceptMethod(
+			method.declaringClass.qualifiedPackageName(),
+			method.declaringClass.qualifiedSourceName(),
+			method.selector,
+			parameterPackageNames,
+			parameterTypeNames,
+			method.returnType.qualifiedPackageName(),
+			method.returnType.qualifiedSourceName(),
+			completion,
+			method.modifiers,
+			startPosition,
+			endPosition);
+	}
+}
+private void findMethods(
+	char[] selector,
+	TypeBinding[] argTypes,
+	ReferenceBinding receiverType,
+	Scope scope,
+	ObjectVector methodsFound,
+	boolean onlyStaticMethods,
+	boolean exactMatch) {
+
+	if (selector == null) return;
+
+	ReferenceBinding currentType = receiverType;
+	if (currentType.isInterface()) {
+		findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
+
+		ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+		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++) {
+					currentType = interfaces[j];
+					if ((currentType.tagBits & TagBits.InterfaceVisited) == 0) { // if interface as not already been visited
+						currentType.tagBits |= TagBits.InterfaceVisited;
+
+						findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
+
+						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;
+			}
+		}
+		currentType = scope.getJavaLangObject();
+	}
+
+	while (currentType != null) {
+		findMethods(selector, argTypes, currentType.methods(), scope, methodsFound, onlyStaticMethods, exactMatch);
+		currentType = currentType.superclass();
+	}
+}
+private void findNestedTypes(char[] typeName, ReferenceBinding 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;
+
+							requestor.acceptClass(
+								localType.qualifiedPackageName(),
+								localType.sourceName,
+								localType.sourceName,
+								localType.modifiers,
+								startPosition,
+								endPosition);
+						}
+					}
+				}
+				break;
+			case Scope.CLASS_SCOPE :
+				findMemberTypes(typeName, scope.enclosingSourceType(), scope);
+				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) {
+	char[] packageName = CharOperation.concatWith(packageStatement.tokens, '.');
+	if (packageName.length == 0) return;
+
+	setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
+	nameEnvironment.findPackages(CharOperation.toLowerCase(packageName), 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 /* ignore case */)) continue;
+
+			requestor.acceptType(
+				sourceType.qualifiedPackageName(),
+				sourceType.sourceName(),
+				sourceType.sourceName(),
+				startPosition,
+				endPosition);
+		}
+	}
+
+	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) {
+	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)
+	char[][] found = null;
+	int lastPosition = -1;
+	int tokenLength = token.length;
+	ObjectVector fieldsFound = new ObjectVector();
+	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;
+			case Scope.BLOCK_SCOPE :
+				BlockScope blockScope = (BlockScope) scope;
+				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;
+
+					if (found == null) {
+						found = new char[5][];
+					} else {
+						for (int f = 0; f < found.length; f++) {
+							char[] name = found[f];
+							if (name == null) break;
+							if (CharOperation.equals(name, local.name, false /* ignore case */)) continue next;
+						}
+					}
+					if (++lastPosition == found.length)
+						System.arraycopy(found, 0, found = new char[lastPosition * 2][], 0, lastPosition);
+					found[lastPosition] = local.name;
+
+					requestor.acceptLocalVariable(
+						local.name,
+						NoChar,
+						local.type == null ? local.declaration.type.toString().toCharArray() : local.type.qualifiedSourceName(),
+						local.modifiers,
+						startPosition,
+						endPosition);
+				}
+				break;
+			case Scope.CLASS_SCOPE :
+				ClassScope classScope = (ClassScope) scope;
+				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, staticsOnly);
+					findMethods(token, null, enclosingType, classScope, methodsFound, staticsOnly, false);
+					staticsOnly |= enclosingType.isStatic();
+//				}
+				break;
+			case Scope.COMPILATION_UNIT_SCOPE :
+				break done;
+		}
+		scope = scope.parent;
+	}
+}
+public AssistParser getParser(){
+	return parser;
+}
+private boolean mustQualifyType(char[][] packageName, char[] readableTypeName) {
+	// If there are no types defined into the current CU yet.
+	if (unitScope == null)
+		return true;
+	if (CharOperation.equals(unitScope.fPackage.compoundName, packageName))
+		return false;
+
+	ImportBinding[] imports = unitScope.imports;
+	for (int i = 0, length = imports.length; i < length; i++) {
+		if (imports[i].onDemand) {
+			if (CharOperation.equals(imports[i].compoundName, packageName))
+				return false; // how do you match p1.p2.A.* ?
+		} else if (CharOperation.equals(imports[i].readableName(), readableTypeName)) {
+			return false;
+		}
+	}
+	return true;
+}
+protected void reset() {
+	super.reset();
+	this.knownPkgs = new HashtableOfObject(10);
+}
+private void setSourceRange(int start, int end) {
+	this.startPosition = start;
+	this.endPosition = end + 1; // Add 1 for now
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java b/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
index 46432c4..7351fac 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/ISearchRequestor.java
@@ -1,51 +1,50 @@
-package org.eclipse.jdt.internal.codeassist;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.codeassist.*;
-
-/**
- * This is the internal requestor passed to the searchable name environment
- * so as to process the multiple search results as they are discovered.
- *
- * It is used to allow the code assist engine to add some more information
- * to the raw name environment results before answering them to the UI.
- */
-public interface ISearchRequestor {
-/**
- * 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[] typeName, int modifiers);
-/**
- * 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[] typeName, int modifiers);
-/**
- * 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);
-/**
- * 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);
-}
+package org.eclipse.jdt.internal.codeassist;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/**
+ * This is the internal requestor passed to the searchable name environment
+ * so as to process the multiple search results as they are discovered.
+ *
+ * It is used to allow the code assist engine to add some more information
+ * to the raw name environment results before answering them to the UI.
+ */
+public interface ISearchRequestor {
+/**
+ * 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[] typeName, int modifiers);
+/**
+ * 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[] typeName, int modifiers);
+/**
+ * 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);
+/**
+ * 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);
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
index f83e65c..dcb2bd7 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
@@ -1,28 +1,26 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class CompletionNodeFound extends RuntimeException {
-	public AstNode astNode;
-	public Binding qualifiedBinding;
-	public Scope scope;
-public CompletionNodeFound() {
-	this(null, null, null); // we found a problem in the completion node
-}
-public CompletionNodeFound(AstNode astNode, Binding qualifiedBinding, Scope scope) {
-	this.astNode = astNode;
-	this.qualifiedBinding = qualifiedBinding;
-	this.scope = scope;
-}
-public CompletionNodeFound(AstNode astNode, Scope scope) {
-	this(astNode, null, scope);
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class CompletionNodeFound extends RuntimeException {
+	public AstNode astNode;
+	public Binding qualifiedBinding;
+	public Scope scope;
+public CompletionNodeFound() {
+	this(null, null, null); // we found a problem in the completion node
+}
+public CompletionNodeFound(AstNode astNode, Binding qualifiedBinding, Scope scope) {
+	this.astNode = astNode;
+	this.qualifiedBinding = qualifiedBinding;
+	this.scope = scope;
+}
+public CompletionNodeFound(AstNode astNode, Scope scope) {
+	this(astNode, null, scope);
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
index 6b14d5a..8b7a785 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
@@ -1,41 +1,40 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
-
-/*
- * Completion node build by the parser in any case it was intending to
- * reduce an exception type reference containing the completion identifier.
- * e.g.
- *
- *	class X {
- *    void foo() {
- *      try {
- *        bar();
- *      } catch (IOExc[cursor] e) {
- *      }
- *    }
- *  }
- *
- *	---> class X {
- *         void foo() {
- *           try {
- *             bar();
- *           } catch (<CompleteOnException:IOExc> e) {
- *           }
- *         }
- *       }
- *
- * The source range of the completion node denotes the source range
- * which should be replaced by the completion.
- */
-public class CompletionOnExceptionReference extends CompletionOnSingleTypeReference {
-public CompletionOnExceptionReference(char[] source, long pos) {
-	super(source, pos);
-}
-public String toStringExpression(int tab) {
-	return "<CompleteOnException:"/*nonNLS*/ + new String(token) + ">"/*nonNLS*/;
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an exception type reference containing the completion identifier.
+ * e.g.
+ *
+ *	class X {
+ *    void foo() {
+ *      try {
+ *        bar();
+ *      } catch (IOExc[cursor] e) {
+ *      }
+ *    }
+ *  }
+ *
+ *	---> class X {
+ *         void foo() {
+ *           try {
+ *             bar();
+ *           } catch (<CompleteOnException:IOExc> e) {
+ *           }
+ *         }
+ *       }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+public class CompletionOnExceptionReference extends CompletionOnSingleTypeReference {
+public CompletionOnExceptionReference(char[] source, long pos) {
+	super(source, pos);
+}
+public String toStringExpression(int tab) {
+	return "<CompleteOnException:"/*nonNLS*/ + new String(token) + ">"/*nonNLS*/;
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
index 4d02d45..aa522e5 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
@@ -1,50 +1,49 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
-
-/*
- * Completion node build by the parser in any case it was intending to
- * reduce an exception type reference containing the completion identifier 
- * as part of a qualified name.
- * e.g.
- *
- *	class X {
- *    void foo() {
- *      try {
- *        bar();
- *      } catch (java.io.IOExc[cursor] e) {
- *      }
- *    }
- *  }
- *
- *	---> class X {
- *         void foo() {
- *           try {
- *             bar();
- *           } catch (<CompleteOnException:java.io.IOExc> e) {
- *           }
- *         }
- *       }
- *
- * The source range of the completion node denotes the source range
- * which should be replaced by the completion.
- */
-public class CompletionOnQualifiedExceptionReference extends CompletionOnQualifiedTypeReference {
-public CompletionOnQualifiedExceptionReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
-	super(previousIdentifiers, completionIdentifier, positions);
-}
-public String toStringExpression(int tab) {
-
-	StringBuffer buffer = new StringBuffer();
-	buffer. append("<CompleteOnException:"/*nonNLS*/);
-	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		buffer.append("."/*nonNLS*/);
-	}
-	buffer.append(completionIdentifier).append(">"/*nonNLS*/);
-	return buffer.toString();
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an exception type reference containing the completion identifier 
+ * as part of a qualified name.
+ * e.g.
+ *
+ *	class X {
+ *    void foo() {
+ *      try {
+ *        bar();
+ *      } catch (java.io.IOExc[cursor] e) {
+ *      }
+ *    }
+ *  }
+ *
+ *	---> class X {
+ *         void foo() {
+ *           try {
+ *             bar();
+ *           } catch (<CompleteOnException:java.io.IOExc> e) {
+ *           }
+ *         }
+ *       }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+public class CompletionOnQualifiedExceptionReference extends CompletionOnQualifiedTypeReference {
+public CompletionOnQualifiedExceptionReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+	super(previousIdentifiers, completionIdentifier, positions);
+}
+public String toStringExpression(int tab) {
+
+	StringBuffer buffer = new StringBuffer();
+	buffer. append("<CompleteOnException:"/*nonNLS*/);
+	for (int i = 0; i < tokens.length; i++) {
+		buffer.append(tokens[i]);
+		buffer.append("."/*nonNLS*/);
+	}
+	buffer.append(completionIdentifier).append(">"/*nonNLS*/);
+	return buffer.toString();
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index 62a3b91..768e766 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -1,1106 +1,1097 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * Parser able to build specific completion parse nodes, given a cursorLocation.
- *
- * Cursor location denotes the position of the last character behind which completion
- * got requested:
- *  -1 means completion at the very beginning of the source
- *	0  means completion behind the first character
- *  n  means completion behind the n-th character
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.codeassist.impl.*;
-
-public class CompletionParser extends AssistParser {
-
-	/* public fields */
-
-	public int cursorLocation;
-	public char[][] labels; // the visible labels up to the cursor location
-
-
-	/* the following fields are internal flags */
-	
-	boolean betweenNewAndLeftBraket; // whether we are between the keyword 'new' and the following left braket, ie. '[', '(' or '{'
-	boolean betweenCatchAndRightParen; // whether we are between the keyword 'catch' and the following ')'
-	boolean completionBehindDot; // true when completion identifier immediately follows a dot
-
-	// the stacks of types and qualifiers for invocations (ie. method invocations, allocation expressions and
-	// explicit constructor invocations). They use the same stack pointer as the selector stack (ie. invocationPtr)
-	// the invocation type stack contains one of the invocation type constants below
-	// the qualifier stack contains pointers to the expression stack or -1 if there is no qualifier
-	// (a qualifier is the expression that qualifies a 'new', a 'super' constructor or a 'this' constructor
-	//  or it is the receiver of a message send)
-	int[] invocationTypeStack = new int[StackIncrement];
-	int[] qualifierStack = new int[StackIncrement];
-
-	// invocation type constants
-	static final int EXPLICIT_RECEIVER = 0;
-	static final int NO_RECEIVER = -1;
-	static final int SUPER_RECEIVER = -2;
-	static final int NAME_RECEIVER = -3;
-	static final int ALLOCATION = -4;
-	static final int QUALIFIED_ALLOCATION = -5;
-
-	// the type of the current invocation (one of the invocation type constants)
-	int invocationType;
-
-	// a pointer in the expression stack to the qualifier of a invocation
-	int qualifier;
-
-	// a stack of label counters
-	// a new counter is pushed on the stack each time when a method (or a constructor) is entered, 
-	// it is poped when the method (or constructor) is exited,
-	// it is incremented when a new label is defined
-	int labelCounterPtr;
-	int[] labelCounterStack = new int[StackIncrement];
-
-	// a stack of invocationPtr: contains the first invocationPtr of a block
-	// the current invocationPtr+1 is pushed when a block is entered
-	// it is poped when a block is exited 
-	int blockInvocationPtr;
-	int[] blockInvocationStack = new int[StackIncrement];
-public CompletionParser(ProblemReporter problemReporter) {
-	super(problemReporter);
-}
-public char[] assistIdentifier(){
-	return ((CompletionScanner)scanner).completionIdentifier;
-}
-protected void attachOrphanCompletionNode(){
-	if (this.isOrphanCompletionNode) {
-		AstNode orphan = this.assistNode;
-		this.isOrphanCompletionNode = false;
-		
-		/* if in context of a type, then persists the identifier into a fake field return type */
-		if (currentElement instanceof RecoveredType){
-			RecoveredType recoveredType = (RecoveredType)currentElement;
-			/* filter out cases where scanner is still inside type header */
-			if (recoveredType.foundOpeningBrace) {
-				/* generate a pseudo field with a completion on type reference */	
-				if (orphan instanceof TypeReference){
-					currentElement = currentElement.add(
-						new CompletionOnFieldType((TypeReference)orphan), 0);
-					return;
-				}
-			}
-		}
-		/* if in context of a method, persists if inside arguments as a type */
-		if (currentElement instanceof RecoveredMethod){
-			RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
-			/* only consider if inside method header */
-			if (!recoveredMethod.foundOpeningBrace) {
-				//if (rParenPos < lParenPos){ // inside arguments
-				if (orphan instanceof TypeReference){
-					currentElement = currentElement.parent.add(
-						new CompletionOnFieldType((TypeReference)orphan), 0);
-					return;
-				}
-			}
-		}
-
-		// add the completion node to the method declaration or constructor declaration
-		if (orphan instanceof Statement) {
-			/* check for completion at the beginning of method body
-				behind an invalid signature
-			 */
-			RecoveredMethod method = currentElement.enclosingMethod();
-			if (method != null){
-				AbstractMethodDeclaration methodDecl = method.methodDeclaration;
-				if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
-					&& (scanner.searchLineNumber(orphan.sourceStart) == scanner.searchLineNumber(methodDecl.sourceEnd))){
-					return;
-				}
-			}
-			// add the completion node as a statement to the list of block statements
-			currentElement = currentElement.add((Statement)orphan, 0);
-			return;
-		} 
-	}
-	
-	// the following code applies only in methods, constructors or initializers
-	if ((!this.inMethodStack[this.inMethodPtr] && !this.inInitializerStack[this.inInitializerPtr])) { 
-		return;
-	}
-	
-	// push top expression on ast stack if it contains the completion node
-	Expression expression;
-	if (this.expressionPtr > -1 && containsCompletionNode(expression = this.expressionStack[this.expressionPtr])) {
-		/* check for completion at the beginning of method body
-			behind an invalid signature
-		 */
-		RecoveredMethod method = currentElement.enclosingMethod();
-		if (method != null){
-			AbstractMethodDeclaration methodDecl = method.methodDeclaration;
-			if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
-				&& (scanner.searchLineNumber(expression.sourceStart) == scanner.searchLineNumber(methodDecl.sourceEnd))){
-				return;
-			}
-		}
-		if (expression instanceof AllocationExpression) {
-			// keep the context if it is an allocation expression
-			Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(expression);
-			currentElement = currentElement.add(statement, 0);
-		} else {
-			Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(this.assistNode);
-			currentElement = currentElement.add(statement, 0);
-		}
-	}
-}
-public int bodyEnd(AbstractMethodDeclaration method){
-	return cursorLocation;
-}
-public int bodyEnd(Initializer initializer){
-	return cursorLocation;
-}
-/**
- * Checks if the completion is on the exception type of a catch clause.
- * Returns whether we found a completion node.
- */
-private boolean checkCatchClause() {
-	if (this.betweenCatchAndRightParen && this.identifierPtr > -1) { 
-		// NB: if the cursor is on the variable, then it has been reduced (so identifierPtr is -1), 
-		//     thus this can only be a completion on the type of the catch clause
-		this.assistNode = getTypeReference(0);
-		this.lastCheckPoint = this.assistNode.sourceEnd + 1;
-		this.isOrphanCompletionNode = true;
-		return true;
-	}
-	return false;
-}
-/**
- * Checks if the completion is on the type following a 'new'.
- * Returns whether we found a completion node.
- */
-private boolean checkClassInstanceCreation() {
-	if (this.betweenNewAndLeftBraket) {
-		// completion on type inside an allocation expression
-		TypeReference type = getTypeReference(0);
-		this.assistNode = type;
-		this.lastCheckPoint = type.sourceEnd + 1;
-		if (this.invocationType == ALLOCATION) {
-			// non qualified allocation expression: attach it later
-			this.isOrphanCompletionNode = true;
-		} else {
-			// qualified allocation expression
-			QualifiedAllocationExpression allocExpr = new QualifiedAllocationExpression();
-			allocExpr.type = type;
-			allocExpr.enclosingInstance = this.expressionStack[this.qualifier];
-			allocExpr.sourceStart = this.intStack[this.intPtr--];
-			allocExpr.sourceEnd = type.sourceEnd;
-			this.expressionStack[this.qualifier] = allocExpr; // attach it now (it replaces the qualifier expression)
-			this.isOrphanCompletionNode = false;
-		}
-		return true;
-	}
-	return false;
-}
-/**
- * Checks if the completion is on the dot following an array type,
- * a primitive type or an primitive array type.
- * Returns whether we found a completion node.
- */
-private boolean checkClassLiteralAccess() {
-	if (this.identifierLengthPtr >= 1 && this.previousToken == TokenNameDOT) { // (NB: the top id length is 1 and it is for the completion identifier)
-		int length;
-		// if the penultimate id length is negative, 
-		// the completion is after a primitive type or a primitive array type
-		if ((length = this.identifierLengthStack[this.identifierLengthPtr-1]) < 0) {
-			// build the primitive type node
-			int dim = this.isAfterArrayType() ? this.intStack[this.intPtr--] : 0;
-			SingleTypeReference typeRef = (SingleTypeReference)TypeReference.baseTypeReference(-length, dim);
-			typeRef.sourceStart = this.intStack[this.intPtr--];
-			//typeRef.sourceEnd = typeRef.sourceStart + typeRef.token.length; // NB: It's ok to use the length of the token since it doesn't contain any unicode
-
-			// find the completion identifier and its source positions
-			char[] source = identifierStack[identifierPtr];
-			long pos = this.identifierPositionStack[this.identifierPtr--];
-			this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
-
-			// build the completion on class literal access node
-			CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
-			access.completionIdentifier = source;
-			this.identifierLengthPtr--; // pop the length that was used to say it is a primitive type
-			this.assistNode = access;
-			this.isOrphanCompletionNode = true;
-			return true;
-		}
-
-		// if the completion is after a regular array type
-		if (isAfterArrayType()) {
-			// find the completion identifier and its source positions
-			char[] source = identifierStack[identifierPtr];
-			long pos = this.identifierPositionStack[this.identifierPtr--];
-			this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
-			
-			// get the type reference
-			TypeReference typeRef = getTypeReference(this.intPtr--);
-			
-			// build the completion on class literal access node
-			CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
-			access.completionIdentifier = source;
-			this.assistNode = access;
-			this.isOrphanCompletionNode = true;
-			return true;
-		}
-
-	}
-	return false;
-}
-/**
- * Checks if the completion is inside a method invocation or a constructor invocation.
- * Returns whether we found a completion node.
- */
-private boolean checkInvocation() {
-	Expression topExpression = this.expressionPtr >= 0 ? 
-		this.expressionStack[this.expressionPtr] :
-		null;
-	boolean isEmptyNameCompletion = false;
-	boolean isEmptyAssistIdentifier = false;
-	int startInvocationPtr = this.blockInvocationPtr >= 0 ? this.blockInvocationStack[this.blockInvocationPtr] : 0;
-	if (this.invocationPtr >= startInvocationPtr
-		&& ((isEmptyNameCompletion = topExpression == this.assistNode && this.isEmptyNameCompletion()) // eg. it is something like "this.fred([cursor]" but it is not something like "this.fred(1 + [cursor]"
-			|| (isEmptyAssistIdentifier = this.indexOfAssistIdentifier() >= 0 && this.identifierStack[this.identifierPtr].length == 0))) { // eg. it is something like "this.fred(1 [cursor]"
-				
-		// pop empty name completion
-		if (isEmptyNameCompletion) {
-			this.expressionPtr--;
-			this.expressionLengthStack[this.expressionLengthPtr]--;
-		} else if (isEmptyAssistIdentifier) {
-			this.identifierPtr--;
-			this.identifierLengthPtr--;
-		}
-
-		// find receiver and qualifier
-		int invocationType = this.invocationTypeStack[this.invocationPtr];
-		int qualifierExprPtr = this.qualifierStack[this.invocationPtr];
-
-		// find arguments
-		int numArgs = this.expressionPtr - qualifierExprPtr;
-		int argStart = qualifierExprPtr + 1;
-		Expression[] arguments = null;
-		if (numArgs > 0) {
-			// remember the arguments
-			arguments = new Expression[numArgs];
-			System.arraycopy(this.expressionStack, argStart, arguments, 0, numArgs);
-
-			// consume the expression arguments
-			this.expressionPtr -= numArgs;
-			int count = numArgs;
-			while (count > 0) {
-				count -= this.expressionLengthStack[this.expressionLengthPtr--];
-			} 
-		}
-
-		// build ast node
-		if (invocationType != ALLOCATION && invocationType != QUALIFIED_ALLOCATION) {
-			// creates completion on message send	
-			CompletionOnMessageSend messageSend = new CompletionOnMessageSend();
-			messageSend.arguments = arguments;
-			switch (invocationType) {
-				case NO_RECEIVER:
-					// implicit this
-					messageSend.receiver = ThisReference.ThisImplicit;
-					break;
-				case NAME_RECEIVER:
-					// remove selector 
-					this.identifierPtr--; 
-					this.identifierLengthStack[this.identifierLengthPtr]--;
-					// consume the receiver
-					messageSend.receiver = this.getUnspecifiedReference();
-					break;
-				case SUPER_RECEIVER:
-					messageSend.receiver = SuperReference.Super;
-					break;
-				case EXPLICIT_RECEIVER:
-					messageSend.receiver = this.expressionStack[qualifierExprPtr];
-			}
-
-			// set selector
-			messageSend.selector = this.identifierStack[this.selectorStack[this.invocationPtr]];
-			// remove selector
-			if (this.identifierLengthPtr >=0 && this.identifierLengthStack[this.identifierLengthPtr] == 1) {
-				this.identifierPtr--; 
-				this.identifierLengthPtr--;
-			}
-		
-			// no source is going to be replaced
-			messageSend.sourceStart = this.cursorLocation + 1;
-			messageSend.sourceEnd = this.cursorLocation;
-
-			// remember the message send as an orphan completion node
-			this.assistNode = messageSend;
-			this.lastCheckPoint = messageSend.sourceEnd + 1;
-			this.isOrphanCompletionNode = true;
-			return true;
-		} else {
-			int selectorPtr = this.selectorStack[this.invocationPtr];
-			if (selectorPtr == THIS_CONSTRUCTOR || selectorPtr == SUPER_CONSTRUCTOR) {
-				// creates an explicit constructor call
-				CompletionOnExplicitConstructorCall call = new CompletionOnExplicitConstructorCall(
-					(selectorPtr == THIS_CONSTRUCTOR) ? ExplicitConstructorCall.This : ExplicitConstructorCall.Super);
-				call.arguments = arguments;
-				if (invocationType == QUALIFIED_ALLOCATION) {
-					call.qualification = this.expressionStack[qualifierExprPtr];
-				}
-		
-				// no source is going to be replaced
-				call.sourceStart = this.cursorLocation + 1;
-				call.sourceEnd = this.cursorLocation;
-
-				// remember the explicit constructor call as an orphan completion node
-				this.assistNode = call;
-				this.lastCheckPoint = call.sourceEnd + 1;
-				this.isOrphanCompletionNode = true;
-				return true;
-			} else {
-				// creates an allocation expression 
-				CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression();
-				allocExpr.arguments = arguments;
-				allocExpr.type = super.getTypeReference(0); // we don't want a completion node here, so call super
-				if (invocationType == QUALIFIED_ALLOCATION) {
-					allocExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
-				}
-				// no source is going to be replaced
-				allocExpr.sourceStart = this.cursorLocation + 1;
-				allocExpr.sourceEnd = this.cursorLocation;
-				
-				// remember the allocation expression as an orphan completion node
-				this.assistNode = allocExpr;
-				this.lastCheckPoint = allocExpr.sourceEnd + 1;
-				this.isOrphanCompletionNode = true;
-				return true;
-			}
-		}
-	}
-	return false;
-}
-/**
- * Checks if the completion is on a member access (ie. in an identifier following a dot).
- * Returns whether we found a completion node.
- */
-private boolean checkMemberAccess() {
-	if (this.previousToken == TokenNameDOT && this.qualifier > -1 && this.expressionPtr == this.qualifier) {
-		// the receiver is an expression
-		pushCompletionOnMemberAccessOnExpressionStack(false);
-		return true;
-	}
-	return false;
-}
-/**
- * Checks if the completion is on a name reference.
- * Returns whether we found a completion node.
- */
-private boolean checkNameCompletion() {
-	/* 
-		We didn't find any other completion, but the completion identifier is on the identifier stack,
-		so it can only be a completion on name.
-		Note that we allow the completion on a name even if nothing is expected (eg. foo() b[cursor] would
-		be a completion on 'b'). This policy gives more to the user than he/she would expect, but this 
-		simplifies the problem. To fix this, the recovery must be changed to work at a 'statement' granularity
-		instead of at the 'expression' granularity as it does right now.
-	*/ 
-	
-	// NB: at this point the completion identifier is on the identifier stack
-	this.assistNode = getUnspecifiedReferenceOptimized();
-	this.lastCheckPoint = this.assistNode.sourceEnd + 1;
-	this.isOrphanCompletionNode = true;
-	return true;
-}
-/**
- * Checks if the completion is in the context of a method and on the type of one of its arguments
- * Returns whether we found a completion node.
- */
-private boolean checkRecoveredMethod() {
-	if (currentElement instanceof RecoveredMethod){
-		/* check if current awaiting identifier is the completion identifier */
-		if (this.indexOfAssistIdentifier() < 0) return false;
-
-		/* check if on line with an error already - to avoid completing inside 
-			illegal type names e.g.  int[<cursor> */
-		if (lastErrorEndPosition <= cursorLocation+1
-			&& scanner.searchLineNumber(lastErrorEndPosition) 
-				== scanner.searchLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
-			return false;
-		}		
- 		RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
-		/* only consider if inside method header */
-		if (!recoveredMethod.foundOpeningBrace
-			&& lastIgnoredToken == -1) {
-			//if (rParenPos < lParenPos){ // inside arguments
-			this.assistNode = this.getTypeReference(0);
-			this.lastCheckPoint = this.assistNode.sourceEnd + 1;
-			this.isOrphanCompletionNode = true;
-			return true;
-		}
-	}
-	return false;
-}
-/**
- * Checks if the completion is in the context of a type and on a type reference in this type.
- * Persists the identifier into a fake field return type
- * Returns whether we found a completion node.
- */
-private boolean checkRecoveredType() {
-	if (currentElement instanceof RecoveredType){
-		/* check if current awaiting identifier is the completion identifier */
-		if (this.indexOfAssistIdentifier() < 0) return false;
-
-		/* check if on line with an error already - to avoid completing inside 
-			illegal type names e.g.  int[<cursor> */
-		if ((lastErrorEndPosition <= cursorLocation+1)
-			&& scanner.searchLineNumber(lastErrorEndPosition) 
-				== scanner.searchLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
-			return false;
-		}
-		RecoveredType recoveredType = (RecoveredType)currentElement;
-		/* filter out cases where scanner is still inside type header */
-		if (recoveredType.foundOpeningBrace) {
-			this.assistNode = this.getTypeReference(0);
-			this.lastCheckPoint = this.assistNode.sourceEnd + 1;
-			this.isOrphanCompletionNode = true;
-			return true;
-		}
-	}
-	return false;
-}
-/* 
- * Check whether about to shift beyond the completion token.
- * If so, depending on the context, a special node might need to be created
- * and attached to the existing recovered structure so as to be remember in the
- * resulting parsed structure.
- */
-public void completionIdentifierCheck(){
-
-	if (checkRecoveredType()) return;
-	if (checkRecoveredMethod()) return;
-
-	// if not in a method in non diet mode and if not inside a field initializer, only record references attached to types
-	if (!(this.inMethodStack[this.inMethodPtr] && !this.diet)
-		&& !insideFieldInitializer()) return; 
-
-	/*
-	 	In some cases, the completion identifier may not have yet been consumed,
-	 	e.g.  int.[cursor]
-	 	This is because the grammar does not allow any (empty) identifier to follow
-	 	a base type. We thus have to manually force the identifier to be consumed
-	 	(i.e. pushed).
-	 */
-	if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
-		if (cursorLocation < this.scanner.startPosition && this.scanner.currentPosition == this.scanner.startPosition){ // fake empty identifier got issued
-			this.pushIdentifier();					
-		} else if (cursorLocation+1 >= this.scanner.startPosition && cursorLocation < this.scanner.currentPosition){
-			this.pushIdentifier();
-		}
-	}
-
-	// check for different scenarii
-	try {
-		// no need to go further if we found a non empty completion node
-		// (we still need to store labels though)
-		if (this.assistNode != null) {
-			// however inside an invocation, the completion identifier may already have been consumed into an empty name 
-			// completion, so this check should be before we check that we are at the cursor location
-			if (!isEmptyNameCompletion() || checkInvocation()) return;
-		}
-
-		// no need to check further if we are not at the cursor location
-		if (this.indexOfAssistIdentifier() < 0) return;
-
-		if (checkClassInstanceCreation()) return;
-		if (checkCatchClause()) return;
-		if (checkMemberAccess()) return;
-		if (checkClassLiteralAccess()) return;
-
-		// if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor])
-		// (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
-		if (checkInvocation()) return;
-
-		if (checkNameCompletion()) return;
-	} finally {
-		storeLabelsIfNeeded();
-	}
-}
-protected void consumeCaseLabel() {
-	Expression caseExpression = this.expressionStack[this.expressionPtr];
-	if (caseExpression instanceof SingleNameReference || caseExpression instanceof QualifiedNameReference) {
-		// label counter was wrongly incremented in consumeToken
-		if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
-	}
-	super.consumeCaseLabel();
-}
-protected void consumeConditionalExpression(int op) {
-	Expression valueIfTrue = this.expressionStack[this.expressionPtr - 1];
-	if (valueIfTrue instanceof SingleNameReference || valueIfTrue instanceof QualifiedNameReference) {
-		// label counter was wrongly incremented in consumeToken
-		if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
-	}
-	super.consumeConditionalExpression(op);
-}
-protected void consumeConstructorBody() {
-	super.consumeConstructorBody();
-	this.labelCounterPtr--;
-}
-protected void consumeConstructorHeaderName() {
-
-	int index;
-
-	/* no need to take action if not inside assist identifiers */
-	if ((index = indexOfAssistIdentifier()) < 0) {
-		super.consumeConstructorHeaderName();
-		return;
-	}
-		
-	/* force to start recovering in order to get fake field behavior */
-	if (currentElement == null){
-		this.hasReportedError = true; // do not report any error
-	}
-	this.restartRecovery = true;
-}
-/*
- * Copy of code from superclass with the following change:
- * If the cursor location is on the field access, then create a 
- * CompletionOnMemberAccess instead.
- */
-protected void consumeFieldAccess(boolean isSuperAccess) {
-	// FieldAccess ::= Primary '.' 'Identifier'
-	// FieldAccess ::= 'super' '.' 'Identifier'
-
-	// potential receiver is being poped, so reset potential receiver
-	this.invocationType = NO_RECEIVER;
-
-	if (this.indexOfAssistIdentifier() < 0) {
-		super.consumeFieldAccess(isSuperAccess);
-	} else {
-		this.pushCompletionOnMemberAccessOnExpressionStack(isSuperAccess);
-	}
-}
-protected void consumeMethodBody() {
-	super.consumeMethodBody();
-	this.labelCounterPtr--;
-}
-protected void consumeNestedMethod() {
-	super.consumeNestedMethod();
-	this.pushNewLabelCounter();
-}
-protected void consumeStatementLabel() {
-	super.consumeStatementLabel();
-	if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
-}
-protected void consumeToken(int token) {
-	int previous = this.previousToken;
-	int previousIdentifierPtr = this.previousIdentifierPtr;
-	super.consumeToken(token);
-
-	// if in field initializer (directly or not), on the completion identifier and not in recovery mode yet
-	// then position end of file at cursor location (so that we have the same behavior as
-	// in method bodies)
-	if (token == TokenNameIdentifier
-			&& this.identifierStack[this.identifierPtr] == assistIdentifier()
-			&& this.currentElement == null
-			&& this.insideFieldInitializer()) {
-		this.scanner.eofPosition = cursorLocation+1;
-	}
-	
-	// if in a method or if in a field initializer 
-	if (this.inMethodStack[this.inMethodPtr] || this.inInitializerStack[this.inInitializerPtr]) {
-		switch (token) {
-			case TokenNameDOT:
-				switch (previous) {
-					case TokenNamethis: // eg. this[.]fred()
-						this.invocationType = EXPLICIT_RECEIVER;
-						break;
-					case TokenNamesuper: // eg. super[.]fred()
-						this.invocationType = SUPER_RECEIVER;
-						break;
-					case TokenNameIdentifier: // eg. bar[.]fred()
-						if (!this.betweenNewAndLeftBraket) { // eg. not new z.y[.]X()
-							if (this.identifierPtr != previousIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred()
-								this.invocationType = EXPLICIT_RECEIVER;
-							} else {
-								this.invocationType = NAME_RECEIVER;
-							}
-						}
-						break;
-				}
-				break;
-			case TokenNameIdentifier:
-				if (previous == TokenNameDOT) { // eg. foo().[fred]()
-					// if current identifier is the empty completion one
-					if (identifierStack[identifierPtr] == CompletionScanner.EmptyCompletionIdentifier){
-						this.completionBehindDot = true;
-					}
-					if (this.invocationType != SUPER_RECEIVER // eg. not super.[fred]()
-						&& this.invocationType != NAME_RECEIVER // eg. not bar.[fred]()
-						&& this.invocationType != ALLOCATION // eg. not new foo.[Bar]()
-						&& this.invocationType != QUALIFIED_ALLOCATION) { // eg. not fred().new foo.[Bar]()
-
-						this.invocationType = EXPLICIT_RECEIVER;
-						this.qualifier = this.expressionPtr;
-					}
-				}
-				break;	
-			case TokenNamenew:
-				this.betweenNewAndLeftBraket = true;
-				this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed
-				if (previous == TokenNameDOT) { // eg. fred().[new] X()
-					this.invocationType = QUALIFIED_ALLOCATION;
-				} else { // eg. [new] X()
-					this.invocationType = ALLOCATION;
-				}
-				break;
-			case TokenNamethis:
-				if (previous == TokenNameDOT) { // eg. fred().[this]()
-					this.invocationType = QUALIFIED_ALLOCATION;
-					this.qualifier = this.expressionPtr;
-				}
-				break;
-			case TokenNamesuper:
-				if (previous == TokenNameDOT) { // eg. fred().[super]()
-					this.invocationType = QUALIFIED_ALLOCATION;
-					this.qualifier = this.expressionPtr;
-				}
-				break;
-			case TokenNamecatch:
-				this.betweenCatchAndRightParen = true;
-				break;
-			case TokenNameLPAREN:
-				this.betweenNewAndLeftBraket = false;
-				if (this.invocationType == NO_RECEIVER || this.invocationType == NAME_RECEIVER) {
-					this.qualifier = this.expressionPtr; // remenber the last expression so that arguments are correctly computed
-				}
-				switch (previous) {
-					case TokenNameIdentifier: // eg. fred[(]) or foo.fred[(])
-						this.pushOnInvocationStacks(this.invocationType, this.qualifier);
-						this.invocationType = NO_RECEIVER;
-						break;
-					case TokenNamethis: // explicit constructor invocation, eg. this[(]1, 2)
-						this.pushOnInvocationStacks(
-							(this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION, 
-							this.qualifier);
-						this.invocationType = NO_RECEIVER;
-						break;
-					case TokenNamesuper: // explicit constructor invocation, eg. super[(]1, 2)
-						this.pushOnInvocationStacks(
-							(this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION, 
-							this.qualifier);
-						this.invocationType = NO_RECEIVER;
-						break;
-				}
-				break;
-			case TokenNameLBRACE:
-				this.betweenNewAndLeftBraket = false;
-				this.pushBlockInvocationPtr();
-				break;
-			case TokenNameLBRACKET:
-				this.betweenNewAndLeftBraket = false;
-				break;
-			case TokenNameRBRACE:
-				if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
-				break;
-			case TokenNameRPAREN:
-				this.betweenCatchAndRightParen = false;
-				break;
-			case TokenNameCOLON:
-				if (previous == TokenNameIdentifier) {
-					if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]++;
-				}
-				break;
-		}
-	}
-}
-/**
- * Return whether the given ast node contains the completion node.
- */
-private boolean containsCompletionNode(AstNode ast) {
-	if (this.assistNode == null || ast instanceof Literal) {
-		return false;
-	}
-	if (this.assistNode == ast) {
-		return true;
-	}
-	if (ast instanceof Reference || ast instanceof TypeReference) {
-		return ast == this.assistNode;
-	}
-	if (ast instanceof Assignment) {
-		Assignment assign = (Assignment)ast;
-		return containsCompletionNode(assign.lhs) || containsCompletionNode(assign.expression);
-	}
-	if (ast instanceof UnaryExpression) {
-		UnaryExpression unary = (UnaryExpression)ast;
-		return containsCompletionNode(unary.expression);
-	}
-	if (ast instanceof BinaryExpression) {
-		BinaryExpression binary = (BinaryExpression)ast;
-		return containsCompletionNode(binary.left) || containsCompletionNode(binary.right);
-	}
-	if (ast instanceof InstanceOfExpression) {
-		InstanceOfExpression instanceOfExpr = (InstanceOfExpression)ast;
-		return containsCompletionNode(instanceOfExpr.expression) || containsCompletionNode(instanceOfExpr.type);
-	}
-	if (ast instanceof ConditionalExpression) {
-		ConditionalExpression conditional = (ConditionalExpression)ast;
-		return containsCompletionNode(conditional.condition) || containsCompletionNode(conditional.valueIfTrue) || containsCompletionNode(conditional.valueIfFalse);
-	}
-	if (ast instanceof AllocationExpression) {
-		AllocationExpression alloc = (AllocationExpression)ast;
-		return containsCompletionNode(alloc.type);
-	}
-	if (ast instanceof CastExpression) {
-		CastExpression cast = (CastExpression)ast;
-		return containsCompletionNode(cast.expression) || containsCompletionNode(cast.type);
-	}
-	if (ast instanceof ExplicitConstructorCall) {
-		ExplicitConstructorCall call = (ExplicitConstructorCall)ast;
-		Expression[] arguments = call.arguments;
-		if (arguments != null) {
-			for (int i = 0; i < arguments.length; i++) {
-				if (containsCompletionNode(arguments[i])) {
-					return true;
-				}
-			}
-			return false;
-		}
-	}
-	return false;
-}
-public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
-	return new CompletionOnImportReference(tokens, positions);
-}
-public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
-	return new CompletionOnPackageReference(tokens, positions);
-}
-public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
-	return new CompletionOnQualifiedNameReference(
-					previousIdentifiers, 
-					name, 
-					positions); 	
-}
-public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
-	return this.betweenCatchAndRightParen // check for exception scenario 
-				? new CompletionOnQualifiedExceptionReference(
-					previousIdentifiers,  
-					name, 
-					positions)
-				: new CompletionOnQualifiedTypeReference(
-					previousIdentifiers, 
-					name, 
-					positions); 	
-}
-public NameReference createSingleAssistNameReference(char[] name, long position) {
-	return new CompletionOnSingleNameReference(name, position);
-}
-public TypeReference createSingleAssistTypeReference(char[] name, long position) {
-	return this.betweenCatchAndRightParen // check for exception scenario 
-		? new CompletionOnExceptionReference(name, position) 
-		: new CompletionOnSingleTypeReference(name, position);
-}
-public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
-
-	this.cursorLocation = cursorLocation;
-	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
-	completionScanner.completionIdentifier = null;
-	completionScanner.cursorLocation = cursorLocation;
-	return this.dietParse(sourceUnit, compilationResult);
-}
-/*
- * Flush parser/scanner state regarding to code assist
- */
-public void flushAssistState() {
-
-	super.flushAssistState();
-	this.isOrphanCompletionNode = false;
-	this.setAssistIdentifier(null);
-	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
-	completionScanner.completedIdentifierStart = 0;
-	completionScanner.completedIdentifierEnd = -1;
-}
-protected NameReference getUnspecifiedReferenceOptimized() {
-	if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
-		// potential receiver is being poped, so reset potential receiver
-		this.invocationType = NO_RECEIVER;
-	}
-	return super.getUnspecifiedReferenceOptimized();
-}
-/**
- * Return whether the given ast node has information interresting for code completion.
- */
-private boolean hasCompletionInformation(AstNode ast) {
-	return (
-		ast instanceof AbstractMethodDeclaration ||
-		ast instanceof AbstractVariableDeclaration ||
-		ast instanceof LabeledStatement ||
-		ast instanceof TypeDeclaration);
-}
-public void initialize() {
-	super.initialize();
-	this.initializeForBlockStatements();
-	this.labelCounterPtr = -1;
-}
-/*
- * Initializes the state of the parser that is about to go for BlockStatements.
- */
-private void initializeForBlockStatements() {
-	this.previousToken = -1;
-	this.previousIdentifierPtr = -1;
-	this.completionBehindDot = false;
-	this.betweenNewAndLeftBraket = false;
-	this.betweenCatchAndRightParen = false;
-	this.invocationType = NO_RECEIVER;
-	this.qualifier = -1;
-	this.blockInvocationPtr = -1;
-}
-public void initializeScanner(){
-	this.scanner = new CompletionScanner();
-}
-/**
- * Returns whether we are directly or indirectly inside a field initializer.
- */
-private boolean insideFieldInitializer() {
-	for (int i = this.inInitializerPtr; i >= 0; i--) {
-		if (this.inInitializerStack[i]) {
-			return true;
-		}
-	}
-	return false;
-}
-/**
- * Returns whether the completion is just after an array type
- * eg. String[].[cursor]
- */
-private boolean isAfterArrayType() {
-	// TBD: The following relies on the fact that array dimensions are small: it says that if the
-	//      top of the intStack is less than 11, then it must be a dimension 
-	//      (smallest position of array type in a compilation unit is 11 as in "class X{Y[]")
-	int dim = 0;
-	if ((this.intPtr > -1) && (this.intStack[this.intPtr] < 11)) {
-		return true;
-	}
-	return false;
-}
-private boolean isEmptyNameCompletion() {
-	return
-		this.assistNode != null && 
-		this.assistNode instanceof CompletionOnSingleNameReference &&
-		(((CompletionOnSingleNameReference)this.assistNode).token.length == 0);
-}
-public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
-
-	this.cursorLocation = cursorLocation;
-	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
-	completionScanner.completionIdentifier = null;
-	completionScanner.cursorLocation = cursorLocation;
-	return this.parse(sourceUnit, compilationResult);
-}
-/*
- * Prepares the state of the parser to go for BlockStatements.
- */
-protected void prepareForBlockStatements() {
-	super.prepareForBlockStatements();
-	this.initializeForBlockStatements();
-}
-protected void pushBlockInvocationPtr() {
-	try {
-		this.blockInvocationStack[++this.blockInvocationPtr] = this.invocationPtr+1;
-	} catch (IndexOutOfBoundsException e) {
-		int oldStackLength = this.blockInvocationStack.length;
-		int[] oldStack = this.labelCounterStack;
-		this.blockInvocationStack = new int[oldStackLength + StackIncrement];
-		System.arraycopy(oldStack, 0, this.blockInvocationStack, 0, oldStackLength);
-		this.blockInvocationStack[this.blockInvocationPtr] = this.invocationPtr+1;
-	}
-}
-/**
- * Creates a completion on member access node and push it
- * on the expression stack.
- */
-private void pushCompletionOnMemberAccessOnExpressionStack(boolean isSuperAccess) {
-	char[] source = identifierStack[identifierPtr];
-	long pos = identifierPositionStack[identifierPtr--];
-	CompletionOnMemberAccess fr = new CompletionOnMemberAccess(source, pos);
-	this.assistNode = fr;
-	this.lastCheckPoint = fr.sourceEnd + 1;
-	identifierLengthPtr--;
-	if (isSuperAccess) { //considerates the fieldReference beginning at the 'super' ....	
-		fr.sourceStart = intStack[intPtr--];
-		fr.receiver = new SuperReference(fr.sourceStart, endPosition);
-		pushOnExpressionStack(fr);
-	} else { //optimize push/pop
-		if ((fr.receiver = expressionStack[expressionPtr]).isThis()) { //fieldreference begins at the this
-			fr.sourceStart = fr.receiver.sourceStart;
-		}
-		expressionStack[expressionPtr] = fr;
-	}
-}
-protected void pushNewLabelCounter() {
-	try {
-		this.labelCounterStack[++this.labelCounterPtr] = 0;
-	} catch (IndexOutOfBoundsException e) {
-		int oldStackLength = this.labelCounterStack.length;
-		int[] oldStack = this.labelCounterStack;
-		this.labelCounterStack = new int[oldStackLength + StackIncrement];
-		System.arraycopy(oldStack, 0, this.labelCounterStack, 0, oldStackLength);
-		this.labelCounterStack[this.labelCounterPtr] = 0;
-	}
-}
-/**
- * Pushes the given invocation type (one of the invocation type constants) on the invocation type stack,
- * and the given qualifier (an expression pointer to the expression stack) on the qualifier stack.
- */
-protected void pushOnInvocationStacks(int invocationType, int qualifierExprPtr) {
-	// NB: invocationPtr has already been incremented by a call to pushOnSelectorStack()
-	try {
-		this.invocationTypeStack[this.invocationPtr] = invocationType;
-		this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
-	} catch (IndexOutOfBoundsException e) {
-		int oldStackLength = this.invocationTypeStack.length;
-		int oldInvocationTypeStack[] = this.invocationTypeStack;
-		int oldQualifierStack[] = this.qualifierStack;
-		this.invocationTypeStack = new int[oldStackLength + StackIncrement];
-		this.qualifierStack = new int[oldStackLength + StackIncrement];
-		System.arraycopy(oldInvocationTypeStack, 0, this.invocationTypeStack, 0, oldStackLength);
-		System.arraycopy(oldQualifierStack, 0, this.qualifierStack, 0, oldStackLength);
-		this.invocationTypeStack[this.invocationPtr] = invocationType;
-		this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
-	}
-}
-public void recordCompletionOnReference(){
-
-	if (currentElement instanceof RecoveredType){
-		RecoveredType recoveredType = (RecoveredType)currentElement;
-
-		/* filter out cases where scanner is still inside type header */
-		if (!recoveredType.foundOpeningBrace) return;
-		
-		/* generate a pseudo field with a completion on type reference */	
-		currentElement.add(
-			new CompletionOnFieldType(this.getTypeReference(0)), 0);
-		return;
-	}
-	if (!diet) return; // only record references attached to types
-
-}
-protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
-
-	/* Intercept error state on EOF inside method bodies, due to 
-	   cursor location being used as an EOF position.
-	*/
-	if (!diet && currentToken == TokenNameEOF) return;
-	super.reportSyntaxError(act, currentKind, stateStackTop);
-}
-/*
- * Reset internal state after completion is over
- */
- 
-public void reset() {
-	super.reset();
-	this.cursorLocation = 0;
-}
-/*
- * Reset internal state after completion is over
- */
- 
-public void resetAfterCompletion() {
-	this.cursorLocation = 0;
-	this.flushAssistState();
-}
-/*
- * Reset context so as to resume to regular parse loop
- * If unable to reset for resuming, answers false.
- *
- * Move checkpoint location, reset internal stacks and
- * decide which grammar goal is activated.
- */
-protected boolean resumeAfterRecovery() {
-
-	if (this.assistNode != null) {
-		// if an assist node has been found and a recovered element exists,
-		// mark enclosing blocks as to be preserved
-		if (this.currentElement != null) {
-			currentElement.preserveEnclosingBlocks();
-		}
-		/* if reached [eof] inside method body, but still inside nested type,
-			or inside a field initializer, should continue in diet mode until 
-			the end of the method body or compilation unit */
-		if ((scanner.eofPosition == cursorLocation+1)
-			&& (!(referenceContext instanceof CompilationUnitDeclaration) 
-				|| insideFieldInitializer())) {
-
-			/*	disabled since does not handle possible field/message refs, i.e. Obj[ASSIST HERE]ect.registerNatives()		    
-			// consume extra tokens which were part of the qualified reference
-			//   so that the replaced source comprises them as well 
-			if (this.assistNode instanceof NameReference){
-				int oldEof = scanner.eofPosition;
-				scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
-				scanner.currentPosition = this.cursorLocation+1;
-				int token = -1;
-				try {
-					do {
-						// first token might not have to be a dot
-						if (token >= 0 || !this.completionBehindDot){
-							if ((token = scanner.getNextToken()) != TokenNameDOT) break;
-						}
-						if ((token = scanner.getNextToken()) != TokenNameIdentifier) break;
-						this.assistNode.sourceEnd = scanner.currentPosition - 1;
-					} while (token != TokenNameEOF);
-				} catch (InvalidInputException e){
-				} finally {
-					scanner.eofPosition = oldEof;
-				}
-			}
-			*/			
-			/* restart in diet mode for finding sibling constructs */
-			if (currentElement.enclosingType() != null){
-				lastCheckPoint = this.assistNode.sourceEnd+1;
-				scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
-			} else {
-				this.resetStacks();
-				return false;	
-			}
-		}
-	}
-	return super.resumeAfterRecovery();
-}
-public void setAssistIdentifier(char[] assistIdent){
-	((CompletionScanner)scanner).completionIdentifier = assistIdent;
-}
-/**
- * Stores the labels left on the identifier stack if they have not been stored yet.
- */
-private void storeLabelsIfNeeded() {
-	int counter = this.labelCounterPtr >= 0 ? this.labelCounterStack[this.labelCounterPtr] : 0;
-	if (this.labels == null && this.identifierPtr >= 0) {
-		this.labels = new char[counter][];
-		System.arraycopy(this.identifierStack, this.identifierPtr - counter + 1, this.labels, 0, counter);
-	}
-	this.identifierPtr -= counter;
-	this.identifierLengthPtr -= counter; // labels have not been concatenated yet
-}
-/*
- * Update recovery state based on current parser/scanner state
- */
-protected void updateRecoveryState() {
-
-	/* expose parser state to recovery state */
-	currentElement.updateFromParserState();
-
-	/* may be able to retrieve completionNode as an orphan, and then attach it */
-	this.completionIdentifierCheck();
-	this.attachOrphanCompletionNode();
-	
-	/* check and update recovered state based on current token,
-		this action is also performed when shifting token after recovery
-		got activated once. 
-	*/
-	this.recoveryTokenCheck();
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * Parser able to build specific completion parse nodes, given a cursorLocation.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ *  -1 means completion at the very beginning of the source
+ *	0  means completion behind the first character
+ *  n  means completion behind the n-th character
+ */
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.codeassist.impl.*;
+
+public class CompletionParser extends AssistParser {
+
+	/* public fields */
+
+	public int cursorLocation;
+	public char[][] labels; // the visible labels up to the cursor location
+
+
+	/* the following fields are internal flags */
+	
+	boolean betweenNewAndLeftBraket; // whether we are between the keyword 'new' and the following left braket, ie. '[', '(' or '{'
+	boolean betweenCatchAndRightParen; // whether we are between the keyword 'catch' and the following ')'
+	boolean completionBehindDot; // true when completion identifier immediately follows a dot
+
+	// the stacks of types and qualifiers for invocations (ie. method invocations, allocation expressions and
+	// explicit constructor invocations). They use the same stack pointer as the selector stack (ie. invocationPtr)
+	// the invocation type stack contains one of the invocation type constants below
+	// the qualifier stack contains pointers to the expression stack or -1 if there is no qualifier
+	// (a qualifier is the expression that qualifies a 'new', a 'super' constructor or a 'this' constructor
+	//  or it is the receiver of a message send)
+	int[] invocationTypeStack = new int[StackIncrement];
+	int[] qualifierStack = new int[StackIncrement];
+
+	// invocation type constants
+	static final int EXPLICIT_RECEIVER = 0;
+	static final int NO_RECEIVER = -1;
+	static final int SUPER_RECEIVER = -2;
+	static final int NAME_RECEIVER = -3;
+	static final int ALLOCATION = -4;
+	static final int QUALIFIED_ALLOCATION = -5;
+
+	// the type of the current invocation (one of the invocation type constants)
+	int invocationType;
+
+	// a pointer in the expression stack to the qualifier of a invocation
+	int qualifier;
+
+	// a stack of label counters
+	// a new counter is pushed on the stack each time when a method (or a constructor) is entered, 
+	// it is poped when the method (or constructor) is exited,
+	// it is incremented when a new label is defined
+	int labelCounterPtr;
+	int[] labelCounterStack = new int[StackIncrement];
+
+	// a stack of invocationPtr: contains the first invocationPtr of a block
+	// the current invocationPtr+1 is pushed when a block is entered
+	// it is poped when a block is exited 
+	int blockInvocationPtr;
+	int[] blockInvocationStack = new int[StackIncrement];
+public CompletionParser(ProblemReporter problemReporter) {
+	super(problemReporter);
+}
+public char[] assistIdentifier(){
+	return ((CompletionScanner)scanner).completionIdentifier;
+}
+protected void attachOrphanCompletionNode(){
+	if (this.isOrphanCompletionNode) {
+		AstNode orphan = this.assistNode;
+		this.isOrphanCompletionNode = false;
+		
+		/* if in context of a type, then persists the identifier into a fake field return type */
+		if (currentElement instanceof RecoveredType){
+			RecoveredType recoveredType = (RecoveredType)currentElement;
+			/* filter out cases where scanner is still inside type header */
+			if (recoveredType.foundOpeningBrace) {
+				/* generate a pseudo field with a completion on type reference */	
+				if (orphan instanceof TypeReference){
+					currentElement = currentElement.add(
+						new CompletionOnFieldType((TypeReference)orphan), 0);
+					return;
+				}
+			}
+		}
+		/* if in context of a method, persists if inside arguments as a type */
+		if (currentElement instanceof RecoveredMethod){
+			RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+			/* only consider if inside method header */
+			if (!recoveredMethod.foundOpeningBrace) {
+				//if (rParenPos < lParenPos){ // inside arguments
+				if (orphan instanceof TypeReference){
+					currentElement = currentElement.parent.add(
+						new CompletionOnFieldType((TypeReference)orphan), 0);
+					return;
+				}
+			}
+		}
+
+		// add the completion node to the method declaration or constructor declaration
+		if (orphan instanceof Statement) {
+			/* check for completion at the beginning of method body
+				behind an invalid signature
+			 */
+			RecoveredMethod method = currentElement.enclosingMethod();
+			if (method != null){
+				AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+				if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+					&& (scanner.searchLineNumber(orphan.sourceStart) == scanner.searchLineNumber(methodDecl.sourceEnd))){
+					return;
+				}
+			}
+			// add the completion node as a statement to the list of block statements
+			currentElement = currentElement.add((Statement)orphan, 0);
+			return;
+		} 
+	}
+	
+	// the following code applies only in methods, constructors or initializers
+	if ((!this.inMethodStack[this.inMethodPtr] && !this.inInitializerStack[this.inInitializerPtr])) { 
+		return;
+	}
+	
+	// push top expression on ast stack if it contains the completion node
+	Expression expression;
+	if (this.expressionPtr > -1 && containsCompletionNode(expression = this.expressionStack[this.expressionPtr])) {
+		/* check for completion at the beginning of method body
+			behind an invalid signature
+		 */
+		RecoveredMethod method = currentElement.enclosingMethod();
+		if (method != null){
+			AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+			if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+				&& (scanner.searchLineNumber(expression.sourceStart) == scanner.searchLineNumber(methodDecl.sourceEnd))){
+				return;
+			}
+		}
+		if (expression instanceof AllocationExpression) {
+			// keep the context if it is an allocation expression
+			Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(expression);
+			currentElement = currentElement.add(statement, 0);
+		} else {
+			Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(this.assistNode);
+			currentElement = currentElement.add(statement, 0);
+		}
+	}
+}
+public int bodyEnd(AbstractMethodDeclaration method){
+	return cursorLocation;
+}
+public int bodyEnd(Initializer initializer){
+	return cursorLocation;
+}
+/**
+ * Checks if the completion is on the exception type of a catch clause.
+ * Returns whether we found a completion node.
+ */
+private boolean checkCatchClause() {
+	if (this.betweenCatchAndRightParen && this.identifierPtr > -1) { 
+		// NB: if the cursor is on the variable, then it has been reduced (so identifierPtr is -1), 
+		//     thus this can only be a completion on the type of the catch clause
+		this.assistNode = getTypeReference(0);
+		this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+		this.isOrphanCompletionNode = true;
+		return true;
+	}
+	return false;
+}
+/**
+ * Checks if the completion is on the type following a 'new'.
+ * Returns whether we found a completion node.
+ */
+private boolean checkClassInstanceCreation() {
+	if (this.betweenNewAndLeftBraket) {
+		// completion on type inside an allocation expression
+		TypeReference type = getTypeReference(0);
+		this.assistNode = type;
+		this.lastCheckPoint = type.sourceEnd + 1;
+		if (this.invocationType == ALLOCATION) {
+			// non qualified allocation expression: attach it later
+			this.isOrphanCompletionNode = true;
+		} else {
+			// qualified allocation expression
+			QualifiedAllocationExpression allocExpr = new QualifiedAllocationExpression();
+			allocExpr.type = type;
+			allocExpr.enclosingInstance = this.expressionStack[this.qualifier];
+			allocExpr.sourceStart = this.intStack[this.intPtr--];
+			allocExpr.sourceEnd = type.sourceEnd;
+			this.expressionStack[this.qualifier] = allocExpr; // attach it now (it replaces the qualifier expression)
+			this.isOrphanCompletionNode = false;
+		}
+		return true;
+	}
+	return false;
+}
+/**
+ * Checks if the completion is on the dot following an array type,
+ * a primitive type or an primitive array type.
+ * Returns whether we found a completion node.
+ */
+private boolean checkClassLiteralAccess() {
+	if (this.identifierLengthPtr >= 1 && this.previousToken == TokenNameDOT) { // (NB: the top id length is 1 and it is for the completion identifier)
+		int length;
+		// if the penultimate id length is negative, 
+		// the completion is after a primitive type or a primitive array type
+		if ((length = this.identifierLengthStack[this.identifierLengthPtr-1]) < 0) {
+			// build the primitive type node
+			int dim = this.isAfterArrayType() ? this.intStack[this.intPtr--] : 0;
+			SingleTypeReference typeRef = (SingleTypeReference)TypeReference.baseTypeReference(-length, dim);
+			typeRef.sourceStart = this.intStack[this.intPtr--];
+			//typeRef.sourceEnd = typeRef.sourceStart + typeRef.token.length; // NB: It's ok to use the length of the token since it doesn't contain any unicode
+
+			// find the completion identifier and its source positions
+			char[] source = identifierStack[identifierPtr];
+			long pos = this.identifierPositionStack[this.identifierPtr--];
+			this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
+
+			// build the completion on class literal access node
+			CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
+			access.completionIdentifier = source;
+			this.identifierLengthPtr--; // pop the length that was used to say it is a primitive type
+			this.assistNode = access;
+			this.isOrphanCompletionNode = true;
+			return true;
+		}
+
+		// if the completion is after a regular array type
+		if (isAfterArrayType()) {
+			// find the completion identifier and its source positions
+			char[] source = identifierStack[identifierPtr];
+			long pos = this.identifierPositionStack[this.identifierPtr--];
+			this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
+			
+			// get the type reference
+			TypeReference typeRef = getTypeReference(this.intPtr--);
+			
+			// build the completion on class literal access node
+			CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
+			access.completionIdentifier = source;
+			this.assistNode = access;
+			this.isOrphanCompletionNode = true;
+			return true;
+		}
+
+	}
+	return false;
+}
+/**
+ * Checks if the completion is inside a method invocation or a constructor invocation.
+ * Returns whether we found a completion node.
+ */
+private boolean checkInvocation() {
+	Expression topExpression = this.expressionPtr >= 0 ? 
+		this.expressionStack[this.expressionPtr] :
+		null;
+	boolean isEmptyNameCompletion = false;
+	boolean isEmptyAssistIdentifier = false;
+	int startInvocationPtr = this.blockInvocationPtr >= 0 ? this.blockInvocationStack[this.blockInvocationPtr] : 0;
+	if (this.invocationPtr >= startInvocationPtr
+		&& ((isEmptyNameCompletion = topExpression == this.assistNode && this.isEmptyNameCompletion()) // eg. it is something like "this.fred([cursor]" but it is not something like "this.fred(1 + [cursor]"
+			|| (isEmptyAssistIdentifier = this.indexOfAssistIdentifier() >= 0 && this.identifierStack[this.identifierPtr].length == 0))) { // eg. it is something like "this.fred(1 [cursor]"
+				
+		// pop empty name completion
+		if (isEmptyNameCompletion) {
+			this.expressionPtr--;
+			this.expressionLengthStack[this.expressionLengthPtr]--;
+		} else if (isEmptyAssistIdentifier) {
+			this.identifierPtr--;
+			this.identifierLengthPtr--;
+		}
+
+		// find receiver and qualifier
+		int invocationType = this.invocationTypeStack[this.invocationPtr];
+		int qualifierExprPtr = this.qualifierStack[this.invocationPtr];
+
+		// find arguments
+		int numArgs = this.expressionPtr - qualifierExprPtr;
+		int argStart = qualifierExprPtr + 1;
+		Expression[] arguments = null;
+		if (numArgs > 0) {
+			// remember the arguments
+			arguments = new Expression[numArgs];
+			System.arraycopy(this.expressionStack, argStart, arguments, 0, numArgs);
+
+			// consume the expression arguments
+			this.expressionPtr -= numArgs;
+			int count = numArgs;
+			while (count > 0) {
+				count -= this.expressionLengthStack[this.expressionLengthPtr--];
+			} 
+		}
+
+		// build ast node
+		if (invocationType != ALLOCATION && invocationType != QUALIFIED_ALLOCATION) {
+			// creates completion on message send	
+			CompletionOnMessageSend messageSend = new CompletionOnMessageSend();
+			messageSend.arguments = arguments;
+			switch (invocationType) {
+				case NO_RECEIVER:
+					// implicit this
+					messageSend.receiver = ThisReference.ThisImplicit;
+					break;
+				case NAME_RECEIVER:
+					// remove selector 
+					this.identifierPtr--; 
+					this.identifierLengthStack[this.identifierLengthPtr]--;
+					// consume the receiver
+					messageSend.receiver = this.getUnspecifiedReference();
+					break;
+				case SUPER_RECEIVER:
+					messageSend.receiver = SuperReference.Super;
+					break;
+				case EXPLICIT_RECEIVER:
+					messageSend.receiver = this.expressionStack[qualifierExprPtr];
+			}
+
+			// set selector
+			messageSend.selector = this.identifierStack[this.selectorStack[this.invocationPtr]];
+			// remove selector
+			if (this.identifierLengthPtr >=0 && this.identifierLengthStack[this.identifierLengthPtr] == 1) {
+				this.identifierPtr--; 
+				this.identifierLengthPtr--;
+			}
+		
+			// no source is going to be replaced
+			messageSend.sourceStart = this.cursorLocation + 1;
+			messageSend.sourceEnd = this.cursorLocation;
+
+			// remember the message send as an orphan completion node
+			this.assistNode = messageSend;
+			this.lastCheckPoint = messageSend.sourceEnd + 1;
+			this.isOrphanCompletionNode = true;
+			return true;
+		} else {
+			int selectorPtr = this.selectorStack[this.invocationPtr];
+			if (selectorPtr == THIS_CONSTRUCTOR || selectorPtr == SUPER_CONSTRUCTOR) {
+				// creates an explicit constructor call
+				CompletionOnExplicitConstructorCall call = new CompletionOnExplicitConstructorCall(
+					(selectorPtr == THIS_CONSTRUCTOR) ? ExplicitConstructorCall.This : ExplicitConstructorCall.Super);
+				call.arguments = arguments;
+				if (invocationType == QUALIFIED_ALLOCATION) {
+					call.qualification = this.expressionStack[qualifierExprPtr];
+				}
+		
+				// no source is going to be replaced
+				call.sourceStart = this.cursorLocation + 1;
+				call.sourceEnd = this.cursorLocation;
+
+				// remember the explicit constructor call as an orphan completion node
+				this.assistNode = call;
+				this.lastCheckPoint = call.sourceEnd + 1;
+				this.isOrphanCompletionNode = true;
+				return true;
+			} else {
+				// creates an allocation expression 
+				CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression();
+				allocExpr.arguments = arguments;
+				allocExpr.type = super.getTypeReference(0); // we don't want a completion node here, so call super
+				if (invocationType == QUALIFIED_ALLOCATION) {
+					allocExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
+				}
+				// no source is going to be replaced
+				allocExpr.sourceStart = this.cursorLocation + 1;
+				allocExpr.sourceEnd = this.cursorLocation;
+				
+				// remember the allocation expression as an orphan completion node
+				this.assistNode = allocExpr;
+				this.lastCheckPoint = allocExpr.sourceEnd + 1;
+				this.isOrphanCompletionNode = true;
+				return true;
+			}
+		}
+	}
+	return false;
+}
+/**
+ * Checks if the completion is on a member access (ie. in an identifier following a dot).
+ * Returns whether we found a completion node.
+ */
+private boolean checkMemberAccess() {
+	if (this.previousToken == TokenNameDOT && this.qualifier > -1 && this.expressionPtr == this.qualifier) {
+		// the receiver is an expression
+		pushCompletionOnMemberAccessOnExpressionStack(false);
+		return true;
+	}
+	return false;
+}
+/**
+ * Checks if the completion is on a name reference.
+ * Returns whether we found a completion node.
+ */
+private boolean checkNameCompletion() {
+	/* 
+		We didn't find any other completion, but the completion identifier is on the identifier stack,
+		so it can only be a completion on name.
+		Note that we allow the completion on a name even if nothing is expected (eg. foo() b[cursor] would
+		be a completion on 'b'). This policy gives more to the user than he/she would expect, but this 
+		simplifies the problem. To fix this, the recovery must be changed to work at a 'statement' granularity
+		instead of at the 'expression' granularity as it does right now.
+	*/ 
+	
+	// NB: at this point the completion identifier is on the identifier stack
+	this.assistNode = getUnspecifiedReferenceOptimized();
+	this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+	this.isOrphanCompletionNode = true;
+	return true;
+}
+/**
+ * Checks if the completion is in the context of a method and on the type of one of its arguments
+ * Returns whether we found a completion node.
+ */
+private boolean checkRecoveredMethod() {
+	if (currentElement instanceof RecoveredMethod){
+		/* check if current awaiting identifier is the completion identifier */
+		if (this.indexOfAssistIdentifier() < 0) return false;
+
+		/* check if on line with an error already - to avoid completing inside 
+			illegal type names e.g.  int[<cursor> */
+		if (lastErrorEndPosition <= cursorLocation+1
+			&& scanner.searchLineNumber(lastErrorEndPosition) 
+				== scanner.searchLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
+			return false;
+		}		
+ 		RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+		/* only consider if inside method header */
+		if (!recoveredMethod.foundOpeningBrace
+			&& lastIgnoredToken == -1) {
+			//if (rParenPos < lParenPos){ // inside arguments
+			this.assistNode = this.getTypeReference(0);
+			this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+			this.isOrphanCompletionNode = true;
+			return true;
+		}
+	}
+	return false;
+}
+/**
+ * Checks if the completion is in the context of a type and on a type reference in this type.
+ * Persists the identifier into a fake field return type
+ * Returns whether we found a completion node.
+ */
+private boolean checkRecoveredType() {
+	if (currentElement instanceof RecoveredType){
+		/* check if current awaiting identifier is the completion identifier */
+		if (this.indexOfAssistIdentifier() < 0) return false;
+
+		/* check if on line with an error already - to avoid completing inside 
+			illegal type names e.g.  int[<cursor> */
+		if ((lastErrorEndPosition <= cursorLocation+1)
+			&& scanner.searchLineNumber(lastErrorEndPosition) 
+				== scanner.searchLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
+			return false;
+		}
+		RecoveredType recoveredType = (RecoveredType)currentElement;
+		/* filter out cases where scanner is still inside type header */
+		if (recoveredType.foundOpeningBrace) {
+			this.assistNode = this.getTypeReference(0);
+			this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+			this.isOrphanCompletionNode = true;
+			return true;
+		}
+	}
+	return false;
+}
+/* 
+ * Check whether about to shift beyond the completion token.
+ * If so, depending on the context, a special node might need to be created
+ * and attached to the existing recovered structure so as to be remember in the
+ * resulting parsed structure.
+ */
+public void completionIdentifierCheck(){
+
+	if (checkRecoveredType()) return;
+	if (checkRecoveredMethod()) return;
+
+	// if not in a method in non diet mode and if not inside a field initializer, only record references attached to types
+	if (!(this.inMethodStack[this.inMethodPtr] && !this.diet)
+		&& !insideFieldInitializer()) return; 
+
+	/*
+	 	In some cases, the completion identifier may not have yet been consumed,
+	 	e.g.  int.[cursor]
+	 	This is because the grammar does not allow any (empty) identifier to follow
+	 	a base type. We thus have to manually force the identifier to be consumed
+	 	(i.e. pushed).
+	 */
+	if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
+		if (cursorLocation < this.scanner.startPosition && this.scanner.currentPosition == this.scanner.startPosition){ // fake empty identifier got issued
+			this.pushIdentifier();					
+		} else if (cursorLocation+1 >= this.scanner.startPosition && cursorLocation < this.scanner.currentPosition){
+			this.pushIdentifier();
+		}
+	}
+
+	// check for different scenarii
+	try {
+		// no need to go further if we found a non empty completion node
+		// (we still need to store labels though)
+		if (this.assistNode != null) {
+			// however inside an invocation, the completion identifier may already have been consumed into an empty name 
+			// completion, so this check should be before we check that we are at the cursor location
+			if (!isEmptyNameCompletion() || checkInvocation()) return;
+		}
+
+		// no need to check further if we are not at the cursor location
+		if (this.indexOfAssistIdentifier() < 0) return;
+
+		if (checkClassInstanceCreation()) return;
+		if (checkCatchClause()) return;
+		if (checkMemberAccess()) return;
+		if (checkClassLiteralAccess()) return;
+
+		// if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor])
+		// (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
+		if (checkInvocation()) return;
+
+		if (checkNameCompletion()) return;
+	} finally {
+		storeLabelsIfNeeded();
+	}
+}
+protected void consumeCaseLabel() {
+	Expression caseExpression = this.expressionStack[this.expressionPtr];
+	if (caseExpression instanceof SingleNameReference || caseExpression instanceof QualifiedNameReference) {
+		// label counter was wrongly incremented in consumeToken
+		if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
+	}
+	super.consumeCaseLabel();
+}
+protected void consumeConditionalExpression(int op) {
+	Expression valueIfTrue = this.expressionStack[this.expressionPtr - 1];
+	if (valueIfTrue instanceof SingleNameReference || valueIfTrue instanceof QualifiedNameReference) {
+		// label counter was wrongly incremented in consumeToken
+		if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
+	}
+	super.consumeConditionalExpression(op);
+}
+protected void consumeConstructorBody() {
+	super.consumeConstructorBody();
+	this.labelCounterPtr--;
+}
+protected void consumeConstructorHeaderName() {
+
+	int index;
+
+	/* no need to take action if not inside assist identifiers */
+	if ((index = indexOfAssistIdentifier()) < 0) {
+		super.consumeConstructorHeaderName();
+		return;
+	}
+		
+	/* force to start recovering in order to get fake field behavior */
+	if (currentElement == null){
+		this.hasReportedError = true; // do not report any error
+	}
+	this.restartRecovery = true;
+}
+/*
+ * Copy of code from superclass with the following change:
+ * If the cursor location is on the field access, then create a 
+ * CompletionOnMemberAccess instead.
+ */
+protected void consumeFieldAccess(boolean isSuperAccess) {
+	// FieldAccess ::= Primary '.' 'Identifier'
+	// FieldAccess ::= 'super' '.' 'Identifier'
+
+	// potential receiver is being poped, so reset potential receiver
+	this.invocationType = NO_RECEIVER;
+
+	if (this.indexOfAssistIdentifier() < 0) {
+		super.consumeFieldAccess(isSuperAccess);
+	} else {
+		this.pushCompletionOnMemberAccessOnExpressionStack(isSuperAccess);
+	}
+}
+protected void consumeMethodBody() {
+	super.consumeMethodBody();
+	this.labelCounterPtr--;
+}
+protected void consumeNestedMethod() {
+	super.consumeNestedMethod();
+	this.pushNewLabelCounter();
+}
+protected void consumeStatementLabel() {
+	super.consumeStatementLabel();
+	if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
+}
+protected void consumeToken(int token) {
+	int previous = this.previousToken;
+	int previousIdentifierPtr = this.previousIdentifierPtr;
+	super.consumeToken(token);
+
+	// if in field initializer (directly or not), on the completion identifier and not in recovery mode yet
+	// then position end of file at cursor location (so that we have the same behavior as
+	// in method bodies)
+	if (token == TokenNameIdentifier
+			&& this.identifierStack[this.identifierPtr] == assistIdentifier()
+			&& this.currentElement == null
+			&& this.insideFieldInitializer()) {
+		this.scanner.eofPosition = cursorLocation+1;
+	}
+	
+	// if in a method or if in a field initializer 
+	if (this.inMethodStack[this.inMethodPtr] || this.inInitializerStack[this.inInitializerPtr]) {
+		switch (token) {
+			case TokenNameDOT:
+				switch (previous) {
+					case TokenNamethis: // eg. this[.]fred()
+						this.invocationType = EXPLICIT_RECEIVER;
+						break;
+					case TokenNamesuper: // eg. super[.]fred()
+						this.invocationType = SUPER_RECEIVER;
+						break;
+					case TokenNameIdentifier: // eg. bar[.]fred()
+						if (!this.betweenNewAndLeftBraket) { // eg. not new z.y[.]X()
+							if (this.identifierPtr != previousIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred()
+								this.invocationType = EXPLICIT_RECEIVER;
+							} else {
+								this.invocationType = NAME_RECEIVER;
+							}
+						}
+						break;
+				}
+				break;
+			case TokenNameIdentifier:
+				if (previous == TokenNameDOT) { // eg. foo().[fred]()
+					// if current identifier is the empty completion one
+					if (identifierStack[identifierPtr] == CompletionScanner.EmptyCompletionIdentifier){
+						this.completionBehindDot = true;
+					}
+					if (this.invocationType != SUPER_RECEIVER // eg. not super.[fred]()
+						&& this.invocationType != NAME_RECEIVER // eg. not bar.[fred]()
+						&& this.invocationType != ALLOCATION // eg. not new foo.[Bar]()
+						&& this.invocationType != QUALIFIED_ALLOCATION) { // eg. not fred().new foo.[Bar]()
+
+						this.invocationType = EXPLICIT_RECEIVER;
+						this.qualifier = this.expressionPtr;
+					}
+				}
+				break;	
+			case TokenNamenew:
+				this.betweenNewAndLeftBraket = true;
+				this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed
+				if (previous == TokenNameDOT) { // eg. fred().[new] X()
+					this.invocationType = QUALIFIED_ALLOCATION;
+				} else { // eg. [new] X()
+					this.invocationType = ALLOCATION;
+				}
+				break;
+			case TokenNamethis:
+				if (previous == TokenNameDOT) { // eg. fred().[this]()
+					this.invocationType = QUALIFIED_ALLOCATION;
+					this.qualifier = this.expressionPtr;
+				}
+				break;
+			case TokenNamesuper:
+				if (previous == TokenNameDOT) { // eg. fred().[super]()
+					this.invocationType = QUALIFIED_ALLOCATION;
+					this.qualifier = this.expressionPtr;
+				}
+				break;
+			case TokenNamecatch:
+				this.betweenCatchAndRightParen = true;
+				break;
+			case TokenNameLPAREN:
+				this.betweenNewAndLeftBraket = false;
+				if (this.invocationType == NO_RECEIVER || this.invocationType == NAME_RECEIVER) {
+					this.qualifier = this.expressionPtr; // remenber the last expression so that arguments are correctly computed
+				}
+				switch (previous) {
+					case TokenNameIdentifier: // eg. fred[(]) or foo.fred[(])
+						this.pushOnInvocationStacks(this.invocationType, this.qualifier);
+						this.invocationType = NO_RECEIVER;
+						break;
+					case TokenNamethis: // explicit constructor invocation, eg. this[(]1, 2)
+						this.pushOnInvocationStacks(
+							(this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION, 
+							this.qualifier);
+						this.invocationType = NO_RECEIVER;
+						break;
+					case TokenNamesuper: // explicit constructor invocation, eg. super[(]1, 2)
+						this.pushOnInvocationStacks(
+							(this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION, 
+							this.qualifier);
+						this.invocationType = NO_RECEIVER;
+						break;
+				}
+				break;
+			case TokenNameLBRACE:
+				this.betweenNewAndLeftBraket = false;
+				this.pushBlockInvocationPtr();
+				break;
+			case TokenNameLBRACKET:
+				this.betweenNewAndLeftBraket = false;
+				break;
+			case TokenNameRBRACE:
+				if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
+				break;
+			case TokenNameRPAREN:
+				this.betweenCatchAndRightParen = false;
+				break;
+			case TokenNameCOLON:
+				if (previous == TokenNameIdentifier) {
+					if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]++;
+				}
+				break;
+		}
+	}
+}
+/**
+ * Return whether the given ast node contains the completion node.
+ */
+private boolean containsCompletionNode(AstNode ast) {
+	if (this.assistNode == null || ast instanceof Literal) {
+		return false;
+	}
+	if (this.assistNode == ast) {
+		return true;
+	}
+	if (ast instanceof Reference || ast instanceof TypeReference) {
+		return ast == this.assistNode;
+	}
+	if (ast instanceof Assignment) {
+		Assignment assign = (Assignment)ast;
+		return containsCompletionNode(assign.lhs) || containsCompletionNode(assign.expression);
+	}
+	if (ast instanceof UnaryExpression) {
+		UnaryExpression unary = (UnaryExpression)ast;
+		return containsCompletionNode(unary.expression);
+	}
+	if (ast instanceof BinaryExpression) {
+		BinaryExpression binary = (BinaryExpression)ast;
+		return containsCompletionNode(binary.left) || containsCompletionNode(binary.right);
+	}
+	if (ast instanceof InstanceOfExpression) {
+		InstanceOfExpression instanceOfExpr = (InstanceOfExpression)ast;
+		return containsCompletionNode(instanceOfExpr.expression) || containsCompletionNode(instanceOfExpr.type);
+	}
+	if (ast instanceof ConditionalExpression) {
+		ConditionalExpression conditional = (ConditionalExpression)ast;
+		return containsCompletionNode(conditional.condition) || containsCompletionNode(conditional.valueIfTrue) || containsCompletionNode(conditional.valueIfFalse);
+	}
+	if (ast instanceof AllocationExpression) {
+		AllocationExpression alloc = (AllocationExpression)ast;
+		return containsCompletionNode(alloc.type);
+	}
+	if (ast instanceof CastExpression) {
+		CastExpression cast = (CastExpression)ast;
+		return containsCompletionNode(cast.expression) || containsCompletionNode(cast.type);
+	}
+	if (ast instanceof ExplicitConstructorCall) {
+		ExplicitConstructorCall call = (ExplicitConstructorCall)ast;
+		Expression[] arguments = call.arguments;
+		if (arguments != null) {
+			for (int i = 0; i < arguments.length; i++) {
+				if (containsCompletionNode(arguments[i])) {
+					return true;
+				}
+			}
+			return false;
+		}
+	}
+	return false;
+}
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
+	return new CompletionOnImportReference(tokens, positions);
+}
+public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
+	return new CompletionOnPackageReference(tokens, positions);
+}
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
+	return new CompletionOnQualifiedNameReference(
+					previousIdentifiers, 
+					name, 
+					positions); 	
+}
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
+	return this.betweenCatchAndRightParen // check for exception scenario 
+				? new CompletionOnQualifiedExceptionReference(
+					previousIdentifiers,  
+					name, 
+					positions)
+				: new CompletionOnQualifiedTypeReference(
+					previousIdentifiers, 
+					name, 
+					positions); 	
+}
+public NameReference createSingleAssistNameReference(char[] name, long position) {
+	return new CompletionOnSingleNameReference(name, position);
+}
+public TypeReference createSingleAssistTypeReference(char[] name, long position) {
+	return this.betweenCatchAndRightParen // check for exception scenario 
+		? new CompletionOnExceptionReference(name, position) 
+		: new CompletionOnSingleTypeReference(name, position);
+}
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
+
+	this.cursorLocation = cursorLocation;
+	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+	completionScanner.completionIdentifier = null;
+	completionScanner.cursorLocation = cursorLocation;
+	return this.dietParse(sourceUnit, compilationResult);
+}
+/*
+ * Flush parser/scanner state regarding to code assist
+ */
+public void flushAssistState() {
+
+	super.flushAssistState();
+	this.isOrphanCompletionNode = false;
+	this.setAssistIdentifier(null);
+	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+	completionScanner.completedIdentifierStart = 0;
+	completionScanner.completedIdentifierEnd = -1;
+}
+protected NameReference getUnspecifiedReferenceOptimized() {
+	if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
+		// potential receiver is being poped, so reset potential receiver
+		this.invocationType = NO_RECEIVER;
+	}
+	return super.getUnspecifiedReferenceOptimized();
+}
+
+public void initialize() {
+	super.initialize();
+	this.initializeForBlockStatements();
+	this.labelCounterPtr = -1;
+}
+/*
+ * Initializes the state of the parser that is about to go for BlockStatements.
+ */
+private void initializeForBlockStatements() {
+	this.previousToken = -1;
+	this.previousIdentifierPtr = -1;
+	this.completionBehindDot = false;
+	this.betweenNewAndLeftBraket = false;
+	this.betweenCatchAndRightParen = false;
+	this.invocationType = NO_RECEIVER;
+	this.qualifier = -1;
+	this.blockInvocationPtr = -1;
+}
+public void initializeScanner(){
+	this.scanner = new CompletionScanner();
+}
+/**
+ * Returns whether we are directly or indirectly inside a field initializer.
+ */
+private boolean insideFieldInitializer() {
+	for (int i = this.inInitializerPtr; i >= 0; i--) {
+		if (this.inInitializerStack[i]) {
+			return true;
+		}
+	}
+	return false;
+}
+/**
+ * Returns whether the completion is just after an array type
+ * eg. String[].[cursor]
+ */
+private boolean isAfterArrayType() {
+	// TBD: The following relies on the fact that array dimensions are small: it says that if the
+	//      top of the intStack is less than 11, then it must be a dimension 
+	//      (smallest position of array type in a compilation unit is 11 as in "class X{Y[]")
+	int dim = 0;
+	if ((this.intPtr > -1) && (this.intStack[this.intPtr] < 11)) {
+		return true;
+	}
+	return false;
+}
+private boolean isEmptyNameCompletion() {
+	return
+		this.assistNode != null && 
+		this.assistNode instanceof CompletionOnSingleNameReference &&
+		(((CompletionOnSingleNameReference)this.assistNode).token.length == 0);
+}
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
+
+	this.cursorLocation = cursorLocation;
+	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+	completionScanner.completionIdentifier = null;
+	completionScanner.cursorLocation = cursorLocation;
+	return this.parse(sourceUnit, compilationResult);
+}
+/*
+ * Prepares the state of the parser to go for BlockStatements.
+ */
+protected void prepareForBlockStatements() {
+	super.prepareForBlockStatements();
+	this.initializeForBlockStatements();
+}
+protected void pushBlockInvocationPtr() {
+	try {
+		this.blockInvocationStack[++this.blockInvocationPtr] = this.invocationPtr+1;
+	} catch (IndexOutOfBoundsException e) {
+		int oldStackLength = this.blockInvocationStack.length;
+		int[] oldStack = this.labelCounterStack;
+		this.blockInvocationStack = new int[oldStackLength + StackIncrement];
+		System.arraycopy(oldStack, 0, this.blockInvocationStack, 0, oldStackLength);
+		this.blockInvocationStack[this.blockInvocationPtr] = this.invocationPtr+1;
+	}
+}
+/**
+ * Creates a completion on member access node and push it
+ * on the expression stack.
+ */
+private void pushCompletionOnMemberAccessOnExpressionStack(boolean isSuperAccess) {
+	char[] source = identifierStack[identifierPtr];
+	long pos = identifierPositionStack[identifierPtr--];
+	CompletionOnMemberAccess fr = new CompletionOnMemberAccess(source, pos);
+	this.assistNode = fr;
+	this.lastCheckPoint = fr.sourceEnd + 1;
+	identifierLengthPtr--;
+	if (isSuperAccess) { //considerates the fieldReference beginning at the 'super' ....	
+		fr.sourceStart = intStack[intPtr--];
+		fr.receiver = new SuperReference(fr.sourceStart, endPosition);
+		pushOnExpressionStack(fr);
+	} else { //optimize push/pop
+		if ((fr.receiver = expressionStack[expressionPtr]).isThis()) { //fieldreference begins at the this
+			fr.sourceStart = fr.receiver.sourceStart;
+		}
+		expressionStack[expressionPtr] = fr;
+	}
+}
+protected void pushNewLabelCounter() {
+	try {
+		this.labelCounterStack[++this.labelCounterPtr] = 0;
+	} catch (IndexOutOfBoundsException e) {
+		int oldStackLength = this.labelCounterStack.length;
+		int[] oldStack = this.labelCounterStack;
+		this.labelCounterStack = new int[oldStackLength + StackIncrement];
+		System.arraycopy(oldStack, 0, this.labelCounterStack, 0, oldStackLength);
+		this.labelCounterStack[this.labelCounterPtr] = 0;
+	}
+}
+/**
+ * Pushes the given invocation type (one of the invocation type constants) on the invocation type stack,
+ * and the given qualifier (an expression pointer to the expression stack) on the qualifier stack.
+ */
+protected void pushOnInvocationStacks(int invocationType, int qualifierExprPtr) {
+	// NB: invocationPtr has already been incremented by a call to pushOnSelectorStack()
+	try {
+		this.invocationTypeStack[this.invocationPtr] = invocationType;
+		this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
+	} catch (IndexOutOfBoundsException e) {
+		int oldStackLength = this.invocationTypeStack.length;
+		int oldInvocationTypeStack[] = this.invocationTypeStack;
+		int oldQualifierStack[] = this.qualifierStack;
+		this.invocationTypeStack = new int[oldStackLength + StackIncrement];
+		this.qualifierStack = new int[oldStackLength + StackIncrement];
+		System.arraycopy(oldInvocationTypeStack, 0, this.invocationTypeStack, 0, oldStackLength);
+		System.arraycopy(oldQualifierStack, 0, this.qualifierStack, 0, oldStackLength);
+		this.invocationTypeStack[this.invocationPtr] = invocationType;
+		this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
+	}
+}
+public void recordCompletionOnReference(){
+
+	if (currentElement instanceof RecoveredType){
+		RecoveredType recoveredType = (RecoveredType)currentElement;
+
+		/* filter out cases where scanner is still inside type header */
+		if (!recoveredType.foundOpeningBrace) return;
+		
+		/* generate a pseudo field with a completion on type reference */	
+		currentElement.add(
+			new CompletionOnFieldType(this.getTypeReference(0)), 0);
+		return;
+	}
+	if (!diet) return; // only record references attached to types
+
+}
+protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
+
+	/* Intercept error state on EOF inside method bodies, due to 
+	   cursor location being used as an EOF position.
+	*/
+	if (!diet && currentToken == TokenNameEOF) return;
+	super.reportSyntaxError(act, currentKind, stateStackTop);
+}
+/*
+ * Reset internal state after completion is over
+ */
+ 
+public void reset() {
+	super.reset();
+	this.cursorLocation = 0;
+}
+/*
+ * Reset internal state after completion is over
+ */
+ 
+public void resetAfterCompletion() {
+	this.cursorLocation = 0;
+	this.flushAssistState();
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+
+	if (this.assistNode != null) {
+		// if an assist node has been found and a recovered element exists,
+		// mark enclosing blocks as to be preserved
+		if (this.currentElement != null) {
+			currentElement.preserveEnclosingBlocks();
+		}
+		/* if reached [eof] inside method body, but still inside nested type,
+			or inside a field initializer, should continue in diet mode until 
+			the end of the method body or compilation unit */
+		if ((scanner.eofPosition == cursorLocation+1)
+			&& (!(referenceContext instanceof CompilationUnitDeclaration) 
+				|| insideFieldInitializer())) {
+
+			/*	disabled since does not handle possible field/message refs, i.e. Obj[ASSIST HERE]ect.registerNatives()		    
+			// consume extra tokens which were part of the qualified reference
+			//   so that the replaced source comprises them as well 
+			if (this.assistNode instanceof NameReference){
+				int oldEof = scanner.eofPosition;
+				scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
+				scanner.currentPosition = this.cursorLocation+1;
+				int token = -1;
+				try {
+					do {
+						// first token might not have to be a dot
+						if (token >= 0 || !this.completionBehindDot){
+							if ((token = scanner.getNextToken()) != TokenNameDOT) break;
+						}
+						if ((token = scanner.getNextToken()) != TokenNameIdentifier) break;
+						this.assistNode.sourceEnd = scanner.currentPosition - 1;
+					} while (token != TokenNameEOF);
+				} catch (InvalidInputException e){
+				} finally {
+					scanner.eofPosition = oldEof;
+				}
+			}
+			*/			
+			/* restart in diet mode for finding sibling constructs */
+			if (currentElement.enclosingType() != null){
+				lastCheckPoint = this.assistNode.sourceEnd+1;
+				scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
+			} else {
+				this.resetStacks();
+				return false;	
+			}
+		}
+	}
+	return super.resumeAfterRecovery();
+}
+public void setAssistIdentifier(char[] assistIdent){
+	((CompletionScanner)scanner).completionIdentifier = assistIdent;
+}
+/**
+ * Stores the labels left on the identifier stack if they have not been stored yet.
+ */
+private void storeLabelsIfNeeded() {
+	int counter = this.labelCounterPtr >= 0 ? this.labelCounterStack[this.labelCounterPtr] : 0;
+	if (this.labels == null && this.identifierPtr >= 0) {
+		this.labels = new char[counter][];
+		System.arraycopy(this.identifierStack, this.identifierPtr - counter + 1, this.labels, 0, counter);
+	}
+	this.identifierPtr -= counter;
+	this.identifierLengthPtr -= counter; // labels have not been concatenated yet
+}
+/*
+ * Update recovery state based on current parser/scanner state
+ */
+protected void updateRecoveryState() {
+
+	/* expose parser state to recovery state */
+	currentElement.updateFromParserState();
+
+	/* may be able to retrieve completionNode as an orphan, and then attach it */
+	this.completionIdentifierCheck();
+	this.attachOrphanCompletionNode();
+	
+	/* check and update recovered state based on current token,
+		this action is also performed when shifting token after recovery
+		got activated once. 
+	*/
+	this.recoveryTokenCheck();
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java
index 543d318..72c987d 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/InvalidCursorLocation.java
@@ -1,25 +1,24 @@
-package org.eclipse.jdt.internal.codeassist.complete;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.codeassist.impl.Engine;
-
-/**
- * Thrown whenever cursor location is not inside a consistent token
- * i.e. inside a string, number, unicode, comments etc...
- */
-public class InvalidCursorLocation extends RuntimeException {
-
-	public String irritant;
-
-	/* Possible irritants */
-	public static final String NO_COMPLETION_INSIDE_UNICODE = "No Completion Inside Unicode"/*nonNLS*/;
-	public static final String NO_COMPLETION_INSIDE_COMMENT = "No Completion Inside Comment"/*nonNLS*/;     
-	public static final String NO_COMPLETION_INSIDE_STRING = "No Completion Inside String"/*nonNLS*/;       
-	public static final String NO_COMPLETION_INSIDE_NUMBER = "No Completion Inside Number"/*nonNLS*/;       
-    
-public InvalidCursorLocation(String irritant){
-	this.irritant = irritant;
-}
-}
+package org.eclipse.jdt.internal.codeassist.complete;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/**
+ * Thrown whenever cursor location is not inside a consistent token
+ * i.e. inside a string, number, unicode, comments etc...
+ */
+public class InvalidCursorLocation extends RuntimeException {
+
+	public String irritant;
+
+	/* Possible irritants */
+	public static final String NO_COMPLETION_INSIDE_UNICODE = "No Completion Inside Unicode"/*nonNLS*/;
+	public static final String NO_COMPLETION_INSIDE_COMMENT = "No Completion Inside Comment"/*nonNLS*/;     
+	public static final String NO_COMPLETION_INSIDE_STRING = "No Completion Inside String"/*nonNLS*/;       
+	public static final String NO_COMPLETION_INSIDE_NUMBER = "No Completion Inside Number"/*nonNLS*/;       
+    
+public InvalidCursorLocation(String irritant){
+	this.irritant = irritant;
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java
index 6a98923..fbf2169 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionNodeFound.java
@@ -1,21 +1,17 @@
-package org.eclipse.jdt.internal.codeassist.select;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class SelectionNodeFound extends RuntimeException {
-	public Binding binding;
-public SelectionNodeFound() {
-	this(null); // we found a problem in the selection node
-}
-public SelectionNodeFound(Binding binding) {
-	this.binding = binding;
-}
-}
+package org.eclipse.jdt.internal.codeassist.select;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SelectionNodeFound extends RuntimeException {
+	public Binding binding;
+public SelectionNodeFound() {
+	this(null); // we found a problem in the selection node
+}
+public SelectionNodeFound(Binding binding) {
+	this.binding = binding;
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
index d4c9138..3ebc0f3 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
@@ -1,53 +1,52 @@
-package org.eclipse.jdt.internal.codeassist.select;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * Selection node build by the parser in any case it was intending to
- * reduce a qualified super reference containing the assist identifier.
- * e.g.
- *
- *	class X extends Z {
- *    class Y {
- *    	void foo() {
- *      	X.[start]super[end].bar();
- *      }
- *    }
- *  }
- *
- *	---> class X {
- *		   class Y {
- *           void foo() {
- *             <SelectOnQualifiedSuper:X.super>
- *           }
- *         }
- *       }
- *
- */
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.util.CharOperation;
-
-public class SelectionOnQualifiedSuperReference extends QualifiedSuperReference {
-public SelectionOnQualifiedSuperReference(TypeReference name, int pos, int sourceEnd) {
-	super(name, pos, sourceEnd);
-}
-public TypeBinding resolveType(BlockScope scope) {
-	TypeBinding binding = super.resolveType(scope);
-
-	if (binding == null || !binding.isValidBinding())
-		throw new SelectionNodeFound();
-	else
-		throw new SelectionNodeFound(binding);
-}
-public String toStringExpression(){
-	
-	StringBuffer buffer = new StringBuffer("<SelectOnQualifiedSuper:"/*nonNLS*/);
-	buffer.append(super.toStringExpression());
-	buffer.append(">"/*nonNLS*/);
-	return buffer.toString();
-}
-}
+package org.eclipse.jdt.internal.codeassist.select;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a qualified super reference containing the assist identifier.
+ * e.g.
+ *
+ *	class X extends Z {
+ *    class Y {
+ *    	void foo() {
+ *      	X.[start]super[end].bar();
+ *      }
+ *    }
+ *  }
+ *
+ *	---> class X {
+ *		   class Y {
+ *           void foo() {
+ *             <SelectOnQualifiedSuper:X.super>
+ *           }
+ *         }
+ *       }
+ *
+ */
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SelectionOnQualifiedSuperReference extends QualifiedSuperReference {
+public SelectionOnQualifiedSuperReference(TypeReference name, int pos, int sourceEnd) {
+	super(name, pos, sourceEnd);
+}
+public TypeBinding resolveType(BlockScope scope) {
+	TypeBinding binding = super.resolveType(scope);
+
+	if (binding == null || !binding.isValidBinding())
+		throw new SelectionNodeFound();
+	else
+		throw new SelectionNodeFound(binding);
+}
+public String toStringExpression(){
+	
+	StringBuffer buffer = new StringBuffer("<SelectOnQualifiedSuper:"/*nonNLS*/);
+	buffer.append(super.toStringExpression());
+	buffer.append(">"/*nonNLS*/);
+	return buffer.toString();
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java
index ea6450a..d6dd52c 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java
@@ -1,52 +1,51 @@
-package org.eclipse.jdt.internal.codeassist.select;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * Selection node build by the parser in any case it was intending to
- * reduce a super reference containing the assist identifier.
- * e.g.
- *
- *	class X extends Z {
- *    class Y {
- *    	void foo() {
- *      	[start]super[end].bar();
- *      }
- *    }
- *  }
- *
- *	---> class X {
- *		   class Y {
- *           void foo() {
- *             <SelectOnQualifiedSuper:super>
- *           }
- *         }
- *       }
- *
- */
-
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.util.CharOperation;
-
-public class SelectionOnSuperReference extends SuperReference {
-
-public SelectionOnSuperReference(int pos, int sourceEnd) {
-	super(pos, sourceEnd);
-}
-public TypeBinding resolveType(BlockScope scope) {
-	TypeBinding binding = super.resolveType(scope);
-
-	if (binding == null || !binding.isValidBinding())
-		throw new SelectionNodeFound();
-	else
-		throw new SelectionNodeFound(binding);
-}
-public String toStringExpression(){
-
-	return "<SelectOnSuper:"/*nonNLS*/+super.toStringExpression()+">"/*nonNLS*/;
-	
-}
-}
+package org.eclipse.jdt.internal.codeassist.select;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a super reference containing the assist identifier.
+ * e.g.
+ *
+ *	class X extends Z {
+ *    class Y {
+ *    	void foo() {
+ *      	[start]super[end].bar();
+ *      }
+ *    }
+ *  }
+ *
+ *	---> class X {
+ *		   class Y {
+ *           void foo() {
+ *             <SelectOnQualifiedSuper:super>
+ *           }
+ *         }
+ *       }
+ *
+ */
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SelectionOnSuperReference extends SuperReference {
+
+public SelectionOnSuperReference(int pos, int sourceEnd) {
+	super(pos, sourceEnd);
+}
+public TypeBinding resolveType(BlockScope scope) {
+	TypeBinding binding = super.resolveType(scope);
+
+	if (binding == null || !binding.isValidBinding())
+		throw new SelectionNodeFound();
+	else
+		throw new SelectionNodeFound(binding);
+}
+public String toStringExpression(){
+
+	return "<SelectOnSuper:"/*nonNLS*/+super.toStringExpression()+">"/*nonNLS*/;
+	
+}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index 2752e8d..6224b2c 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -1,497 +1,496 @@
-package org.eclipse.jdt.internal.codeassist.select;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * Parser able to build specific completion parse nodes, given a cursorLocation.
- *
- * Cursor location denotes the position of the last character behind which completion
- * got requested:
- *  -1 means completion at the very beginning of the source
- *	0  means completion behind the first character
- *  n  means completion behind the n-th character
- */
- 
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.codeassist.impl.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.CharOperation;
-
-public class SelectionParser extends AssistParser {
-
-	/* public fields */
-
-	public int selectionStart, selectionEnd;
-	public AstNode selectionNode;
-
-	public static final char[] SUPER = "super"/*nonNLS*/.toCharArray();
-public SelectionParser(ProblemReporter problemReporter) {
-	super(problemReporter);
-}
-public char[] assistIdentifier(){
-	return ((SelectionScanner)scanner).selectionIdentifier;
-}
-protected void attachOrphanCompletionNode(){
-	if (isOrphanCompletionNode){
-		isOrphanCompletionNode = false;
-		Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(this.assistNode);
-		currentElement = currentElement.add(statement, 0);
-		currentToken = 0; // given we are not on an eof, we do not want side effects caused by looked-ahead token
-	}
-}
-protected void classInstanceCreation(boolean alwaysQualified) {
-	// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
-
-	// ClassBodyopt produces a null item on the astStak if it produces NO class body
-	// An empty class body produces a 0 on the length stack.....
-
-	if (this.indexOfAssistIdentifier() < 0) {
-		super.classInstanceCreation(alwaysQualified);
-		return;
-	} 
-	QualifiedAllocationExpression alloc;
-	int length;
-	if (((length = astLengthStack[astLengthPtr--]) == 1)
-		&& (astStack[astPtr] == null)) {
-		//NO ClassBody
-		astPtr--;
-		alloc = new SelectionOnQualifiedAllocationExpression();
-		alloc.sourceEnd = endPosition; //the position has been stored explicitly
-
-		if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
-			expressionPtr -= length;
-			System.arraycopy(
-				expressionStack, 
-				expressionPtr + 1, 
-				alloc.arguments = new Expression[length], 
-				0, 
-				length); 
-		}
-		// trick to avoid creating a selection on type reference
-		char [] oldIdent = this.assistIdentifier();
-		this.setAssistIdentifier(null);			
-		alloc.type = getTypeReference(0);
-		this.setAssistIdentifier(oldIdent);
-		
-		//the default constructor with the correct number of argument
-		//will be created and added by the TC (see createsInternalConstructorWithBinding)
-		alloc.sourceStart = intStack[intPtr--];
-		pushOnExpressionStack(alloc);
-
-		this.assistNode = alloc;
-		this.lastCheckPoint = alloc.sourceEnd + 1;
-		restartRecovery = true; // force to restart into recovery mode
-		isOrphanCompletionNode = true;				
-	}
-}
-protected void consumeArrayCreationExpression() {
-	// ArrayCreationExpression ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializeropt
-	// ArrayCreationExpression ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializeropt
-
-	super.consumeArrayCreationExpression();
-
-	ArrayAllocationExpression alloc = (ArrayAllocationExpression)expressionStack[expressionPtr];
-	if (alloc.type == assistNode){
-		restartRecovery = true;
-		isOrphanCompletionNode = true; 
-	}
-}
-protected void consumeEnterAnonymousClassBody() {
-	// EnterAnonymousClassBody ::= $empty
-
-	if (this.indexOfAssistIdentifier() < 0) {
-		super.consumeEnterAnonymousClassBody();
-		return;
-	}
-	QualifiedAllocationExpression alloc;
-	AnonymousLocalTypeDeclaration anonymousType = 
-		new AnonymousLocalTypeDeclaration(); 
-	alloc = 
-		anonymousType.allocation = new SelectionOnQualifiedAllocationExpression(anonymousType); 
-	pushOnAstStack(anonymousType);
-
-	alloc.sourceEnd = rParenPos; //the position has been stored explicitly
-	int argumentLength;
-	if ((argumentLength = expressionLengthStack[expressionLengthPtr--]) != 0) {
-		expressionPtr -= argumentLength;
-		System.arraycopy(
-			expressionStack, 
-			expressionPtr + 1, 
-			alloc.arguments = new Expression[argumentLength], 
-			0, 
-			argumentLength); 
-	}
-	// trick to avoid creating a selection on type reference
-	char [] oldIdent = this.assistIdentifier();
-	this.setAssistIdentifier(null);			
-	alloc.type = getTypeReference(0);
-	this.setAssistIdentifier(oldIdent);		
-
-	anonymousType.sourceEnd = alloc.sourceEnd;
-	//position at the type while it impacts the anonymous declaration
-	anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
-	alloc.sourceStart = intStack[intPtr--];
-	pushOnExpressionStack(alloc);
-
-	assistNode = alloc;
-	this.lastCheckPoint = alloc.sourceEnd + 1;
-	restartRecovery = true; // force to restart into recovery mode
-	isOrphanCompletionNode = true;	
-		
-	anonymousType.bodyStart = scanner.currentPosition;	
-	listLength = 0; // will be updated when reading super-interfaces
-	// recovery
-	if (currentElement != null){ 
-		lastCheckPoint = anonymousType.bodyStart;
-		currentElement = currentElement.add(anonymousType, 0); // the recoveryTokenCheck will deal with the open brace
-		lastIgnoredToken = -1;		
-	}
-}
-protected void consumeEnterVariable() {
-	// EnterVariable ::= $empty
-	// do nothing by default
-
-	super.consumeEnterVariable();
-
-	AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
-	if (variable.type == assistNode){
-		restartRecovery = true;
-		isOrphanCompletionNode = false; // already attached inside variable decl
-	}
-}
-protected void consumeFieldAccess(boolean isSuperAccess) {
-	// FieldAccess ::= Primary '.' 'Identifier'
-	// FieldAccess ::= 'super' '.' 'Identifier'
-
-	if (this.indexOfAssistIdentifier() < 0) {
-		super.consumeFieldAccess(isSuperAccess);
-		return;
-	} 
-	FieldReference fieldReference = 
-		new SelectionOnFieldReference(
-			identifierStack[identifierPtr], 
-			identifierPositionStack[identifierPtr--]);
-	identifierLengthPtr--;
-	if (isSuperAccess) { //considerates the fieldReferenceerence beginning at the 'super' ....	
-		fieldReference.sourceStart = intStack[intPtr--];
-		fieldReference.receiver = new SuperReference(fieldReference.sourceStart, endPosition);
-		pushOnExpressionStack(fieldReference);
-	} else { //optimize push/pop
-		if ((fieldReference.receiver = expressionStack[expressionPtr]).isThis()) { //fieldReferenceerence begins at the this
-			fieldReference.sourceStart = fieldReference.receiver.sourceStart;
-		}
-		expressionStack[expressionPtr] = fieldReference;
-	}
-	assistNode = fieldReference;
-	this.lastCheckPoint = fieldReference.sourceEnd + 1;
-	restartRecovery	= true;	// force to restart in recovery mode
-	isOrphanCompletionNode = true;		
-}
-protected void consumeMethodInvocationName() {
-	// MethodInvocation ::= Name '(' ArgumentListopt ')'
-
-	// when the name is only an identifier...we have a message send to "this" (implicit)
-
-	char[] selector = identifierStack[identifierPtr];
-	if (!(selector == this.assistIdentifier() && CharOperation.equals(selector, SUPER))){
-		super.consumeMethodInvocationName();
-		return;
-	}	
-	ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(ExplicitConstructorCall.Super);
-	constructorCall.sourceEnd = rParenPos;
-	constructorCall.sourceStart = (int) (identifierPositionStack[identifierPtr] >>> 32);
-	int length;
-	if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
-		expressionPtr -= length;
-		System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
-	}
-
-	pushOnAstStack(constructorCall);
-	this.assistNode = constructorCall;	
-	this.lastCheckPoint = constructorCall.sourceEnd + 1;
-	restartRecovery	= true;	// force to restart in recovery mode
-	isOrphanCompletionNode = true;	
-}
-protected void consumeMethodInvocationPrimary() {
-	//optimize the push/pop
-	//MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
-
-	char[] selector = identifierStack[identifierPtr];
-	if (!(selector == this.assistIdentifier() && CharOperation.equals(selector, SUPER))){
-		super.consumeMethodInvocationPrimary();
-		return;
-	}
-	ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(ExplicitConstructorCall.Super);
-	constructorCall.sourceEnd = rParenPos;
-	int length;
-	if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
-		expressionPtr -= length;
-		System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
-	}
-	constructorCall.qualification = expressionStack[expressionPtr--];
-	constructorCall.sourceStart = constructorCall.qualification.sourceStart;
-	
-	pushOnAstStack(constructorCall);
-	this.assistNode = constructorCall;
-	this.lastCheckPoint = constructorCall.sourceEnd + 1;
-	restartRecovery	= true;	// force to restart in recovery mode
-	isOrphanCompletionNode = true;	
-}
-protected void consumeTypeImportOnDemandDeclarationName() {
-	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
-	/* push an ImportRef build from the last name 
-	stored in the identifier stack. */
-
-	int index;
-
-	/* no need to take action if not inside assist identifiers */
-	if ((index = indexOfAssistIdentifier()) < 0) {
-		super.consumeTypeImportOnDemandDeclarationName();
-		return;
-	}
-	/* retrieve identifiers subset and whole positions, the assist node positions
-		should include the entire replaced source. */
-	int length = identifierLengthStack[identifierLengthPtr];
-	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
-	identifierLengthPtr--;
-	identifierPtr -= length;
-	long[] positions = new long[length];
-	System.arraycopy(
-		identifierPositionStack, 
-		identifierPtr + 1, 
-		positions, 
-		0, 
-		length); 
-
-	/* build specific assist node on import statement */
-	ImportReference reference = this.createAssistImportReference(subset, positions);
-	reference.onDemand = true;
-	assistNode = reference;
-	this.lastCheckPoint = reference.sourceEnd + 1;
-	
-	pushOnAstStack(reference);
-
-	if (currentToken == TokenNameSEMICOLON){
-		reference.declarationSourceEnd = scanner.currentPosition - 1;
-	} else {
-		reference.declarationSourceEnd = (int) positions[length-1];
-	}
-	//endPosition is just before the ;
-	reference.declarationSourceStart = intStack[intPtr--];
-	// flush annotations defined prior to import statements
-	reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
-
-	// recovery
-	if (currentElement != null){
-		lastCheckPoint = reference.declarationSourceEnd+1;
-		currentElement = currentElement.add(reference, 0);
-		lastIgnoredToken = -1;
-		restartRecovery = true; // used to avoid branching back into the regular automaton		
-	}
-}
-public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
-	return new SelectionOnImportReference(tokens, positions);
-}
-public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
-	return new SelectionOnPackageReference(tokens, positions);
-}
-public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
-	return new SelectionOnQualifiedNameReference(
-					previousIdentifiers, 
-					name, 
-					positions); 	
-}
-public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
-	return new SelectionOnQualifiedTypeReference(
-					previousIdentifiers, 
-					name, 
-					positions); 	
-}
-public NameReference createSingleAssistNameReference(char[] name, long position) {
-	return new SelectionOnSingleNameReference(name, position);
-}
-public TypeReference createSingleAssistTypeReference(char[] name, long position) {
-	return new SelectionOnSingleTypeReference(name, position);
-}
-public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
-
-	this.selectionStart = selectionStart;
-	this.selectionEnd = selectionEnd;	
-	SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
-	selectionScanner.selectionIdentifier = null;
-	selectionScanner.selectionStart = selectionStart;
-	selectionScanner.selectionEnd = selectionEnd;	
-	return this.dietParse(sourceUnit, compilationResult);
-}
-/*
- * Flush parser/scanner state regarding to code assist
- */
-public void flushAssistState() {
-
-	super.flushAssistState();
-	this.selectionNode = null;
-	this.setAssistIdentifier(null);
-}
-protected NameReference getUnspecifiedReference() {
-	/* build a (unspecified) NameReference which may be qualified*/
-
-	int completionIndex;
-
-	/* no need to take action if not inside completed identifiers */
-	if ((completionIndex = indexOfAssistIdentifier()) < 0) {
-		return super.getUnspecifiedReference();
-	}
-
-	int length = identifierLengthStack[identifierLengthPtr];
-	if (CharOperation.equals(assistIdentifier(), SUPER)){
-		Reference reference;
-		if (completionIndex > 0){ // qualified super
-			// discard 'super' from identifier stacks
-			identifierLengthStack[identifierLengthPtr] = completionIndex;
-			int ptr = identifierPtr -= (length - completionIndex);
-			reference = 
-				new SelectionOnQualifiedSuperReference(
-					getTypeReference(0), 
-					(int)(identifierPositionStack[ptr+1] >>> 32),
-					(int) identifierPositionStack[ptr+1]);
-		} else { // standard super
-			identifierPtr -= length;
-			identifierLengthPtr--;
-			reference = new SelectionOnSuperReference((int)(identifierPositionStack[identifierPtr+1] >>> 32), (int) identifierPositionStack[identifierPtr+1]);
-		}
-		pushOnAstStack(reference);
-		this.assistNode = reference;	
-		this.lastCheckPoint = reference.sourceEnd + 1;
-		restartRecovery	= true;	// force to restart in recovery mode
-		isOrphanCompletionNode = true;	
-		return new SingleNameReference(new char[0], 0); // dummy reference
-	}
-	NameReference nameReference;
-	/* retrieve identifiers subset and whole positions, the completion node positions
-		should include the entire replaced source. */
-	char[][] subset = identifierSubSet(completionIndex);
-	identifierLengthPtr--;
-	identifierPtr -= length;
-	long[] positions = new long[length];
-	System.arraycopy(
-		identifierPositionStack, 
-		identifierPtr + 1, 
-		positions, 
-		0, 
-		length);
-	/* build specific completion on name reference */
-	if (completionIndex == 0) {
-		/* completion inside first identifier */
-		nameReference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
-	} else {
-		/* completion inside subsequent identifier */
-		nameReference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
-	}
-	assistNode = nameReference;
-	this.lastCheckPoint = nameReference.sourceEnd + 1;
-	isOrphanCompletionNode = true;
-	restartRecovery = true; // force to restart into recovery mode
-	return nameReference;
-}
-/*
- * Copy of code from superclass with the following change:
- * In the case of qualified name reference if the cursor location is on the 
- * qualified name reference, then create a CompletionOnQualifiedNameReference 
- * instead.
- */
-protected NameReference getUnspecifiedReferenceOptimized() {
-
-	int index = indexOfAssistIdentifier();
-	NameReference reference = super.getUnspecifiedReferenceOptimized();
-
-	if (index >= 0){
-		restartRecovery = true; // force to stop and restart in recovery mode
-		isOrphanCompletionNode = true;		
-	}
-	return reference;
-}
-public void initializeScanner(){
-	this.scanner = new SelectionScanner();
-}
-protected MessageSend newMessageSend() {
-	// '(' ArgumentListopt ')'
-	// the arguments are on the expression stack
-
-	char[] selector = identifierStack[identifierPtr];
-	if (selector != this.assistIdentifier()){
-		return super.newMessageSend();
-	}	
-	MessageSend messageSend = new SelectionOnMessageSend();
-	int length;
-	if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
-		expressionPtr -= length;
-		System.arraycopy(
-			expressionStack, 
-			expressionPtr + 1, 
-			messageSend.arguments = new Expression[length], 
-			0, 
-			length); 
-	};
-	assistNode = messageSend;
-	restartRecovery	= true;	// force to restart in recovery mode
-	isOrphanCompletionNode = true;	
-	return messageSend;
-}
-public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
-
-	this.selectionStart = selectionStart;
-	this.selectionEnd = selectionEnd;	
-	SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
-	selectionScanner.selectionIdentifier = null;
-	selectionScanner.selectionStart = selectionStart;
-	selectionScanner.selectionEnd = selectionEnd;	
-	return this.parse(sourceUnit, compilationResult);
-}
-/*
- * Reset context so as to resume to regular parse loop
- * If unable to reset for resuming, answers false.
- *
- * Move checkpoint location, reset internal stacks and
- * decide which grammar goal is activated.
- */
-protected boolean resumeAfterRecovery() {
-
-	/* if reached assist node inside method body, but still inside nested type,
-		should continue in diet mode until the end of the method body */
-	if (this.assistNode != null
-		&& !(referenceContext instanceof CompilationUnitDeclaration)){
-		currentElement.preserveEnclosingBlocks();
-		if (currentElement.enclosingType() == null){
-			this.resetStacks();
-			return false;
-		}
-	}
-	return super.resumeAfterRecovery();			
-}
-public void setAssistIdentifier(char[] assistIdent){
-	((SelectionScanner)scanner).selectionIdentifier = assistIdent;
-}
-/*
- * Update recovery state based on current parser/scanner state
- */
-protected void updateRecoveryState() {
-
-	/* expose parser state to recovery state */
-	currentElement.updateFromParserState();
-
-	/* may be able to retrieve completionNode as an orphan, and then attach it */
-	this.attachOrphanCompletionNode();
-	
-	/* check and update recovered state based on current token,
-		this action is also performed when shifting token after recovery
-		got activated once. 
-	*/
-	this.recoveryTokenCheck();
-}
-}
+package org.eclipse.jdt.internal.codeassist.select;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * Parser able to build specific completion parse nodes, given a cursorLocation.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ *  -1 means completion at the very beginning of the source
+ *	0  means completion behind the first character
+ *  n  means completion behind the n-th character
+ */
+ 
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.codeassist.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.CharOperation;
+
+public class SelectionParser extends AssistParser {
+
+	/* public fields */
+
+	public int selectionStart, selectionEnd;
+	public AstNode selectionNode;
+
+	public static final char[] SUPER = "super"/*nonNLS*/.toCharArray();
+public SelectionParser(ProblemReporter problemReporter) {
+	super(problemReporter);
+}
+public char[] assistIdentifier(){
+	return ((SelectionScanner)scanner).selectionIdentifier;
+}
+protected void attachOrphanCompletionNode(){
+	if (isOrphanCompletionNode){
+		isOrphanCompletionNode = false;
+		Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(this.assistNode);
+		currentElement = currentElement.add(statement, 0);
+		currentToken = 0; // given we are not on an eof, we do not want side effects caused by looked-ahead token
+	}
+}
+protected void classInstanceCreation(boolean alwaysQualified) {
+	// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
+
+	// ClassBodyopt produces a null item on the astStak if it produces NO class body
+	// An empty class body produces a 0 on the length stack.....
+
+	if (this.indexOfAssistIdentifier() < 0) {
+		super.classInstanceCreation(alwaysQualified);
+		return;
+	} 
+	QualifiedAllocationExpression alloc;
+	int length;
+	if (((length = astLengthStack[astLengthPtr--]) == 1)
+		&& (astStack[astPtr] == null)) {
+		//NO ClassBody
+		astPtr--;
+		alloc = new SelectionOnQualifiedAllocationExpression();
+		alloc.sourceEnd = endPosition; //the position has been stored explicitly
+
+		if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+			expressionPtr -= length;
+			System.arraycopy(
+				expressionStack, 
+				expressionPtr + 1, 
+				alloc.arguments = new Expression[length], 
+				0, 
+				length); 
+		}
+		// trick to avoid creating a selection on type reference
+		char [] oldIdent = this.assistIdentifier();
+		this.setAssistIdentifier(null);			
+		alloc.type = getTypeReference(0);
+		this.setAssistIdentifier(oldIdent);
+		
+		//the default constructor with the correct number of argument
+		//will be created and added by the TC (see createsInternalConstructorWithBinding)
+		alloc.sourceStart = intStack[intPtr--];
+		pushOnExpressionStack(alloc);
+
+		this.assistNode = alloc;
+		this.lastCheckPoint = alloc.sourceEnd + 1;
+		restartRecovery = true; // force to restart into recovery mode
+		isOrphanCompletionNode = true;				
+	}
+}
+protected void consumeArrayCreationExpression() {
+	// ArrayCreationExpression ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializeropt
+	// ArrayCreationExpression ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializeropt
+
+	super.consumeArrayCreationExpression();
+
+	ArrayAllocationExpression alloc = (ArrayAllocationExpression)expressionStack[expressionPtr];
+	if (alloc.type == assistNode){
+		restartRecovery = true;
+		isOrphanCompletionNode = true; 
+	}
+}
+protected void consumeEnterAnonymousClassBody() {
+	// EnterAnonymousClassBody ::= $empty
+
+	if (this.indexOfAssistIdentifier() < 0) {
+		super.consumeEnterAnonymousClassBody();
+		return;
+	}
+	QualifiedAllocationExpression alloc;
+	AnonymousLocalTypeDeclaration anonymousType = 
+		new AnonymousLocalTypeDeclaration(); 
+	alloc = 
+		anonymousType.allocation = new SelectionOnQualifiedAllocationExpression(anonymousType); 
+	pushOnAstStack(anonymousType);
+
+	alloc.sourceEnd = rParenPos; //the position has been stored explicitly
+	int argumentLength;
+	if ((argumentLength = expressionLengthStack[expressionLengthPtr--]) != 0) {
+		expressionPtr -= argumentLength;
+		System.arraycopy(
+			expressionStack, 
+			expressionPtr + 1, 
+			alloc.arguments = new Expression[argumentLength], 
+			0, 
+			argumentLength); 
+	}
+	// trick to avoid creating a selection on type reference
+	char [] oldIdent = this.assistIdentifier();
+	this.setAssistIdentifier(null);			
+	alloc.type = getTypeReference(0);
+	this.setAssistIdentifier(oldIdent);		
+
+	anonymousType.sourceEnd = alloc.sourceEnd;
+	//position at the type while it impacts the anonymous declaration
+	anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
+	alloc.sourceStart = intStack[intPtr--];
+	pushOnExpressionStack(alloc);
+
+	assistNode = alloc;
+	this.lastCheckPoint = alloc.sourceEnd + 1;
+	restartRecovery = true; // force to restart into recovery mode
+	isOrphanCompletionNode = true;	
+		
+	anonymousType.bodyStart = scanner.currentPosition;	
+	listLength = 0; // will be updated when reading super-interfaces
+	// recovery
+	if (currentElement != null){ 
+		lastCheckPoint = anonymousType.bodyStart;
+		currentElement = currentElement.add(anonymousType, 0); // the recoveryTokenCheck will deal with the open brace
+		lastIgnoredToken = -1;		
+	}
+}
+protected void consumeEnterVariable() {
+	// EnterVariable ::= $empty
+	// do nothing by default
+
+	super.consumeEnterVariable();
+
+	AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
+	if (variable.type == assistNode){
+		restartRecovery = true;
+		isOrphanCompletionNode = false; // already attached inside variable decl
+	}
+}
+protected void consumeFieldAccess(boolean isSuperAccess) {
+	// FieldAccess ::= Primary '.' 'Identifier'
+	// FieldAccess ::= 'super' '.' 'Identifier'
+
+	if (this.indexOfAssistIdentifier() < 0) {
+		super.consumeFieldAccess(isSuperAccess);
+		return;
+	} 
+	FieldReference fieldReference = 
+		new SelectionOnFieldReference(
+			identifierStack[identifierPtr], 
+			identifierPositionStack[identifierPtr--]);
+	identifierLengthPtr--;
+	if (isSuperAccess) { //considerates the fieldReferenceerence beginning at the 'super' ....	
+		fieldReference.sourceStart = intStack[intPtr--];
+		fieldReference.receiver = new SuperReference(fieldReference.sourceStart, endPosition);
+		pushOnExpressionStack(fieldReference);
+	} else { //optimize push/pop
+		if ((fieldReference.receiver = expressionStack[expressionPtr]).isThis()) { //fieldReferenceerence begins at the this
+			fieldReference.sourceStart = fieldReference.receiver.sourceStart;
+		}
+		expressionStack[expressionPtr] = fieldReference;
+	}
+	assistNode = fieldReference;
+	this.lastCheckPoint = fieldReference.sourceEnd + 1;
+	restartRecovery	= true;	// force to restart in recovery mode
+	isOrphanCompletionNode = true;		
+}
+protected void consumeMethodInvocationName() {
+	// MethodInvocation ::= Name '(' ArgumentListopt ')'
+
+	// when the name is only an identifier...we have a message send to "this" (implicit)
+
+	char[] selector = identifierStack[identifierPtr];
+	if (!(selector == this.assistIdentifier() && CharOperation.equals(selector, SUPER))){
+		super.consumeMethodInvocationName();
+		return;
+	}	
+	ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(ExplicitConstructorCall.Super);
+	constructorCall.sourceEnd = rParenPos;
+	constructorCall.sourceStart = (int) (identifierPositionStack[identifierPtr] >>> 32);
+	int length;
+	if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+		expressionPtr -= length;
+		System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
+	}
+
+	pushOnAstStack(constructorCall);
+	this.assistNode = constructorCall;	
+	this.lastCheckPoint = constructorCall.sourceEnd + 1;
+	restartRecovery	= true;	// force to restart in recovery mode
+	isOrphanCompletionNode = true;	
+}
+protected void consumeMethodInvocationPrimary() {
+	//optimize the push/pop
+	//MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
+
+	char[] selector = identifierStack[identifierPtr];
+	if (!(selector == this.assistIdentifier() && CharOperation.equals(selector, SUPER))){
+		super.consumeMethodInvocationPrimary();
+		return;
+	}
+	ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(ExplicitConstructorCall.Super);
+	constructorCall.sourceEnd = rParenPos;
+	int length;
+	if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+		expressionPtr -= length;
+		System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
+	}
+	constructorCall.qualification = expressionStack[expressionPtr--];
+	constructorCall.sourceStart = constructorCall.qualification.sourceStart;
+	
+	pushOnAstStack(constructorCall);
+	this.assistNode = constructorCall;
+	this.lastCheckPoint = constructorCall.sourceEnd + 1;
+	restartRecovery	= true;	// force to restart in recovery mode
+	isOrphanCompletionNode = true;	
+}
+protected void consumeTypeImportOnDemandDeclarationName() {
+	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+	/* push an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	int index;
+
+	/* no need to take action if not inside assist identifiers */
+	if ((index = indexOfAssistIdentifier()) < 0) {
+		super.consumeTypeImportOnDemandDeclarationName();
+		return;
+	}
+	/* retrieve identifiers subset and whole positions, the assist node positions
+		should include the entire replaced source. */
+	int length = identifierLengthStack[identifierLengthPtr];
+	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length); 
+
+	/* build specific assist node on import statement */
+	ImportReference reference = this.createAssistImportReference(subset, positions);
+	reference.onDemand = true;
+	assistNode = reference;
+	this.lastCheckPoint = reference.sourceEnd + 1;
+	
+	pushOnAstStack(reference);
+
+	if (currentToken == TokenNameSEMICOLON){
+		reference.declarationSourceEnd = scanner.currentPosition - 1;
+	} else {
+		reference.declarationSourceEnd = (int) positions[length-1];
+	}
+	//endPosition is just before the ;
+	reference.declarationSourceStart = intStack[intPtr--];
+	// flush annotations defined prior to import statements
+	reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+
+	// recovery
+	if (currentElement != null){
+		lastCheckPoint = reference.declarationSourceEnd+1;
+		currentElement = currentElement.add(reference, 0);
+		lastIgnoredToken = -1;
+		restartRecovery = true; // used to avoid branching back into the regular automaton		
+	}
+}
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
+	return new SelectionOnImportReference(tokens, positions);
+}
+public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
+	return new SelectionOnPackageReference(tokens, positions);
+}
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
+	return new SelectionOnQualifiedNameReference(
+					previousIdentifiers, 
+					name, 
+					positions); 	
+}
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
+	return new SelectionOnQualifiedTypeReference(
+					previousIdentifiers, 
+					name, 
+					positions); 	
+}
+public NameReference createSingleAssistNameReference(char[] name, long position) {
+	return new SelectionOnSingleNameReference(name, position);
+}
+public TypeReference createSingleAssistTypeReference(char[] name, long position) {
+	return new SelectionOnSingleTypeReference(name, position);
+}
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
+
+	this.selectionStart = selectionStart;
+	this.selectionEnd = selectionEnd;	
+	SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
+	selectionScanner.selectionIdentifier = null;
+	selectionScanner.selectionStart = selectionStart;
+	selectionScanner.selectionEnd = selectionEnd;	
+	return this.dietParse(sourceUnit, compilationResult);
+}
+/*
+ * Flush parser/scanner state regarding to code assist
+ */
+public void flushAssistState() {
+
+	super.flushAssistState();
+	this.selectionNode = null;
+	this.setAssistIdentifier(null);
+}
+protected NameReference getUnspecifiedReference() {
+	/* build a (unspecified) NameReference which may be qualified*/
+
+	int completionIndex;
+
+	/* no need to take action if not inside completed identifiers */
+	if ((completionIndex = indexOfAssistIdentifier()) < 0) {
+		return super.getUnspecifiedReference();
+	}
+
+	int length = identifierLengthStack[identifierLengthPtr];
+	if (CharOperation.equals(assistIdentifier(), SUPER)){
+		Reference reference;
+		if (completionIndex > 0){ // qualified super
+			// discard 'super' from identifier stacks
+			identifierLengthStack[identifierLengthPtr] = completionIndex;
+			int ptr = identifierPtr -= (length - completionIndex);
+			reference = 
+				new SelectionOnQualifiedSuperReference(
+					getTypeReference(0), 
+					(int)(identifierPositionStack[ptr+1] >>> 32),
+					(int) identifierPositionStack[ptr+1]);
+		} else { // standard super
+			identifierPtr -= length;
+			identifierLengthPtr--;
+			reference = new SelectionOnSuperReference((int)(identifierPositionStack[identifierPtr+1] >>> 32), (int) identifierPositionStack[identifierPtr+1]);
+		}
+		pushOnAstStack(reference);
+		this.assistNode = reference;	
+		this.lastCheckPoint = reference.sourceEnd + 1;
+		restartRecovery	= true;	// force to restart in recovery mode
+		isOrphanCompletionNode = true;	
+		return new SingleNameReference(new char[0], 0); // dummy reference
+	}
+	NameReference nameReference;
+	/* retrieve identifiers subset and whole positions, the completion node positions
+		should include the entire replaced source. */
+	char[][] subset = identifierSubSet(completionIndex);
+	identifierLengthPtr--;
+	identifierPtr -= length;
+	long[] positions = new long[length];
+	System.arraycopy(
+		identifierPositionStack, 
+		identifierPtr + 1, 
+		positions, 
+		0, 
+		length);
+	/* build specific completion on name reference */
+	if (completionIndex == 0) {
+		/* completion inside first identifier */
+		nameReference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
+	} else {
+		/* completion inside subsequent identifier */
+		nameReference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
+	}
+	assistNode = nameReference;
+	this.lastCheckPoint = nameReference.sourceEnd + 1;
+	isOrphanCompletionNode = true;
+	restartRecovery = true; // force to restart into recovery mode
+	return nameReference;
+}
+/*
+ * Copy of code from superclass with the following change:
+ * In the case of qualified name reference if the cursor location is on the 
+ * qualified name reference, then create a CompletionOnQualifiedNameReference 
+ * instead.
+ */
+protected NameReference getUnspecifiedReferenceOptimized() {
+
+	int index = indexOfAssistIdentifier();
+	NameReference reference = super.getUnspecifiedReferenceOptimized();
+
+	if (index >= 0){
+		restartRecovery = true; // force to stop and restart in recovery mode
+		isOrphanCompletionNode = true;		
+	}
+	return reference;
+}
+public void initializeScanner(){
+	this.scanner = new SelectionScanner();
+}
+protected MessageSend newMessageSend() {
+	// '(' ArgumentListopt ')'
+	// the arguments are on the expression stack
+
+	char[] selector = identifierStack[identifierPtr];
+	if (selector != this.assistIdentifier()){
+		return super.newMessageSend();
+	}	
+	MessageSend messageSend = new SelectionOnMessageSend();
+	int length;
+	if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+		expressionPtr -= length;
+		System.arraycopy(
+			expressionStack, 
+			expressionPtr + 1, 
+			messageSend.arguments = new Expression[length], 
+			0, 
+			length); 
+	};
+	assistNode = messageSend;
+	restartRecovery	= true;	// force to restart in recovery mode
+	isOrphanCompletionNode = true;	
+	return messageSend;
+}
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
+
+	this.selectionStart = selectionStart;
+	this.selectionEnd = selectionEnd;	
+	SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
+	selectionScanner.selectionIdentifier = null;
+	selectionScanner.selectionStart = selectionStart;
+	selectionScanner.selectionEnd = selectionEnd;	
+	return this.parse(sourceUnit, compilationResult);
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+
+	/* if reached assist node inside method body, but still inside nested type,
+		should continue in diet mode until the end of the method body */
+	if (this.assistNode != null
+		&& !(referenceContext instanceof CompilationUnitDeclaration)){
+		currentElement.preserveEnclosingBlocks();
+		if (currentElement.enclosingType() == null){
+			this.resetStacks();
+			return false;
+		}
+	}
+	return super.resumeAfterRecovery();			
+}
+public void setAssistIdentifier(char[] assistIdent){
+	((SelectionScanner)scanner).selectionIdentifier = assistIdent;
+}
+/*
+ * Update recovery state based on current parser/scanner state
+ */
+protected void updateRecoveryState() {
+
+	/* expose parser state to recovery state */
+	currentElement.updateFromParserState();
+
+	/* may be able to retrieve completionNode as an orphan, and then attach it */
+	this.attachOrphanCompletionNode();
+	
+	/* check and update recovered state based on current token,
+		this action is also performed when shifting token after recovery
+		got activated once. 
+	*/
+	this.recoveryTokenCheck();
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index 5c055b1..8e29f7f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -1,2440 +1,2438 @@
-package org.eclipse.jdt.internal.compiler;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/**
- * Represents a class file wrapper on bytes, it is aware of its actual
- * type name.
- *
- * Public APIs are listed below:
- *
- * byte[] getBytes();
- *		Answer the actual bytes of the class file
- *
- * char[][] getCompoundName();
- * 		Answer the compound name of the class file.
- * 		For example, {{java}, {util}, {Hashtable}}.
- *
- * byte[] getReducedBytes();
- * 		Answer a smaller byte format, which is only contains some structural 
- *      information. Those bytes are decodable with a regular class file reader, 
- *      such as DietClassFileReader
- */ 
-
-import java.io.*;
-import java.util.*;
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
-
-
-public class ClassFile implements AttributeNamesConstants, CompilerModifiers, TypeConstants, TypeIds {
-	public SourceTypeBinding referenceBinding;
-	public ConstantPool constantPool;
-	public ClassFile enclosingClassFile; // used to generate private access methods
-	public int produceDebugAttributes;
-	public ReferenceBinding[] innerClassesBindings;
-	public int numberOfInnerClasses;
-	public byte[] header; // the header contains all the bytes till the end of the constant pool
-	public byte[] contents; // that collection contains all the remaining bytes of the .class file
-	public int headerOffset;
-	public int contentsOffset;
-	public int constantPoolOffset;
-	public int methodCountOffset;
-	public int methodCount;
-	protected boolean creatingProblemType;
-	public static final int INITIAL_CONTENTS_SIZE = 1000;
-	public static final int INITIAL_HEADER_SIZE = 1000;
-	public static final int INCREMENT_SIZE = 1000;
-	public static final int INNER_CLASSES_SIZE = 5;
-	protected CharArrayCache nameUsage;
-	public CodeStream codeStream;
-	protected int problemLine; // used to create line number attributes for problem methods
-/**
- * INTERNAL USE-ONLY
- * This methods creates a new instance of the receiver.
- */
-public ClassFile() {}
-/**
- * INTERNAL USE-ONLY
- * This methods creates a new instance of the receiver.
- *
- * @param aType org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
- * @param enclosingClassFile org.eclipse.jdt.internal.compiler.ClassFile
- * @param creatingProblemType <CODE>boolean</CODE>
- */
-public ClassFile(SourceTypeBinding aType, ClassFile enclosingClassFile, boolean creatingProblemType) {
-	referenceBinding = aType;
-	header = new byte[INITIAL_HEADER_SIZE];
-	// generate the magic numbers inside the header
-	header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
-	header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
-	header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
-	header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
-	if (((SourceTypeBinding) referenceBinding).scope.environment().options.targetJDK == CompilerOptions.JDK1_2) {
-		// Compatible with JDK 1.2
-		header[headerOffset++] = 0; // minorVersion = 0 means we just need to offset the current offset by 2
-		header[headerOffset++] = 0;
-		header[headerOffset++] = 0;
-		header[headerOffset++] = 46;
-	} else {
-		// Compatible with JDK 1.1
-		header[headerOffset++] = 0;
-		header[headerOffset++] = 3;
-		header[headerOffset++] = 0;
-		header[headerOffset++] = 45;
-	}
-	constantPoolOffset = headerOffset;
-	headerOffset += 2;
-	constantPool = new ConstantPool(this);
-
-	int accessFlags = aType.getAccessFlags();
-	if (aType.isProtected()) {
-		// set Acc_Public
-		accessFlags |= AccPublic;
-	}
-	// clear all bits that are illegal for a class or an interface
-	accessFlags
-		&= ~(
-			AccStrictfp
-				| AccProtected
-				| AccPrivate
-				| AccStatic
-				| AccSynchronized
-				| AccNative);
-				
-	// set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
-	accessFlags |= AccSuper;
-
-	this.enclosingClassFile = enclosingClassFile;
-	// innerclasses get their names computed at code gen time
-	if (aType.isLocalType()) {
-		((LocalTypeBinding) aType).constantPoolName(computeConstantPoolName((LocalTypeBinding) aType));
-		ReferenceBinding[] memberTypes = aType.memberTypes();
-		for (int i = 0, max = memberTypes.length; i < max; i++) {
-			((LocalTypeBinding) memberTypes[i]).constantPoolName(computeConstantPoolName((LocalTypeBinding) memberTypes[i]));
-		}
-	}
-	contents = new byte[INITIAL_CONTENTS_SIZE];
-	// now we continue to generate the bytes inside the contents array
-	contents[contentsOffset++] = (byte) (accessFlags >> 8);
-	contents[contentsOffset++] = (byte) accessFlags;
-	int classNameIndex = constantPool.literalIndex(aType);
-	contents[contentsOffset++] = (byte) (classNameIndex >> 8);
-	contents[contentsOffset++] = (byte) classNameIndex;
-	int superclassNameIndex;
-	if (aType.isInterface()) {
-		superclassNameIndex = constantPool.literalIndexForJavaLangObject();
-	} else {
-		superclassNameIndex = (aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
-	}
-	contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
-	contents[contentsOffset++] = (byte) superclassNameIndex;
-	ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
-	int interfacesCount = superInterfacesBinding.length;
-	contents[contentsOffset++] = (byte) (interfacesCount >> 8);
-	contents[contentsOffset++] = (byte) interfacesCount;
-	if (superInterfacesBinding != null) {
-		for (int i = 0; i < interfacesCount; i++) {
-			int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
-			contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
-			contents[contentsOffset++] = (byte) interfaceIndex;
-		}
-	}
-	produceDebugAttributes = ((SourceTypeBinding) referenceBinding).scope.environment().options.produceDebugAttributes;
-	innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
-	this.creatingProblemType = creatingProblemType;
-	codeStream = new CodeStream(this);
-
-	// retrieve the enclosing one guaranteed to be the one matching the propagated flow info
-	// 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
-	ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
-	if (this == outermostClassFile) {
-		codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
-	} else {
-		codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
-	}
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus method.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- */
-public void addAbstractMethod(
-	AbstractMethodDeclaration method,
-	MethodBinding methodBinding) {
-
-	// force the modifiers to be public and abstract
-	methodBinding.modifiers = AccPublic | AccAbstract;
-	
-	this.generateMethodInfoHeader(methodBinding);
-	int methodAttributeOffset = this.contentsOffset;
-	int attributeNumber = this.generateMethodInfoAttribute(methodBinding);
-	this.completeMethodInfo(methodAttributeOffset, attributeNumber);
-}
-/**
- * INTERNAL USE-ONLY
- * This methods generate all the attributes for the receiver.
- * For a class they could be:
- * - source file attribute
- * - inner classes attribute
- * - deprecated attribute
- */
-public void addAttributes() {
-	// update the method count
-	contents[methodCountOffset++] = (byte) (methodCount >> 8);
-	contents[methodCountOffset] = (byte) methodCount;
-	
-	int attributeNumber = 0;
-	// leave two bytes for the number of attributes and store the current offset
-	int attributeOffset = contentsOffset;
-	contentsOffset += 2;
-	int contentsLength;
-
-	// source attribute
-	if ((produceDebugAttributes & CompilerOptions.Source) != 0) {
-		String fullFileName = new String(referenceBinding.scope.referenceCompilationUnit().getFileName());
-		fullFileName = fullFileName.replace('\\', '/');
-		int lastIndex = fullFileName.lastIndexOf('/');
-		if (lastIndex != -1) {
-			fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
-		}
-		// check that there is enough space to write all the bytes for the field info corresponding
-		// to the @fieldBinding
-		if (contentsOffset + 8 >= (contentsLength = contents.length)) {
-			System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-		}
-		int sourceAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SourceName);
-		contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
-		contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
-		// The length of a source file attribute is 2. This is a fixed-length
-		// attribute
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 2;
-		// write the source file name
-		int fileNameIndex = constantPool.literalIndex(fullFileName.toCharArray());
-		contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
-		contents[contentsOffset++] = (byte) fileNameIndex;
-		attributeNumber++;
-	}
-
-	// Deprecated attribute
-	if (referenceBinding.isDeprecated()) {
-		// check that there is enough space to write all the bytes for the field info corresponding
-		// to the @fieldBinding
-		if (contentsOffset + 6 >= (contentsLength = contents.length)) {
-			System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-		}
-		int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
-		contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
-		contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
-		// the length of a deprecated attribute is equals to 0
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		attributeNumber++;
-	}
-
-	// Inner class attribute
-	if (numberOfInnerClasses != 0) {
-		// Generate the inner class attribute
-		int exSize;
-		if (contentsOffset + (exSize = (8 * numberOfInnerClasses + 8)) >= (contentsLength = contents.length)) {
-			System.arraycopy(contents, 0, (contents = new byte[contentsLength + (exSize >= INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
-		}
-		// Now we now the size of the attribute and the number of entries
-		// attribute name
-		int attributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
-		contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
-		contents[contentsOffset++] = (byte) attributeNameIndex;
-		int value = (numberOfInnerClasses << 3) + 2;
-		contents[contentsOffset++] = (byte) (value >> 24);
-		contents[contentsOffset++] = (byte) (value >> 16);
-		contents[contentsOffset++] = (byte) (value >> 8);
-		contents[contentsOffset++] = (byte) value;
-		contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
-		contents[contentsOffset++] = (byte) numberOfInnerClasses;
-		for (int i = 0; i < numberOfInnerClasses; i++) {
-			ReferenceBinding innerClass = innerClassesBindings[i];
-			int accessFlags = innerClass.getAccessFlags();
-			int innerClassIndex = constantPool.literalIndex(innerClass);
-			// inner class index
-			contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
-			contents[contentsOffset++] = (byte) innerClassIndex;
-			// outer class index: anonymous and local have no outer class index
-			if (innerClass.isMemberType()) {
-				// member or member of local
-				int outerClassIndex = constantPool.literalIndex(innerClass.enclosingType());
-				contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
-				contents[contentsOffset++] = (byte) outerClassIndex;
-			} else {
-				// equals to 0 if the innerClass is not a member type
-				contents[contentsOffset++] = 0;
-				contents[contentsOffset++] = 0;
-			}
-			// name index
-			if (!innerClass.isAnonymousType()) {
-				int nameIndex = constantPool.literalIndex(innerClass.sourceName());
-				contents[contentsOffset++] = (byte) (nameIndex >> 8);
-				contents[contentsOffset++] = (byte) nameIndex;
-			} else {
-				// equals to 0 if the innerClass is an anonymous type
-				contents[contentsOffset++] = 0;
-				contents[contentsOffset++] = 0;
-			}				
-			// access flag
-			if (innerClass.isAnonymousType()) {
-				accessFlags |= AccPrivate;
-			} else
-				if (innerClass.isLocalType() && !innerClass.isMemberType()) {
-					accessFlags |= AccPrivate;
-				}
-			contents[contentsOffset++] = (byte) (accessFlags >> 8);
-			contents[contentsOffset++] = (byte) accessFlags;
-		}
-		attributeNumber++;
-	}
-	// update the number of attributes
-	if (attributeOffset + 2 >= (contentsLength = contents.length)) {
-		System.arraycopy(
-			contents,
-			0,
-			(contents = new byte[contentsLength + INCREMENT_SIZE]),
-			0,
-			contentsLength);
-	}
-	contents[attributeOffset++] = (byte) (attributeNumber >> 8);
-	contents[attributeOffset] = (byte) attributeNumber;
-
-	// resynchronize all offsets of the classfile
-	header = constantPool.poolContent;
-	headerOffset = constantPool.currentOffset;
-	int constantPoolCount = constantPool.currentIndex;
-	header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
-	header[constantPoolOffset] = (byte) constantPoolCount;
-}
-/**
- * INTERNAL USE-ONLY
- * This methods generate all the default abstract method infos that correpond to
- * the abstract methods inherited from superinterfaces.
- */
-public void addDefaultAbstractMethods() { // default abstract methods
-	MethodBinding[] defaultAbstractMethods = referenceBinding.getDefaultAbstractMethods();
-	for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
-		generateMethodInfoHeader(defaultAbstractMethods[i]);
-		int methodAttributeOffset = contentsOffset;
-		int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
-		completeMethodInfo(methodAttributeOffset, attributeNumber);
-	}
-}
-/**
- * INTERNAL USE-ONLY
- * This methods generates the bytes for the field binding passed like a parameter
- * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
- */
-public void addFieldInfo(FieldBinding fieldBinding) {
-	int attributeNumber = 0;
-	// check that there is enough space to write all the bytes for the field info corresponding
-	// to the @fieldBinding
-	int contentsLength;
-	if (contentsOffset + 30 >= (contentsLength = contents.length)) {
-		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	// Generate two attribute: constantValueAttribute and SyntheticAttribute
-	// Now we can generate all entries into the byte array
-	// First the accessFlags
-	int accessFlags = fieldBinding.getAccessFlags();
-	contents[contentsOffset++] = (byte) (accessFlags >> 8);
-	contents[contentsOffset++] = (byte) accessFlags;
-	// Then the nameIndex
-	int nameIndex = constantPool.literalIndex(fieldBinding.name);
-	contents[contentsOffset++] = (byte) (nameIndex >> 8);
-	contents[contentsOffset++] = (byte) nameIndex;
-	// Then the descriptorIndex
-	int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
-	contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
-	contents[contentsOffset++] = (byte) descriptorIndex;
-	// leave some space for the number of attributes
-	int fieldAttributeOffset = contentsOffset;
-	contentsOffset += 2;
-	// 4.7.2 only static constant fields get a ConstantAttribute
-	if (fieldBinding.isStatic() 
-		&& fieldBinding.constant != Constant.NotAConstant 
-		&& fieldBinding.constant.typeID() != T_null) {
-		// Now we generate the constant attribute corresponding to the fieldBinding
-		int constantValueNameIndex = constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
-		contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
-		contents[contentsOffset++] = (byte) constantValueNameIndex;
-		// The attribute length = 2 in case of a constantValue attribute
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 2;
-		attributeNumber++;
-		// Need to add the constant_value_index
-		switch (fieldBinding.constant.typeID()) {
-			case T_boolean :
-				int booleanValueIndex = constantPool.literalIndex(fieldBinding.constant.booleanValue() ? 1 : 0);
-				contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
-				contents[contentsOffset++] = (byte) booleanValueIndex;
-				break;
-			case T_byte :
-			case T_char :
-			case T_int :
-			case T_short :
-				int integerValueIndex = constantPool.literalIndex(fieldBinding.constant.intValue());
-				contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
-				contents[contentsOffset++] = (byte) integerValueIndex;
-				break;
-			case T_float :
-				int floatValueIndex = constantPool.literalIndex(fieldBinding.constant.floatValue());
-				contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
-				contents[contentsOffset++] = (byte) floatValueIndex;
-				break;
-			case T_double :
-				int doubleValueIndex = constantPool.literalIndex(fieldBinding.constant.doubleValue());
-				contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
-				contents[contentsOffset++] = (byte) doubleValueIndex;
-				break;
-			case T_long :
-				int longValueIndex = constantPool.literalIndex(fieldBinding.constant.longValue());
-				contents[contentsOffset++] = (byte) (longValueIndex >> 8);
-				contents[contentsOffset++] = (byte) longValueIndex;
-				break;
-			case T_String :
-				int stringValueIndex = constantPool.literalIndex(((StringConstant) fieldBinding.constant).stringValue());
-				if (stringValueIndex == -1) {
-					if (!creatingProblemType) {
-						// report an error and abort: will lead to a problem type classfile creation
-						TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
-						FieldDeclaration[] fieldDecls = typeDeclaration.fields;
-						for (int i = 0, max = fieldDecls.length; i < max; i++) {
-							if (fieldDecls[i].binding == fieldBinding) {
-								// problem should abort
-								typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(fieldDecls[i]);
-							}
-						}
-					} else {
-						// already inside a problem type creation : no constant for this field
-						contentsOffset = fieldAttributeOffset + 2; // +2 is necessary to keep the two byte space for the attribute number
-						attributeNumber--;
-					}
-				} else {
-					contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
-					contents[contentsOffset++] = (byte) stringValueIndex;
-				}
-		}
-	}
-	if (fieldBinding.isSynthetic()) {
-		int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
-		contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
-		contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
-		// the length of a synthetic attribute is equals to 0
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		attributeNumber++;
-	}
-	if (fieldBinding.isDeprecated()) {
-		int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
-		contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
-		contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
-		// the length of a deprecated attribute is equals to 0
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		attributeNumber++;
-	}
-	contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
-	contents[fieldAttributeOffset] = (byte) attributeNumber;
-}
-/**
- * INTERNAL USE-ONLY
- * This methods generate all the fields infos for the receiver.
- * This includes:
- * - a field info for each defined field of that class
- * - a field info for each synthetic field (e.g. this$0)
- */
-public void addFieldInfos() {
-	SourceTypeBinding currentBinding = referenceBinding;
-	FieldBinding[] syntheticFields = currentBinding.syntheticFields();
-	int fieldCount = currentBinding.fieldCount() + (syntheticFields == null ? 0 : syntheticFields.length);
-
-	// write the number of fields
-	contents[contentsOffset++] = (byte) (fieldCount >> 8);
-	contents[contentsOffset++] = (byte) fieldCount;
-
-	FieldBinding[] fieldBindings = currentBinding.fields();
-	for (int i = 0, max = fieldBindings.length; i < max; i++) {
-		addFieldInfo(fieldBindings[i]);
-	}
-	if (syntheticFields != null) {
-		for (int i = 0, max = syntheticFields.length; i < max; i++) {
-			addFieldInfo(syntheticFields[i]);
-		}
-	}
-}
-/**
- * INTERNAL USE-ONLY
- * This methods stores the bindings for each inner class. They will be used to know which entries
- * have to be generated for the inner classes attributes.
- * @param referenceBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding 
- */
-public void addInnerClasses(ReferenceBinding referenceBinding) {
-	// check first if that reference binding is there
-	for (int i = 0; i < numberOfInnerClasses; i++) {
-		if (innerClassesBindings[i] == referenceBinding)
-			return;
-	}
-	int length = innerClassesBindings.length;
-	if (numberOfInnerClasses == length) {
-		System.arraycopy(innerClassesBindings, 0, (innerClassesBindings = new ReferenceBinding[length * 2]), 0, length);
-	}
-	innerClassesBindings[numberOfInnerClasses++] = referenceBinding;
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem clinit method info that correspond to a boggus method.
- *
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- */
-public void addProblemClinit(IProblem[] problems) {
-	generateMethodInfoHeaderForClinit();
-	// leave two spaces for the number of attributes
-	contentsOffset -= 2;
-	int attributeOffset = contentsOffset;
-	contentsOffset += 2;
-	ReferenceBinding[] thrownsExceptions;
-	int attributeNumber = 0;
-	int contentsLength;
-
-	int codeAttributeOffset = contentsOffset;
-	generateCodeAttributeHeader();
-	codeStream.resetForProblemClinit(this);
-	String problemString = ""/*nonNLS*/;
-	if (problems != null) {
-		int max = problems.length;
-		StringBuffer buffer = new StringBuffer(25);
-		int count = 0;
-		for (int i = 0; i < max; i++) {
-			IProblem problem = problems[i];
-			if ((problem != null) && (problem.isError())) {
-				buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
-				count++;
-				if (problemLine == 0) {
-					problemLine = problem.getSourceLineNumber();
-				}
-				problems[i] = null;
-			}
-		} // insert the top line afterwards, once knowing how many problems we have to consider
-		if (count > 1) {
-			buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
-		} else {
-			buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
-		}
-		problemString = buffer.toString();
-	}
-
-	// return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
-	int[] exceptionHandler = codeStream.generateCodeAttributeForProblemMethod(referenceBinding.scope.problemReporter().options.runtimeExceptionNameForCompileError, problemString);
-	attributeNumber++; // code attribute
-	completeCodeAttributeForClinit(
-		codeAttributeOffset,
-		exceptionHandler,
-		referenceBinding
-			.scope
-			.referenceCompilationUnit()
-			.compilationResult
-			.lineSeparatorPositions);
-	contents[attributeOffset++] = (byte) (attributeNumber >> 8);
-	contents[attributeOffset] = (byte) attributeNumber;
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus constructor.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- */
-public void addProblemConstructor(
-	AbstractMethodDeclaration method, 
-	MethodBinding methodBinding, 
-	IProblem[] problems) {
-
-	// always clear the strictfp/native/abstract bit for a problem method
-	methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
-		
-	generateMethodInfoHeader(methodBinding); 
-	// We know that we won't get more than 1 attribute: the code attribute
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 1; // Code attribute
-	int codeAttributeOffset = contentsOffset;
-	generateCodeAttributeHeader();
-	final ProblemReporter problemReporter = method.scope.problemReporter();
-	codeStream.reset(method, this);
-	String problemString = ""/*nonNLS*/;
-	if (problems != null) {
-		int max = problems.length;
-		StringBuffer buffer = new StringBuffer(25);
-		int count = 0;
-		for (int i = 0; i < max; i++) {
-			IProblem problem = problems[i];
-			if ((problem != null) && (problem.isError())) {
-				buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
-				count++;
-				if (problemLine == 0) {
-					problemLine = problem.getSourceLineNumber();
-				}
-			}
-		} // insert the top line afterwards, once knowing how many problems we have to consider
-		if (count > 1) {
-			buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
-		} else {
-			buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
-		}
-		problemString = buffer.toString();
-	}
-	
-	// return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
-	int[] exceptionHandler = 
-		codeStream.generateCodeAttributeForProblemMethod(
-			problemReporter.options.runtimeExceptionNameForCompileError, 
-			problemString);
-	completeCodeAttributeForProblemMethod(
-		method,
-		methodBinding, 
-		codeAttributeOffset, 
-		exceptionHandler, 
-		((SourceTypeBinding) methodBinding.declaringClass)
-			.scope
-			.referenceCompilationUnit()
-			.compilationResult
-			.lineSeparatorPositions); 
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus constructor.
- * Reset the position inside the contents byte array to the savedOffset.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- * @param savedOffset <CODE>int</CODE>
- */
-public void addProblemConstructor(AbstractMethodDeclaration method, MethodBinding methodBinding,IProblem[] problems, int savedOffset) {
-	// we need to move back the contentsOffset to the value at the beginning of the method
-	contentsOffset = savedOffset;
-	methodCount--; // we need to remove the method that causes the problem
-	addProblemConstructor(method, methodBinding, problems);
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus method.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- */
-public void addProblemMethod(
-	AbstractMethodDeclaration method, 
-	MethodBinding methodBinding, 
-	IProblem[] problems) {
-	if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
-		method.abort(AbstractMethodDeclaration.AbortType);
-	}	
-	// always clear the strictfp/native/abstract bit for a problem method
-	methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
-	
-	generateMethodInfoHeader(methodBinding);
-	// leave two spaces for the number of attributes
-	int attributeOffset = contentsOffset;
-	contentsOffset += 2;
-	ReferenceBinding[] thrownsExceptions;
-	int attributeNumber = 0;
-	int contentsLength;
-	
-	if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
-		// The method has a throw clause. So we need to add an exception attribute
-		// check that there is enough space to write all the bytes for the exception attribute
-		int length = thrownsExceptions.length;
-		if (contentsOffset + (8 + length * 2) >= (contentsLength = contents.length)) {
-			System.arraycopy(contents, 0, (contents = new byte[contentsLength + Math.max(INCREMENT_SIZE, (8 + length * 2))]), 0, contentsLength);
-		}
-		int exceptionNameIndex = constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
-		contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
-		contents[contentsOffset++] = (byte) exceptionNameIndex;
-		// The attribute length = length * 2 + 2 in case of a exception attribute
-		int attributeLength = length * 2 + 2;
-		contents[contentsOffset++] = (byte) (attributeLength >> 24);
-		contents[contentsOffset++] = (byte) (attributeLength >> 16);
-		contents[contentsOffset++] = (byte) (attributeLength >> 8);
-		contents[contentsOffset++] = (byte) attributeLength;
-		contents[contentsOffset++] = (byte) (length >> 8);
-		contents[contentsOffset++] = (byte) length;
-		for (int i = 0; i < length; i++) {
-			int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
-			contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
-			contents[contentsOffset++] = (byte) exceptionIndex;
-		}
-		attributeNumber++;
-	}
-
-	// Deprecated attribute
-	// Check that there is enough space to write the deprecated attribute
-	if (contentsOffset + 6 >= (contentsLength = contents.length)) {
-		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	if (methodBinding.isDeprecated()) {
-		int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
-		contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
-		contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
-		// the length of a deprecated attribute is equals to 0
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-
-		attributeNumber++;
-	}
-	
-	int codeAttributeOffset = contentsOffset;
-	generateCodeAttributeHeader();
-	final ProblemReporter problemReporter = method.scope.problemReporter();
-	codeStream.reset(method, this);
-	String problemString = ""/*nonNLS*/;
-	if (problems != null) {
-		int max = problems.length;
-		StringBuffer buffer = new StringBuffer(25);
-		int count = 0;
-		for (int i = 0; i < max; i++) {
-			IProblem problem = problems[i];
-			if ((problem != null)
-				&& (problem.isError())
-				&& (problem.getSourceStart() >= method.declarationSourceStart)
-				&& (problem.getSourceEnd() <= method.declarationSourceEnd)) {
-				buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
-				count++;
-				if (problemLine == 0) {
-					problemLine = problem.getSourceLineNumber();
-				}
-				problems[i] = null;
-			}
-		} // insert the top line afterwards, once knowing how many problems we have to consider
-		if (count > 1) {
-			buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
-		} else {
-			buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
-		}
-		problemString = buffer.toString();
-	}
-
-	// return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
-	int[] exceptionHandler = 
-		codeStream.generateCodeAttributeForProblemMethod(
-			problemReporter.options.runtimeExceptionNameForCompileError, 
-			problemString);
-	attributeNumber++; // code attribute
-	completeCodeAttributeForProblemMethod(
-		method, 
-		methodBinding, 
-		codeAttributeOffset, 
-		exceptionHandler, 
-		((SourceTypeBinding) methodBinding.declaringClass)
-			.scope
-			.referenceCompilationUnit()
-			.compilationResult
-			.lineSeparatorPositions);
-	contents[attributeOffset++] = (byte) (attributeNumber >> 8);
-	contents[attributeOffset] = (byte) attributeNumber;	
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a boggus method.
- * Reset the position inside the contents byte array to the savedOffset.
- *
- * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
- * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
- * @param savedOffset <CODE>int</CODE>
- */
-public void addProblemMethod(AbstractMethodDeclaration method, MethodBinding methodBinding,IProblem[] problems, int savedOffset) {
-	// we need to move back the contentsOffset to the value at the beginning of the method
-	contentsOffset = savedOffset;
-	methodCount--; // we need to remove the method that causes the problem
-	addProblemMethod(method, methodBinding, problems);
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for all the special method infos.
- * They are:
- * - synthetic access methods
- * - default abstract methods
- */
-public void addSpecialMethods() {
-	// add all methods (default abstract methods and synthetic)
-
-	// default abstract methods
-	SourceTypeBinding currentBinding = referenceBinding;
-	MethodBinding[] defaultAbstractMethods = currentBinding.getDefaultAbstractMethods();
-	for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
-		generateMethodInfoHeader(defaultAbstractMethods[i]);
-		int methodAttributeOffset = contentsOffset;
-		int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
-		completeMethodInfo(methodAttributeOffset, attributeNumber);
-	}
-
-	// add synthetic methods infos
-	SyntheticAccessMethodBinding[] syntheticAccessMethods = currentBinding.syntheticAccessMethods();
-	if (syntheticAccessMethods != null) {
-		for (int i = 0, max = syntheticAccessMethods.length; i < max; i++) {
-			SyntheticAccessMethodBinding accessMethodBinding = syntheticAccessMethods[i];
-			switch (accessMethodBinding.accessType) {
-				case SyntheticAccessMethodBinding.FieldReadAccess :
-					// generate a method info to emulate an reading access to
-					// a private field
-					addSyntheticFieldReadAccessMethod(syntheticAccessMethods[i]);
-					break;
-				case SyntheticAccessMethodBinding.FieldWriteAccess :
-					// generate a method info to emulate an writing access to
-					// a private field
-					addSyntheticFieldWriteAccessMethod(syntheticAccessMethods[i]);
-					break;
-				case SyntheticAccessMethodBinding.MethodAccess :
-					// generate a method info to emulate an access to a private method
-					addSyntheticMethodAccessMethod(syntheticAccessMethods[i]);
-					break;
-				case SyntheticAccessMethodBinding.ConstructorAccess :
-					// generate a method info to emulate an access to a private method
-					addSyntheticConstructorAccessMethod(syntheticAccessMethods[i]);
-			}
-		}
-	}
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an access to a private constructor.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public void addSyntheticConstructorAccessMethod(SyntheticAccessMethodBinding methodBinding) {
-	generateMethodInfoHeader(methodBinding);
-	// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 2;	
-	// Code attribute
-	int codeAttributeOffset = contentsOffset;
-	generateCodeAttributeHeader();
-	codeStream.init(this);
-	codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
-	completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
-	// add the synthetic attribute
-	int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
-	contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
-	contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
-	// the length of a synthetic attribute is equals to 0
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an read access to a private field.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public void addSyntheticFieldReadAccessMethod(SyntheticAccessMethodBinding methodBinding) {
-	generateMethodInfoHeader(methodBinding);
-	// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 2;
-	// Code attribute
-	int codeAttributeOffset = contentsOffset;
-	generateCodeAttributeHeader();
-	codeStream.init(this);
-	codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
-	completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
-	// add the synthetic attribute
-	int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
-	contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
-	contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
-	// the length of a synthetic attribute is equals to 0
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;	
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an write access to a private field.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public void addSyntheticFieldWriteAccessMethod(SyntheticAccessMethodBinding methodBinding) {
-	generateMethodInfoHeader(methodBinding);
-	// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 2;	
-	// Code attribute
-	int codeAttributeOffset = contentsOffset;
-	generateCodeAttributeHeader();
-	codeStream.init(this);
-	codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
-	completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
-	// add the synthetic attribute
-	int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
-	contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
-	contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
-	// the length of a synthetic attribute is equals to 0
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;	
-}
-/**
- * INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an access to a private method.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public void addSyntheticMethodAccessMethod(SyntheticAccessMethodBinding methodBinding) {
-	generateMethodInfoHeader(methodBinding);
-	// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 2;	
-	// Code attribute
-	int codeAttributeOffset = contentsOffset;
-	generateCodeAttributeHeader();
-	codeStream.init(this);
-	codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
-	completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
-	// add the synthetic attribute
-	int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
-	contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
-	contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
-	// the length of a synthetic attribute is equals to 0
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 0;	
-}
-/**
- * INTERNAL USE-ONLY
- * Build all the directories and subdirectories corresponding to the packages names
- * into the directory specified in parameters.
- *
- * outputPath is formed like:
- *	   c:\temp\ the last character is a file separator
- * relativeFileName is formed like:
- *     java\lang\String.class *
- * 
- * @param outputPath java.lang.String
- * @param relativeFileName java.lang.String
- * @return java.lang.String
- */
-public static String buildAllDirectoriesInto(String outputPath, String relativeFileName) throws IOException {
-	char fileSeparatorChar = File.separatorChar;
-	String fileSeparator = File.separator;
-	File f;
-	// First we ensure that the outputPath exists
-	outputPath = outputPath.replace('/', fileSeparatorChar);
-	// To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
-	if (outputPath.endsWith(fileSeparator)) {
-		outputPath = outputPath.substring(0, outputPath.length() - 1);
-	}
-	f = new File(outputPath);
-	if (f.exists()) {
-		if (!f.isDirectory()) {
-			System.out.println(Util.bind("output.isFile"/*nonNLS*/,f.getAbsolutePath()));
-			throw new IOException(Util.bind("output.isFileNotDirectory"/*nonNLS*/));
-		}
-	} else {
-		// we have to create that directory
-		if (!f.mkdirs()) {
-			System.out.println(Util.bind("output.dirName"/*nonNLS*/,f.getAbsolutePath()));
-			throw new IOException(Util.bind("output.notValidAll"/*nonNLS*/));
-		}
-	}
-	StringBuffer outDir = new StringBuffer(outputPath);
-	outDir.append(fileSeparator);
-	StringTokenizer tokenizer = new StringTokenizer(relativeFileName, fileSeparator);
-	String token = tokenizer.nextToken();
-	while (tokenizer.hasMoreTokens()) {
-		f = new File(outDir.append(token).append(fileSeparator).toString());
-		if (f.exists()) {
-			// The outDir already exists, so we proceed the next entry
-			// System.out.println("outDir: " + outDir + " already exists.");
-		} else {
-			// Need to add the outDir
-			if (!f.mkdir()) {
-				System.out.println(Util.bind("output.fileName"/*nonNLS*/,f.getName()));
-				throw new IOException(Util.bind("output.notValid"/*nonNLS*/));
-			}
-		}
-		token = tokenizer.nextToken();
-	}
-	// token contains the last one
-	return outDir.append(token).toString();
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- */
-public void completeCodeAttribute(int codeAttributeOffset) {
-	// reinitialize the localContents with the byte modified by the code stream
-	byte[] localContents = contents = codeStream.bCodeStream;
-	int localContentsOffset = codeStream.classFileOffset;
-	// codeAttributeOffset is the position inside localContents byte array before we started to write
-	// any information about the codeAttribute
-	// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
-	// to get the right position, 6 for the max_stack etc...
-	int contentsLength;
-	int code_length = codeStream.position;
-	if (code_length > 65535) {
-		codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration);
-	}
-	if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	int max_stack = codeStream.stackMax;
-	localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
-	localContents[codeAttributeOffset + 7] = (byte) max_stack;
-	int max_locals = codeStream.maxLocals;
-	localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
-	localContents[codeAttributeOffset + 9] = (byte) max_locals;
-	localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
-	localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
-	localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
-	localContents[codeAttributeOffset + 13] = (byte) code_length;
-
-	// write the exception table
-	int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
-	ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
-	int exSize;
-	if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2)) >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
-	}
-	// there is no exception table, so we need to offset by 2 the current offset and move 
-	// on the attribute generation
-	localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
-	localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
-	for (int i = 0; i < exceptionHandlersNumber; i++) {
-		ExceptionLabel exceptionHandler = exceptionHandlers[i];
-		int start = exceptionHandler.start;
-		localContents[localContentsOffset++] = (byte) (start >> 8);
-		localContents[localContentsOffset++] = (byte) start;
-		int end = exceptionHandler.end;
-		localContents[localContentsOffset++] = (byte) (end >> 8);
-		localContents[localContentsOffset++] = (byte) end;
-		int handlerPC = exceptionHandler.position;
-		localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
-		localContents[localContentsOffset++] = (byte) handlerPC;
-		if (exceptionHandler.exceptionType == null) {
-			// any exception handler
-			localContents[localContentsOffset++] = 0;
-			localContents[localContentsOffset++] = 0;
-		} else {
-			int nameIndex;
-			if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
-				/* represents ClassNotFoundException, see class literal access*/
-				nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
-			} else {
-				nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
-			}
-			localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-			localContents[localContentsOffset++] = (byte) nameIndex;
-		}
-	}
-
-	// debug attributes
-	int codeAttributeAttributeOffset = localContentsOffset;
-	int attributeNumber = 0;
-	// leave two bytes for the attribute_length
-	localContentsOffset += 2;
-
-	// first we handle the linenumber attribute
-	if (codeStream.generateLineNumberAttributes) {
-		/* Create and add the line number attribute (used for debugging) 
-		 * Build the pairs of:
-		 * 	(bytecodePC lineNumber)
-		 * according to the table of start line indexes and the pcToSourceMap table
-		 * contained into the codestream
-		 */
-		/** OLD CODE
-				int[][] pcToSourceMapTable;
-		int previousLineNumber;
-		int[] flatTable;
-		int index;
-		int startLineIndexes[] = codeStream.methodDeclaration.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
-		int max = startLineIndexes.length;
-		*/ 
-		int[] pcToSourceMapTable;
-		if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null) && (codeStream.pcToSourceMapSize != 0)) {
-			int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
-			if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
-				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-			}
-			localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
-			localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
-			int lineNumberTableOffset = localContentsOffset;
-			localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
-			/** OLD CODE
-			previousLineNumber = 0;
-
-			// Seems like do would be better, but this preserves the existing behavior.
-
-			flatTable = new int[code_length];
-			for (int i = codeStream.pcToSourceMapSize - 1; i >= 0; i--) {
-				// entry contains the following structure:
-				// position 1: startPC
-				// position 2: endPC
-				// position 3: sourceStart
-				// position 4: sourceEnd
-				// Compute the line number for a given source position
-				index = searchLineNumber(startLineIndexes, pcToSourceMapTable[i][2]);
-				for (int j = pcToSourceMapTable[i][0]; j < pcToSourceMapTable[i][1]; j++)
-					flatTable[j] = index;
-			}
-			previousLineNumber = -1;
-			
-			*/
-			int numberOfEntries = 0;
-			int length = codeStream.pcToSourceMapSize;
-			/** OLD CODE
-				int length = flatTable.length;
-						for (int i = 0; i < length; i++) {
-				if (flatTable[i] != previousLineNumber) {
-					previousLineNumber = flatTable[i];
-					// write the entry
-					if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
-						System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-					}
-					localContents[localContentsOffset++] = (byte) (i >> 8);
-					localContents[localContentsOffset++] = (byte) i;
-					localContents[localContentsOffset++] = (byte) (previousLineNumber >> 8);
-					localContents[localContentsOffset++] = (byte) previousLineNumber;
-					numberOfEntries++;
-				}
-			}
-			*/			
-			for (int i = 0; i < length;) {
-				// write the entry
-				if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
-					System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-				}
-				int pc = pcToSourceMapTable[i++];
-				localContents[localContentsOffset++] = (byte) (pc >> 8);
-				localContents[localContentsOffset++] = (byte) pc;
-				int lineNumber = pcToSourceMapTable[i++];
-				localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
-				localContents[localContentsOffset++] = (byte) lineNumber;
-				numberOfEntries++;
-			}
-			// now we change the size of the line number attribute
-			int lineNumberAttr_length = numberOfEntries * 4 + 2;
-			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
-			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
-			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
-			localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
-			localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
-			localContents[lineNumberTableOffset++] = (byte) numberOfEntries;
-			attributeNumber++;
-		}
-	}
-
-
-
-	// then we do the local variable attribute
-	if (codeStream.generateLocalVariableTableAttributes) {
-		int localVariableTableOffset = localContentsOffset;
-		int numberOfEntries = 0;
-		int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
-		if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
-			System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-		}
-		localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
-		localContents[localContentsOffset++] = (byte) localVariableNameIndex;
-		localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
-		int nameIndex;
-		int descriptorIndex;
-		if (!codeStream.methodDeclaration.isStatic()) {
-			numberOfEntries++;
-			if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
-				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-			}
-			localContentsOffset += 2; // the startPC for this is always 0
-			localContents[localContentsOffset++] = (byte) (code_length >> 8);
-			localContents[localContentsOffset++] = (byte) code_length;
-			nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
-			localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-			localContents[localContentsOffset++] = (byte) nameIndex;
-			descriptorIndex = constantPool.literalIndex(codeStream.methodDeclaration.binding.declaringClass.signature());
-			localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
-			localContents[localContentsOffset++] = (byte) descriptorIndex;
-			localContentsOffset += 2; // the resolved position for this is always 0
-		}
-		for (int i = 0; i < codeStream.allLocalsCounter; i++) {
-			LocalVariableBinding localVariable = codeStream.locals[i];
-			for (int j = 0; j < localVariable.initializationCount; j++) {
-				int startPC = localVariable.initializationPCs[j << 1];
-				int endPC = localVariable.initializationPCs[(j << 1) + 1];
-				if (startPC != endPC) { // only entries for non zero length
-					int currentLength;
-					if (endPC == -1) {
-						localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
-					}
-					if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
-						System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-					}
-					// now we can safely add the local entry
-					numberOfEntries++;
-					localContents[localContentsOffset++] = (byte) (startPC >> 8);
-					localContents[localContentsOffset++] = (byte) startPC;
-					int length = endPC - startPC;
-					localContents[localContentsOffset++] = (byte) (length >> 8);
-					localContents[localContentsOffset++] = (byte) length;
-					nameIndex = constantPool.literalIndex(localVariable.name);
-					localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-					localContents[localContentsOffset++] = (byte) nameIndex;
-					descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
-					localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
-					localContents[localContentsOffset++] = (byte) descriptorIndex;
-					int resolvedPosition = localVariable.resolvedPosition;
-					localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
-					localContents[localContentsOffset++] = (byte) resolvedPosition;
-				}
-			}
-		}
-		int value = numberOfEntries * 10 + 2;
-		localVariableTableOffset += 2;
-		localContents[localVariableTableOffset++] = (byte) (value >> 24);
-		localContents[localVariableTableOffset++] = (byte) (value >> 16);
-		localContents[localVariableTableOffset++] = (byte) (value >> 8);
-		localContents[localVariableTableOffset++] = (byte) value;
-		localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
-		localContents[localVariableTableOffset] = (byte) numberOfEntries;
-		attributeNumber++;
-	}
-	// update the number of attributes
-	// ensure first that there is enough space available inside the localContents array
-	if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
-	localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
-
-	// update the attribute length
-	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
-	localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
-	localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
-	localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
-	localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
-	contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- */
-public void completeCodeAttributeForClinit(int codeAttributeOffset) {
-	// reinitialize the contents with the byte modified by the code stream
-	byte[] localContents = contents = codeStream.bCodeStream;
-	int localContentsOffset = codeStream.classFileOffset;
-	// codeAttributeOffset is the position inside contents byte array before we started to write
-	// any information about the codeAttribute
-	// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
-	// to get the right position, 6 for the max_stack etc...
-	int contentsLength;
-	int code_length = codeStream.position;
-	if (code_length > 65535) {
-		codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration.scope.referenceType());
-	}
-	if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	int max_stack = codeStream.stackMax;
-	localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
-	localContents[codeAttributeOffset + 7] = (byte) max_stack;
-	int max_locals = codeStream.maxLocals;
-	localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
-	localContents[codeAttributeOffset + 9] = (byte) max_locals;
-	localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
-	localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
-	localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
-	localContents[codeAttributeOffset + 13] = (byte) code_length;
-
-	// write the exception table
-	int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
-	ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
-	int exSize;
-	if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2)) >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
-	}
-	// there is no exception table, so we need to offset by 2 the current offset and move 
-	// on the attribute generation
-	localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
-	localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
-	for (int i = 0; i < exceptionHandlersNumber; i++) {
-		ExceptionLabel exceptionHandler = exceptionHandlers[i];
-		int start = exceptionHandler.start;
-		localContents[localContentsOffset++] = (byte) (start >> 8);
-		localContents[localContentsOffset++] = (byte) start;
-		int end = exceptionHandler.end;
-		localContents[localContentsOffset++] = (byte) (end >> 8);
-		localContents[localContentsOffset++] = (byte) end;
-		int handlerPC = exceptionHandler.position;
-		localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
-		localContents[localContentsOffset++] = (byte) handlerPC;
-		if (exceptionHandler.exceptionType == null) {
-			// any exception handler
-			localContentsOffset += 2;
-		} else {
-			int nameIndex;
-			if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
-				/* represents denote ClassNotFoundException, see class literal access*/
-				nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
-			} else {
-				nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
-			}
-			localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-			localContents[localContentsOffset++] = (byte) nameIndex;
-		}
-	}
-
-	// debug attributes
-	int codeAttributeAttributeOffset = localContentsOffset;
-	int attributeNumber = 0;
-	// leave two bytes for the attribute_length
-	localContentsOffset += 2;
-
-	// first we handle the linenumber attribute
-	if (codeStream.generateLineNumberAttributes) {
-		/* Create and add the line number attribute (used for debugging) 
-		 * Build the pairs of:
-		 * 	(bytecodePC lineNumber)
-		 * according to the table of start line indexes and the pcToSourceMap table
-		 * contained into the codestream
-		 */
-		int[] pcToSourceMapTable;
-		if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null) && (codeStream.pcToSourceMapSize != 0)) {
-			int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
-			if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
-				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-			}
-			localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
-			localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
-			int lineNumberTableOffset = localContentsOffset;
-			localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
-			int numberOfEntries = 0;
-			int length = codeStream.pcToSourceMapSize;
-			for (int i = 0; i < length;) {
-				// write the entry
-				if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
-					System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-				}
-				int pc = pcToSourceMapTable[i++];
-				localContents[localContentsOffset++] = (byte) (pc >> 8);
-				localContents[localContentsOffset++] = (byte) pc;
-				int lineNumber = pcToSourceMapTable[i++];
-				localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
-				localContents[localContentsOffset++] = (byte) lineNumber;
-				numberOfEntries++;
-			}
-			// now we change the size of the line number attribute
-			int lineNumberAttr_length = numberOfEntries * 4 + 2;
-			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
-			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
-			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
-			localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
-			localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
-			localContents[lineNumberTableOffset++] = (byte) numberOfEntries;
-			attributeNumber++;
-		}
-	}
-
-
-
-	// then we do the local variable attribute
-	if (codeStream.generateLocalVariableTableAttributes) {
-		int localVariableTableOffset = localContentsOffset;
-		int numberOfEntries = 0;
-		//		codeAttribute.addLocalVariableTableAttribute(this);
-		if ((codeStream.pcToSourceMap != null) && (codeStream.pcToSourceMapSize != 0)) {
-			int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
-			if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
-				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-			}
-			localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
-			localContents[localContentsOffset++] = (byte) localVariableNameIndex;
-			localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
-			int nameIndex;
-			int descriptorIndex;
-			for (int i = 0; i < codeStream.allLocalsCounter; i++) {
-				LocalVariableBinding localVariable = codeStream.locals[i];
-				for (int j = 0; j < localVariable.initializationCount; j++) {
-					int startPC = localVariable.initializationPCs[j << 1];
-					int endPC = localVariable.initializationPCs[ (j << 1) + 1];
-					if (startPC != endPC) { // only entries for non zero length
-						int currentLength;
-						if (endPC == -1) {
-							localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
-						}
-						if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
-							System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-						}
-						// now we can safely add the local entry
-						numberOfEntries++;
-						localContents[localContentsOffset++] = (byte) (startPC >> 8);
-						localContents[localContentsOffset++] = (byte) startPC;
-						int length = endPC - startPC;
-						localContents[localContentsOffset++] = (byte) (length >> 8);
-						localContents[localContentsOffset++] = (byte) length;
-						nameIndex = constantPool.literalIndex(localVariable.name);
-						localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-						localContents[localContentsOffset++] = (byte) nameIndex;
-						descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
-						localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
-						localContents[localContentsOffset++] = (byte) descriptorIndex;
-						int resolvedPosition = localVariable.resolvedPosition;
-						localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
-						localContents[localContentsOffset++] = (byte) resolvedPosition;
-					}
-				}
-			}
-			int value = numberOfEntries * 10 + 2;
-			localVariableTableOffset += 2;
-			localContents[localVariableTableOffset++] = (byte) (value >> 24);
-			localContents[localVariableTableOffset++] = (byte) (value >> 16);
-			localContents[localVariableTableOffset++] = (byte) (value >> 8);
-			localContents[localVariableTableOffset++] = (byte) value;
-			localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
-			localContents[localVariableTableOffset] = (byte) numberOfEntries;
-			attributeNumber++;
-		}
-	}
-	// update the number of attributes
-	// ensure first that there is enough space available inside the contents array
-	if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
-	localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
-	// update the attribute length
-	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
-	localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
-	localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
-	localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
-	localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
-	contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- * @param exceptionHandler int[]
- * @param startIndexes int[]
- */
-public void completeCodeAttributeForClinit(int codeAttributeOffset, int[] exceptionHandler, int[] startLineIndexes) {
-	// reinitialize the contents with the byte modified by the code stream
-	byte[] localContents = contents = codeStream.bCodeStream;
-	int localContentsOffset = codeStream.classFileOffset;
-	// codeAttributeOffset is the position inside contents byte array before we started to write
-	// any information about the codeAttribute
-	// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
-	// to get the right position, 6 for the max_stack etc...
-	int contentsLength;
-	int code_length = codeStream.position;
-	if (code_length > 65535) {
-		codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration.scope.referenceType());
-	}
-	if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	int max_stack = codeStream.stackMax;
-	localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
-	localContents[codeAttributeOffset + 7] = (byte) max_stack;
-	int max_locals = codeStream.maxLocals;
-	localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
-	localContents[codeAttributeOffset + 9] = (byte) max_locals;
-	localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
-	localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
-	localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
-	localContents[codeAttributeOffset + 13] = (byte) code_length;
-
-	// write the exception table
-	localContents[localContentsOffset++] = 0;
-	localContents[localContentsOffset++] = 1;
-	int start = exceptionHandler[0];
-	localContents[localContentsOffset++] = (byte) (start >> 8);
-	localContents[localContentsOffset++] = (byte) start;
-	int end = exceptionHandler[1];
-	localContents[localContentsOffset++] = (byte) (end >> 8);
-	localContents[localContentsOffset++] = (byte) end;
-	int handlerPC = exceptionHandler[2];
-	localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
-	localContents[localContentsOffset++] = (byte) handlerPC;
-	int nameIndex = constantPool.literalIndexForJavaLangException();
-	localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-	localContents[localContentsOffset++] = (byte) nameIndex;
-	
-	// debug attributes
-	int codeAttributeAttributeOffset = localContentsOffset;
-	int attributeNumber = 0; // leave two bytes for the attribute_length
-	localContentsOffset += 2; // first we handle the linenumber attribute
-
-	// first we handle the linenumber attribute
-	if (codeStream.generateLineNumberAttributes) {
-		/* Create and add the line number attribute (used for debugging) 
-		    * Build the pairs of:
-		    * (bytecodePC lineNumber)
-		    * according to the table of start line indexes and the pcToSourceMap table
-		    * contained into the codestream
-		    */
-		int index = 0, max = startLineIndexes.length;
-		int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
-		localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
-		localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 6;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 1;
-		// first entry at pc = 0
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = (byte) (problemLine >> 8);
-		localContents[localContentsOffset++] = (byte) problemLine;
-		// now we change the size of the line number attribute
-		attributeNumber++;
-	}
-
-	// then we do the local variable attribute
-	if (codeStream.generateLocalVariableTableAttributes) {
-		int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
-		if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
-			System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-		}
-		localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
-		localContents[localContentsOffset++] = (byte) localVariableNameIndex;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 2;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 0;
-		attributeNumber++;
-	}
-	
-	// update the number of attributes
-	// ensure first that there is enough space available inside the contents array
-	if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
-	localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
-	// update the attribute length
-	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
-	localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
-	localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
-	localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
-	localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
-	contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- * @param exceptionHandler int[] 
- */
-public void completeCodeAttributeForProblemMethod(AbstractMethodDeclaration method, MethodBinding binding, int codeAttributeOffset, int[] exceptionHandler, int[] startLineIndexes) {
-	// reinitialize the localContents with the byte modified by the code stream
-	byte[] localContents = contents = codeStream.bCodeStream;
-	int localContentsOffset = codeStream.classFileOffset;
-	// codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
-	int max_stack = codeStream.stackMax;
-	localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
-	localContents[codeAttributeOffset + 7] = (byte) max_stack;
-	int max_locals = codeStream.maxLocals;
-	localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
-	localContents[codeAttributeOffset + 9] = (byte) max_locals;
-	int code_length = codeStream.position;
-	localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
-	localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
-	localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
-	localContents[codeAttributeOffset + 13] = (byte) code_length;
-	// write the exception table
-	int contentsLength;
-	if (localContentsOffset + 50 >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	localContents[localContentsOffset++] = 0;
-	localContents[localContentsOffset++] = 1;
-	int start = exceptionHandler[0];
-	localContents[localContentsOffset++] = (byte) (start >> 8);
-	localContents[localContentsOffset++] = (byte) start;
-	int end = exceptionHandler[1];
-	localContents[localContentsOffset++] = (byte) (end >> 8);
-	localContents[localContentsOffset++] = (byte) end;
-	int handlerPC = exceptionHandler[2];
-	localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
-	localContents[localContentsOffset++] = (byte) handlerPC;
-	int nameIndex = constantPool.literalIndexForJavaLangException();
-	localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-	localContents[localContentsOffset++] = (byte) nameIndex; // debug attributes
-	int codeAttributeAttributeOffset = localContentsOffset;
-	int attributeNumber = 0; // leave two bytes for the attribute_length
-	localContentsOffset += 2; // first we handle the linenumber attribute
-
-	if (codeStream.generateLineNumberAttributes) {
-		/* Create and add the line number attribute (used for debugging) 
-		    * Build the pairs of:
-		    * (bytecodePC lineNumber)
-		    * according to the table of start line indexes and the pcToSourceMap table
-		    * contained into the codestream
-		    */
-		int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
-		localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
-		localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 6;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 1;
-		if (problemLine == 0) {
-			problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
-		}
-		// first entry at pc = 0
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = 0;
-		localContents[localContentsOffset++] = (byte) (problemLine >> 8);
-		localContents[localContentsOffset++] = (byte) problemLine;
-		// now we change the size of the line number attribute
-		attributeNumber++;
-	}
-
-	// then we do the local variable attribute
-	if (codeStream.generateLocalVariableTableAttributes) {
-		// compute the resolved position for the arguments of the method
-		int argSize;
-		int localVariableTableOffset = localContentsOffset;
-		int numberOfEntries = 0;
-		//		codeAttribute.addLocalVariableTableAttribute(this);
-		int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
-		if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
-			System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-		}
-		localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
-		localContents[localContentsOffset++] = (byte) localVariableNameIndex;
-		localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
-		int descriptorIndex;
-		if (!codeStream.methodDeclaration.isStatic()) {
-			numberOfEntries++;
-			if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
-				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-			}
-			localContents[localContentsOffset++] = 0;
-			localContents[localContentsOffset++] = 0;
-			localContents[localContentsOffset++] = (byte) (code_length >> 8);
-			localContents[localContentsOffset++] = (byte) code_length;
-			nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
-			localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-			localContents[localContentsOffset++] = (byte) nameIndex;
-			descriptorIndex = constantPool.literalIndex(codeStream.methodDeclaration.binding.declaringClass.signature());
-			localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
-			localContents[localContentsOffset++] = (byte) descriptorIndex;
-			// the resolved position for this is always 0
-			localContents[localContentsOffset++] = 0;
-			localContents[localContentsOffset++] = 0;
-		}
-		if (binding.isConstructor()) {
-			ReferenceBinding declaringClass = binding.declaringClass;
-			if (declaringClass.isNestedType()) {
-				NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
-				argSize = methodDeclaringClass.syntheticArgumentsOffset;
-				SyntheticArgumentBinding[] syntheticArguments;
-				if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
-					for (int i = 0, max = syntheticArguments.length; i < max; i++) {
-						LocalVariableBinding localVariable = syntheticArguments[i];
-						int currentLength;
-						if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
-							System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-						}
-						// now we can safely add the local entry
-						numberOfEntries++;
-						localContents[localContentsOffset++] = 0;
-						localContents[localContentsOffset++] = 0;
-						localContents[localContentsOffset++] = (byte) (code_length >> 8);
-						localContents[localContentsOffset++] = (byte) code_length;
-						nameIndex = constantPool.literalIndex(localVariable.name);
-						localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-						localContents[localContentsOffset++] = (byte) nameIndex;
-						descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
-						localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
-						localContents[localContentsOffset++] = (byte) descriptorIndex;
-						int resolvedPosition = localVariable.resolvedPosition;
-						localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
-						localContents[localContentsOffset++] = (byte) resolvedPosition;
-					}
-				}
-			} else {
-				argSize = 1;
-			}
-		} else {
-			argSize = binding.isStatic() ? 0 : 1;
-		}
-		if (method.binding != null) {
-			TypeBinding[] parameters = method.binding.parameters;
-			Argument[] arguments = method.arguments;
-			if ((parameters != null) && (arguments != null)) {
-				for (int i = 0, max = parameters.length; i < max; i++) {
-					TypeBinding argumentBinding = parameters[i];
-					int currentLength;
-					if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
-						System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-					}
-					// now we can safely add the local entry
-					numberOfEntries++;
-					localContents[localContentsOffset++] = 0;
-					localContents[localContentsOffset++] = 0;
-					localContents[localContentsOffset++] = (byte) (code_length >> 8);
-					localContents[localContentsOffset++] = (byte) code_length;
-					nameIndex = constantPool.literalIndex(arguments[i].name);
-					localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
-					localContents[localContentsOffset++] = (byte) nameIndex;
-					descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
-					localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
-					localContents[localContentsOffset++] = (byte) descriptorIndex;
-					int resolvedPosition = argSize;
-					if ((argumentBinding == TypeBinding.LongBinding) || (argumentBinding == TypeBinding.DoubleBinding))
-						argSize += 2;
-					else
-						argSize++;
-					localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
-					localContents[localContentsOffset++] = (byte) resolvedPosition;
-				}
-			}
-		}
-		int value = numberOfEntries * 10 + 2;
-		localVariableTableOffset += 2;
-		localContents[localVariableTableOffset++] = (byte) (value >> 24);
-		localContents[localVariableTableOffset++] = (byte) (value >> 16);
-		localContents[localVariableTableOffset++] = (byte) (value >> 8);
-		localContents[localVariableTableOffset++] = (byte) value;
-		localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
-		localContents[localVariableTableOffset] = (byte) numberOfEntries;
-		attributeNumber++;
-	}
-
-	// update the number of attributes// ensure first that there is enough space available inside the localContents array
-	if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
-		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
-	localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
-	// update the attribute length
-	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
-	localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
-	localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
-	localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
-	localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
-	contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * That method completes the creation of the code attribute by setting
- * - the attribute_length
- * - max_stack
- * - max_locals
- * - code_length
- * - exception table
- * - and debug attributes if necessary.
- *
- * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param codeAttributeOffset <CODE>int</CODE>
- */
-public void completeCodeAttributeForSyntheticAccessMethod(SyntheticAccessMethodBinding binding, int codeAttributeOffset, int[] startLineIndexes) {
-	// reinitialize the contents with the byte modified by the code stream
-	contents = codeStream.bCodeStream;
-	int localContentsOffset = codeStream.classFileOffset;
-	// codeAttributeOffset is the position inside contents byte array before we started to write
-	// any information about the codeAttribute
-	// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
-	// to get the right position, 6 for the max_stack etc...
-	int max_stack = codeStream.stackMax;
-	contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
-	contents[codeAttributeOffset + 7] = (byte) max_stack;
-	int max_locals = codeStream.maxLocals;
-	contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
-	contents[codeAttributeOffset + 9] = (byte) max_locals;
-	int code_length = codeStream.position;
-	contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
-	contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
-	contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
-	contents[codeAttributeOffset + 13] = (byte) code_length;
-	int contentsLength;
-	if ((localContentsOffset + 40) >= (contentsLength = contents.length)) {
-		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	// there is no exception table, so we need to offset by 2 the current offset and move 
-	// on the attribute generation
-	localContentsOffset += 2;
-	// debug attributes
-	int codeAttributeAttributeOffset = localContentsOffset;
-	int attributeNumber = 0;
-	// leave two bytes for the attribute_length
-	localContentsOffset += 2;
-
-	// first we handle the linenumber attribute
-	if (codeStream.generateLineNumberAttributes) {
-		int index = 0, max = startLineIndexes.length;
-		int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
-		contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
-		contents[localContentsOffset++] = (byte) lineNumberNameIndex;
-		int lineNumberTableOffset = localContentsOffset;
-		localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
-		// Seems like do would be better, but this preserves the existing behavior.
-		index = searchLineNumber(startLineIndexes, binding.sourceStart);
-		contents[localContentsOffset++] = 0;
-		contents[localContentsOffset++] = 0;
-		contents[localContentsOffset++] = (byte) (index >> 8);
-		contents[localContentsOffset++] = (byte) index;
-		// now we change the size of the line number attribute
-		contents[lineNumberTableOffset++] = 0;
-		contents[lineNumberTableOffset++] = 0;
-		contents[lineNumberTableOffset++] = 0;
-		contents[lineNumberTableOffset++] = 6;
-		contents[lineNumberTableOffset++] = 0;
-		contents[lineNumberTableOffset++] = 1;
-		attributeNumber++;
-	}
-
-	// then we do the local variable attribute
-	if (codeStream.generateLocalVariableTableAttributes) {
-		int localVariableTableOffset = localContentsOffset;
-		int numberOfEntries = 0;
-		int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
-		if (localContentsOffset + 8 > (contentsLength = contents.length)) {
-			System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-		}
-		contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
-		contents[localContentsOffset++] = (byte) localVariableNameIndex;
-		localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
-		int nameIndex;
-		int descriptorIndex;
-		for (int i = 0; i < codeStream.allLocalsCounter; i++) {
-			LocalVariableBinding localVariable = codeStream.locals[i];
-			for (int j = 0; j < localVariable.initializationCount; j++) {
-				int startPC = localVariable.initializationPCs[j << 1];
-				int endPC = localVariable.initializationPCs[(j << 1) + 1];
-				if (startPC != endPC) { // only entries for non zero length
-					int currentLength;
-					if (endPC == -1) {
-						localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
-					}
-					if (localContentsOffset + 10 > (contentsLength = contents.length)) {
-						System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-					}
-					// now we can safely add the local entry
-					numberOfEntries++;
-					contents[localContentsOffset++] = (byte) (startPC >> 8);
-					contents[localContentsOffset++] = (byte) startPC;
-					int length = endPC - startPC;
-					contents[localContentsOffset++] = (byte) (length >> 8);
-					contents[localContentsOffset++] = (byte) length;
-					nameIndex = constantPool.literalIndex(localVariable.name);
-					contents[localContentsOffset++] = (byte) (nameIndex >> 8);
-					contents[localContentsOffset++] = (byte) nameIndex;
-					descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
-					contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
-					contents[localContentsOffset++] = (byte) descriptorIndex;
-					int resolvedPosition = localVariable.resolvedPosition;
-					contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
-					contents[localContentsOffset++] = (byte) resolvedPosition;
-				}
-			}
-		}
-		int value = numberOfEntries * 10 + 2;
-		localVariableTableOffset += 2;
-		contents[localVariableTableOffset++] = (byte) (value >> 24);
-		contents[localVariableTableOffset++] = (byte) (value >> 16);
-		contents[localVariableTableOffset++] = (byte) (value >> 8);
-		contents[localVariableTableOffset++] = (byte) value;
-		contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
-		contents[localVariableTableOffset] = (byte) numberOfEntries;
-		attributeNumber++;
-	}
-
-	// update the number of attributes
-	// ensure first that there is enough space available inside the contents array
-	if (codeAttributeAttributeOffset + 2 >= (contentsLength = contents.length)) {
-		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
-	contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
-
-	// update the attribute length
-	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
-	contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
-	contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
-	contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
-	contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
-	contentsOffset = localContentsOffset;
-}
-/**
- * INTERNAL USE-ONLY
- * Complete the creation of a method info by setting up the number of attributes at the right offset.
- *
- * @param methodAttributeOffset <CODE>int</CODE>
- * @param attributeNumber <CODE>int</CODE> 
- */
-public void completeMethodInfo(int methodAttributeOffset, int attributeNumber) {
-	// update the number of attributes
-	contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
-	contents[methodAttributeOffset] = (byte) attributeNumber;
-}
-/*
- * INTERNAL USE-ONLY
- * Innerclasses get their name computed as they are generated, since some may not
- * be actually outputed if sitting inside unreachable code.
- *
- * @param localType org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding
- */
-public char[] computeConstantPoolName(LocalTypeBinding localType) {
-	if (localType.constantPoolName() != null) {
-		return localType.constantPoolName();
-	}
-
-	// delegates to the outermost enclosing classfile, since it is the only one with a global vision of its innertypes.
-	if (enclosingClassFile != null) {
-		return this.outerMostEnclosingClassFile().computeConstantPoolName(localType);
-	}
-
-	if (nameUsage == null) {
-		nameUsage = new CharArrayCache();
-	}
-	if (localType.isMemberType()) { // catches member types of local types
-		return CharOperation.concat(
-			localType.enclosingType().constantPoolName(),
-			localType.sourceName,
-			'$');
-	} else {
-		char[][] compoundName =  (char[][]) referenceBinding.compoundName.clone();
-		int last = compoundName.length - 1;
-		StringBuffer nameBuffer = new StringBuffer().append(compoundName[last]);
-		// retrieve the number of use of the combination
-		char[] simpleName = localType.sourceName;
-		//if (simpleName == null) simpleName = new char[]{}; // for anonymous
-		int nameCount = nameUsage.get(simpleName); // -1 if not found
-		nameCount =  nameCount == -1 ? 1 : nameCount + 1;
-		nameBuffer.append('$').append(nameCount);
-		nameUsage.put(simpleName, nameCount);
-		if (!localType.isAnonymousType()) { // named local type
-			nameBuffer.append('$').append(simpleName);
-		}
-		compoundName[last] = nameBuffer.toString().toCharArray();
-		return CharOperation.concatWith(compoundName, '/');
-	}
-}
-/**
- * INTERNAL USE-ONLY
- * Request the creation of a ClassFile compatible representation of a problematic type
- *
- * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
- * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
- */
-public static void createProblemType(TypeDeclaration typeDeclaration, CompilationResult unitResult) {
-	SourceTypeBinding typeBinding = typeDeclaration.binding;
-	ClassFile classFile = new ClassFile(typeBinding, null, true);
-
-	// inner attributes
-	if (typeBinding.isMemberType())
-		classFile.recordEnclosingTypeAttributes(typeBinding);
-
-	// add its fields
-	FieldBinding[] fields = typeBinding.fields;
-	if ((fields != null) && (fields != NoFields)) {
-		for (int i = 0, max = fields.length; i < max; i++) {
-			if (fields[i].constant == null) {
-				FieldReference.getConstantFor(fields[i], false, null, 0);
-			}
-		}
-		classFile.addFieldInfos();
-	} else {
-		// we have to set the number of fields to be equals to 0
-		classFile.contents[classFile.contentsOffset++] = 0;
-		classFile.contents[classFile.contentsOffset++] = 0;
-	}
-	// leave some space for the methodCount
-	classFile.setForMethodInfos();
-	// add its user defined methods
-	MethodBinding[] methods = typeBinding.methods;
-	AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
-	int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
-	int problemsLength;
-	IProblem[] problems = unitResult.getProblems();
-	if (problems == null) {
-		problems = new IProblem[0];
-	}
-	IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
-	System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
-	if (methods != null) {
-		if (typeBinding.isInterface()) {
-			// we cannot create problem methods for an interface. So we have to generate a clinit
-			// which should contain all the problem
-			classFile.addProblemClinit(problemsCopy);
-			for (int i = 0, max = methods.length; i < max; i++) {
-				MethodBinding methodBinding;
-				if ((methodBinding = methods[i]) != null) {
-					// find the corresponding method declaration
-					for (int j = 0; j < maxMethodDecl; j++) {
-						if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
-							if (!methodBinding.isConstructor()) {
-								classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
-							}
-							break;
-						}
-					}
-				}
-			}			
-		} else {
-			for (int i = 0, max = methods.length; i < max; i++) {
-				MethodBinding methodBinding;
-				if ((methodBinding = methods[i]) != null) {
-					// find the corresponding method declaration
-					for (int j = 0; j < maxMethodDecl; j++) {
-						if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
-							AbstractMethodDeclaration methodDecl;
-							if ((methodDecl = methodDeclarations[j]).isConstructor()) {
-								classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
-							} else {
-								classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
-							}
-							break;
-						}
-					}
-				}
-			}
-		}
-		// add abstract methods
-		classFile.addDefaultAbstractMethods();
-	}
-	// propagate generation of (problem) member types
-	if (typeDeclaration.memberTypes != null) {
-		CompilationResult result = typeDeclaration.scope.referenceCompilationUnit().compilationResult;
-		for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
-			TypeDeclaration memberType = typeDeclaration.memberTypes[i];
-			if (memberType.binding != null) {
-				classFile.recordNestedMemberAttribute(memberType.binding);
-				ClassFile.createProblemType(memberType, unitResult);
-			}
-		}
-	}
-	classFile.addAttributes();
-	unitResult.record(typeBinding.constantPoolName(), classFile);
-}
-/**
- * INTERNAL USE-ONLY
- * This methods returns a char[] representing the file name of the receiver
- *
- * @return char[]
- */
-public char[] fileName() {
-	return constantPool.UTF8Cache.returnKeyFor(1);
-}
-/**
- * INTERNAL USE-ONLY
- * That method generates the header of a code attribute.
- * - the index inside the constant pool for the attribute name (i.e. Code)
- * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
- */
-public void generateCodeAttributeHeader() {
-	int contentsLength;
-	if (contentsOffset + 20 >= (contentsLength = contents.length)) {
-		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	int constantValueNameIndex = constantPool.literalIndex(AttributeNamesConstants.CodeName);
-	contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
-	contents[contentsOffset++] = (byte) constantValueNameIndex;
-	// leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
-	contentsOffset += 12;
-}
-/**
- * INTERNAL USE-ONLY
- * That method generates the attributes of a code attribute.
- * They could be:
- * - an exception attribute for each try/catch found inside the method
- * - a deprecated attribute
- * - a synthetic attribute for synthetic access methods
- *
- * It returns the number of attributes created for the code attribute.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return <CODE>int</CODE>
- */
-public int generateMethodInfoAttribute(MethodBinding methodBinding) {
-	// leave two bytes for the attribute_number
-	contentsOffset += 2;
-	// now we can handle all the attribute for that method info:
-	// it could be:
-	// - a CodeAttribute
-	// - a ExceptionAttribute
-	// - a DeprecatedAttribute
-	// - a SyntheticAttribute
-
-	// Exception attribute
-	ReferenceBinding[] thrownsExceptions;
-	int contentsLength;
-	int attributeNumber = 0;
-	if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
-		// The method has a throw clause. So we need to add an exception attribute
-		// check that there is enough space to write all the bytes for the exception attribute
-		int length = thrownsExceptions.length;
-		if (contentsOffset + (8 + length * 2) >= (contentsLength = contents.length)) {
-			System.arraycopy(contents, 0, (contents = new byte[contentsLength + Math.max(INCREMENT_SIZE, (8 + length * 2))]), 0, contentsLength);
-		}
-		int exceptionNameIndex = constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
-		contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
-		contents[contentsOffset++] = (byte) exceptionNameIndex;
-		// The attribute length = length * 2 + 2 in case of a exception attribute
-		int attributeLength = length * 2 + 2;
-		contents[contentsOffset++] = (byte) (attributeLength >> 24);
-		contents[contentsOffset++] = (byte) (attributeLength >> 16);
-		contents[contentsOffset++] = (byte) (attributeLength >> 8);
-		contents[contentsOffset++] = (byte) attributeLength;
-		contents[contentsOffset++] = (byte) (length >> 8);
-		contents[contentsOffset++] = (byte) length;
-		for (int i = 0; i < length; i++) {
-			int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
-			contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
-			contents[contentsOffset++] = (byte) exceptionIndex;
-		}
-		attributeNumber++;
-	}
-
-	// Deprecated attribute
-	// Check that there is enough space to write the deprecated attribute
-	if (contentsOffset + 6 >= (contentsLength = contents.length)) {
-		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	if (methodBinding.isDeprecated()) {
-		int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
-		contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
-		contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
-		// the length of a deprecated attribute is equals to 0
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-
-		attributeNumber++;
-	}
-
-	// Synthetic attribute
-	// Check that there is enough space to write the deprecated attribute
-	if (contentsOffset + 6 >= (contentsLength = contents.length)) {
-		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	if (methodBinding.isSynthetic()) {
-		int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
-		contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
-		contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
-		// the length of a synthetic attribute is equals to 0
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-		contents[contentsOffset++] = 0;
-
-		attributeNumber++;
-	}
-	return attributeNumber;
-}
-/**
- * INTERNAL USE-ONLY
- * That method generates the header of a method info:
- * The header consists in:
- * - the access flags
- * - the name index of the method name inside the constant pool
- * - the descriptor index of the signature of the method inside the constant pool.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- */
-public void generateMethodInfoHeader(MethodBinding methodBinding) {
-	// check that there is enough space to write all the bytes for the method info corresponding
-	// to the @methodBinding
-	int contentsLength;
-	methodCount++; // add one more method
-	if (contentsOffset + 10 >= (contentsLength = contents.length)) {
-		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	int accessFlags = methodBinding.getAccessFlags();
-	if (methodBinding.isRequiredToClearPrivateModifier()) {
-		accessFlags &= ~AccPrivate;
-	}
-	contents[contentsOffset++] = (byte) (accessFlags >> 8);
-	contents[contentsOffset++] = (byte) accessFlags;
-	int nameIndex = constantPool.literalIndex(methodBinding.selector);
-	contents[contentsOffset++] = (byte) (nameIndex >> 8);
-	contents[contentsOffset++] = (byte) nameIndex;
-	int descriptorIndex = constantPool.literalIndex(methodBinding.signature());
-	contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
-	contents[contentsOffset++] = (byte) descriptorIndex;
-}
-/**
- * INTERNAL USE-ONLY
- * That method generates the method info header of a clinit:
- * The header consists in:
- * - the access flags (always default access + static)
- * - the name index of the method name (always <clinit>) inside the constant pool 
- * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- */
-public void generateMethodInfoHeaderForClinit() {
-	// check that there is enough space to write all the bytes for the method info corresponding
-	// to the @methodBinding
-	int contentsLength;
-	methodCount++; // add one more method
-	if (contentsOffset + 10 >= (contentsLength = contents.length)) {
-		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
-	}
-	contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
-	contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
-	int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.Clinit);
-	contents[contentsOffset++] = (byte) (nameIndex >> 8);
-	contents[contentsOffset++] = (byte) nameIndex;
-	int descriptorIndex = constantPool.literalIndex(QualifiedNamesConstants.ClinitSignature);
-	contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
-	contents[contentsOffset++] = (byte) descriptorIndex;
-	// We know that we won't get more than 1 attribute: the code attribute
-	contents[contentsOffset++] = 0;
-	contents[contentsOffset++] = 1;
-}
-/**
- * EXTERNAL API
- * Answer the actual bytes of the class file
- *
- * This method encodes the receiver structure into a byte array which is the content of the classfile.
- * Returns the byte array that represents the encoded structure of the receiver.
- *
- * @return byte[]
- */
-public byte[] getBytes() {
-	byte[] fullContents = new byte[headerOffset + contentsOffset];
-	System.arraycopy(header, 0, fullContents, 0, headerOffset);
-	System.arraycopy(contents, 0, fullContents, headerOffset, contentsOffset);
-	return fullContents;
-}
-/**
- * EXTERNAL API
- * Answer the compound name of the class file.
- * @return char[][]
- * e.g. {{java}, {util}, {Hashtable}}.
- */
-public char[][] getCompoundName() {
-	return CharOperation.splitOn('/', fileName());
-}
-/**
- * EXTERNAL API
- * Answer a smaller byte format, which is only contains some structural information.
- *
- * Those bytes are decodable with a regular class file reader, such as:
- * DietClassFileReader
- */
- 
-public byte[] getReducedBytes() {
-	return getBytes(); // might be improved
-}
-/**
- * INTERNAL USE-ONLY
- * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
- * for all inner types of the receiver.
- * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
- */
-public ClassFile outerMostEnclosingClassFile() {
-	ClassFile current = this;
-	while (current.enclosingClassFile != null)
-		current = current.enclosingClassFile;
-	return current;
-}
-/**
- * INTERNAL USE-ONLY
- * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
- * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
- *
- * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
- */
-public void recordEnclosingTypeAttributes(ReferenceBinding binding) {
-	// add all the enclosing types
-	ReferenceBinding enclosingType = referenceBinding.enclosingType();
-	int depth = 0;
-	while (enclosingType != null) {
-		depth++;
-		enclosingType = enclosingType.enclosingType();
-	}
-	enclosingType = referenceBinding;
-	ReferenceBinding enclosingTypes[];
-	if (depth >= 2) {
-		enclosingTypes = new ReferenceBinding[depth];
-		for (int i = depth - 1; i >= 0; i--) {
-			enclosingTypes[i] = enclosingType;
-			enclosingType = enclosingType.enclosingType();
-		}
-		for (int i = 0; i < depth; i++) {
-			addInnerClasses(enclosingTypes[i]);
-		}
-	} else {
-		addInnerClasses(referenceBinding);
-	}
-}
-/**
- * INTERNAL USE-ONLY
- * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
- * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
- *
- * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
- */
-public void recordNestedLocalAttribute(ReferenceBinding binding) {
-	// add all the enclosing types
-	ReferenceBinding enclosingType = referenceBinding.enclosingType();
-	int depth = 0;
-	while (enclosingType != null) {
-		depth++;
-		enclosingType = enclosingType.enclosingType();
-	}
-	enclosingType = referenceBinding;
-	ReferenceBinding enclosingTypes[];
-	if (depth >= 2) {
-		enclosingTypes = new ReferenceBinding[depth];
-		for (int i = depth - 1; i >= 0; i--) {
-			enclosingTypes[i] = enclosingType;
-			enclosingType = enclosingType.enclosingType();
-		}
-		for (int i = 0; i < depth; i++)
-			addInnerClasses(enclosingTypes[i]);
-	} else {
-		addInnerClasses(binding);
-	}
-}
-/**
- * INTERNAL USE-ONLY
- * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
- * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
- *
- * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
- */
-public void recordNestedMemberAttribute(ReferenceBinding binding) {
-	addInnerClasses(binding);
-}
-/**
- * INTERNAL USE-ONLY
- * Search the line number corresponding to a specific position
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
- */
-public static final int searchLineNumber(int[] startLineIndexes, int position) {
-	// this code is completely useless, but it is the same implementation than
-	// org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
-	// if (startLineIndexes == null)
-	//	return 1;
-	int length = startLineIndexes.length;
-	if (length == 0)
-		return 1;
-	int g = 0, d = length - 1;
-	int m = 0;
-	while (g <= d) {
-		m = (g + d) /2;
-		if (position < startLineIndexes[m]) {
-			d = m-1;
-		} else if (position > startLineIndexes[m]) {
-			g = m+1;
-		} else {
-			return m + 1;
-		}
-	}
-	if (position < startLineIndexes[m]) {
-		return m+1;
-	}
-	return m+2;
-}
-/**
- * INTERNAL USE-ONLY
- * This methods leaves the space for method counts recording.
- */
-public void setForMethodInfos() {
-	// leave some space for the methodCount
-	methodCountOffset = contentsOffset;
-	contentsOffset += 2;
-}
-/**
- * INTERNAL USE-ONLY
- * outputPath is formed like:
- *	   c:\temp\ the last character is a file separator
- * relativeFileName is formed like:
- *     java\lang\String.class
- * @param fileName java.lang.String
- * @param content byte[]
- */
-public static void writeToDisk(String outputPath, String relativeFileName, byte[] contents) throws IOException {
-	String fileName;
-	File file;
-	FileOutputStream output = new FileOutputStream(file = new File((fileName = buildAllDirectoriesInto(outputPath, relativeFileName))));
-	output.write(contents);
-	output.flush();
-	output.close();
-}
-}
+package org.eclipse.jdt.internal.compiler;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/**
+ * Represents a class file wrapper on bytes, it is aware of its actual
+ * type name.
+ *
+ * Public APIs are listed below:
+ *
+ * byte[] getBytes();
+ *		Answer the actual bytes of the class file
+ *
+ * char[][] getCompoundName();
+ * 		Answer the compound name of the class file.
+ * 		For example, {{java}, {util}, {Hashtable}}.
+ *
+ * byte[] getReducedBytes();
+ * 		Answer a smaller byte format, which is only contains some structural 
+ *      information. Those bytes are decodable with a regular class file reader, 
+ *      such as DietClassFileReader
+ */ 
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+
+
+public class ClassFile implements AttributeNamesConstants, CompilerModifiers, TypeConstants, TypeIds {
+	public SourceTypeBinding referenceBinding;
+	public ConstantPool constantPool;
+	public ClassFile enclosingClassFile; // used to generate private access methods
+	public int produceDebugAttributes;
+	public ReferenceBinding[] innerClassesBindings;
+	public int numberOfInnerClasses;
+	public byte[] header; // the header contains all the bytes till the end of the constant pool
+	public byte[] contents; // that collection contains all the remaining bytes of the .class file
+	public int headerOffset;
+	public int contentsOffset;
+	public int constantPoolOffset;
+	public int methodCountOffset;
+	public int methodCount;
+	protected boolean creatingProblemType;
+	public static final int INITIAL_CONTENTS_SIZE = 1000;
+	public static final int INITIAL_HEADER_SIZE = 1000;
+	public static final int INCREMENT_SIZE = 1000;
+	public static final int INNER_CLASSES_SIZE = 5;
+	protected CharArrayCache nameUsage;
+	public CodeStream codeStream;
+	protected int problemLine; // used to create line number attributes for problem methods
+/**
+ * INTERNAL USE-ONLY
+ * This methods creates a new instance of the receiver.
+ */
+public ClassFile() {}
+/**
+ * INTERNAL USE-ONLY
+ * This methods creates a new instance of the receiver.
+ *
+ * @param aType org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
+ * @param enclosingClassFile org.eclipse.jdt.internal.compiler.ClassFile
+ * @param creatingProblemType <CODE>boolean</CODE>
+ */
+public ClassFile(SourceTypeBinding aType, ClassFile enclosingClassFile, boolean creatingProblemType) {
+	referenceBinding = aType;
+	header = new byte[INITIAL_HEADER_SIZE];
+	// generate the magic numbers inside the header
+	header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
+	header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
+	header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
+	header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
+	if (((SourceTypeBinding) referenceBinding).scope.environment().options.targetJDK == CompilerOptions.JDK1_2) {
+		// Compatible with JDK 1.2
+		header[headerOffset++] = 0; // minorVersion = 0 means we just need to offset the current offset by 2
+		header[headerOffset++] = 0;
+		header[headerOffset++] = 0;
+		header[headerOffset++] = 46;
+	} else {
+		// Compatible with JDK 1.1
+		header[headerOffset++] = 0;
+		header[headerOffset++] = 3;
+		header[headerOffset++] = 0;
+		header[headerOffset++] = 45;
+	}
+	constantPoolOffset = headerOffset;
+	headerOffset += 2;
+	constantPool = new ConstantPool(this);
+
+	int accessFlags = aType.getAccessFlags();
+	if (aType.isProtected()) {
+		// set Acc_Public
+		accessFlags |= AccPublic;
+	}
+	// clear all bits that are illegal for a class or an interface
+	accessFlags
+		&= ~(
+			AccStrictfp
+				| AccProtected
+				| AccPrivate
+				| AccStatic
+				| AccSynchronized
+				| AccNative);
+				
+	// set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
+	accessFlags |= AccSuper;
+
+	this.enclosingClassFile = enclosingClassFile;
+	// innerclasses get their names computed at code gen time
+	if (aType.isLocalType()) {
+		((LocalTypeBinding) aType).constantPoolName(computeConstantPoolName((LocalTypeBinding) aType));
+		ReferenceBinding[] memberTypes = aType.memberTypes();
+		for (int i = 0, max = memberTypes.length; i < max; i++) {
+			((LocalTypeBinding) memberTypes[i]).constantPoolName(computeConstantPoolName((LocalTypeBinding) memberTypes[i]));
+		}
+	}
+	contents = new byte[INITIAL_CONTENTS_SIZE];
+	// now we continue to generate the bytes inside the contents array
+	contents[contentsOffset++] = (byte) (accessFlags >> 8);
+	contents[contentsOffset++] = (byte) accessFlags;
+	int classNameIndex = constantPool.literalIndex(aType);
+	contents[contentsOffset++] = (byte) (classNameIndex >> 8);
+	contents[contentsOffset++] = (byte) classNameIndex;
+	int superclassNameIndex;
+	if (aType.isInterface()) {
+		superclassNameIndex = constantPool.literalIndexForJavaLangObject();
+	} else {
+		superclassNameIndex = (aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
+	}
+	contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
+	contents[contentsOffset++] = (byte) superclassNameIndex;
+	ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
+	int interfacesCount = superInterfacesBinding.length;
+	contents[contentsOffset++] = (byte) (interfacesCount >> 8);
+	contents[contentsOffset++] = (byte) interfacesCount;
+	if (superInterfacesBinding != null) {
+		for (int i = 0; i < interfacesCount; i++) {
+			int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
+			contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
+			contents[contentsOffset++] = (byte) interfaceIndex;
+		}
+	}
+	produceDebugAttributes = ((SourceTypeBinding) referenceBinding).scope.environment().options.produceDebugAttributes;
+	innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
+	this.creatingProblemType = creatingProblemType;
+	codeStream = new CodeStream(this);
+
+	// retrieve the enclosing one guaranteed to be the one matching the propagated flow info
+	// 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
+	ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
+	if (this == outermostClassFile) {
+		codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
+	} else {
+		codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
+	}
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus method.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ */
+public void addAbstractMethod(
+	AbstractMethodDeclaration method,
+	MethodBinding methodBinding) {
+
+	// force the modifiers to be public and abstract
+	methodBinding.modifiers = AccPublic | AccAbstract;
+	
+	this.generateMethodInfoHeader(methodBinding);
+	int methodAttributeOffset = this.contentsOffset;
+	int attributeNumber = this.generateMethodInfoAttribute(methodBinding);
+	this.completeMethodInfo(methodAttributeOffset, attributeNumber);
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods generate all the attributes for the receiver.
+ * For a class they could be:
+ * - source file attribute
+ * - inner classes attribute
+ * - deprecated attribute
+ */
+public void addAttributes() {
+	// update the method count
+	contents[methodCountOffset++] = (byte) (methodCount >> 8);
+	contents[methodCountOffset] = (byte) methodCount;
+	
+	int attributeNumber = 0;
+	// leave two bytes for the number of attributes and store the current offset
+	int attributeOffset = contentsOffset;
+	contentsOffset += 2;
+	int contentsLength;
+
+	// source attribute
+	if ((produceDebugAttributes & CompilerOptions.Source) != 0) {
+		String fullFileName = new String(referenceBinding.scope.referenceCompilationUnit().getFileName());
+		fullFileName = fullFileName.replace('\\', '/');
+		int lastIndex = fullFileName.lastIndexOf('/');
+		if (lastIndex != -1) {
+			fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
+		}
+		// check that there is enough space to write all the bytes for the field info corresponding
+		// to the @fieldBinding
+		if (contentsOffset + 8 >= (contentsLength = contents.length)) {
+			System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+		}
+		int sourceAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SourceName);
+		contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
+		contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
+		// The length of a source file attribute is 2. This is a fixed-length
+		// attribute
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 2;
+		// write the source file name
+		int fileNameIndex = constantPool.literalIndex(fullFileName.toCharArray());
+		contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
+		contents[contentsOffset++] = (byte) fileNameIndex;
+		attributeNumber++;
+	}
+
+	// Deprecated attribute
+	if (referenceBinding.isDeprecated()) {
+		// check that there is enough space to write all the bytes for the field info corresponding
+		// to the @fieldBinding
+		if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+			System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+		}
+		int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+		contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+		contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+		// the length of a deprecated attribute is equals to 0
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		attributeNumber++;
+	}
+
+	// Inner class attribute
+	if (numberOfInnerClasses != 0) {
+		// Generate the inner class attribute
+		int exSize;
+		if (contentsOffset + (exSize = (8 * numberOfInnerClasses + 8)) >= (contentsLength = contents.length)) {
+			System.arraycopy(contents, 0, (contents = new byte[contentsLength + (exSize >= INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
+		}
+		// Now we now the size of the attribute and the number of entries
+		// attribute name
+		int attributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
+		contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+		contents[contentsOffset++] = (byte) attributeNameIndex;
+		int value = (numberOfInnerClasses << 3) + 2;
+		contents[contentsOffset++] = (byte) (value >> 24);
+		contents[contentsOffset++] = (byte) (value >> 16);
+		contents[contentsOffset++] = (byte) (value >> 8);
+		contents[contentsOffset++] = (byte) value;
+		contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
+		contents[contentsOffset++] = (byte) numberOfInnerClasses;
+		for (int i = 0; i < numberOfInnerClasses; i++) {
+			ReferenceBinding innerClass = innerClassesBindings[i];
+			int accessFlags = innerClass.getAccessFlags();
+			int innerClassIndex = constantPool.literalIndex(innerClass);
+			// inner class index
+			contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
+			contents[contentsOffset++] = (byte) innerClassIndex;
+			// outer class index: anonymous and local have no outer class index
+			if (innerClass.isMemberType()) {
+				// member or member of local
+				int outerClassIndex = constantPool.literalIndex(innerClass.enclosingType());
+				contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
+				contents[contentsOffset++] = (byte) outerClassIndex;
+			} else {
+				// equals to 0 if the innerClass is not a member type
+				contents[contentsOffset++] = 0;
+				contents[contentsOffset++] = 0;
+			}
+			// name index
+			if (!innerClass.isAnonymousType()) {
+				int nameIndex = constantPool.literalIndex(innerClass.sourceName());
+				contents[contentsOffset++] = (byte) (nameIndex >> 8);
+				contents[contentsOffset++] = (byte) nameIndex;
+			} else {
+				// equals to 0 if the innerClass is an anonymous type
+				contents[contentsOffset++] = 0;
+				contents[contentsOffset++] = 0;
+			}				
+			// access flag
+			if (innerClass.isAnonymousType()) {
+				accessFlags |= AccPrivate;
+			} else
+				if (innerClass.isLocalType() && !innerClass.isMemberType()) {
+					accessFlags |= AccPrivate;
+				}
+			contents[contentsOffset++] = (byte) (accessFlags >> 8);
+			contents[contentsOffset++] = (byte) accessFlags;
+		}
+		attributeNumber++;
+	}
+	// update the number of attributes
+	if (attributeOffset + 2 >= (contentsLength = contents.length)) {
+		System.arraycopy(
+			contents,
+			0,
+			(contents = new byte[contentsLength + INCREMENT_SIZE]),
+			0,
+			contentsLength);
+	}
+	contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+	contents[attributeOffset] = (byte) attributeNumber;
+
+	// resynchronize all offsets of the classfile
+	header = constantPool.poolContent;
+	headerOffset = constantPool.currentOffset;
+	int constantPoolCount = constantPool.currentIndex;
+	header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
+	header[constantPoolOffset] = (byte) constantPoolCount;
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods generate all the default abstract method infos that correpond to
+ * the abstract methods inherited from superinterfaces.
+ */
+public void addDefaultAbstractMethods() { // default abstract methods
+	MethodBinding[] defaultAbstractMethods = referenceBinding.getDefaultAbstractMethods();
+	for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
+		generateMethodInfoHeader(defaultAbstractMethods[i]);
+		int methodAttributeOffset = contentsOffset;
+		int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
+		completeMethodInfo(methodAttributeOffset, attributeNumber);
+	}
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods generates the bytes for the field binding passed like a parameter
+ * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
+ */
+public void addFieldInfo(FieldBinding fieldBinding) {
+	int attributeNumber = 0;
+	// check that there is enough space to write all the bytes for the field info corresponding
+	// to the @fieldBinding
+	int contentsLength;
+	if (contentsOffset + 30 >= (contentsLength = contents.length)) {
+		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	// Generate two attribute: constantValueAttribute and SyntheticAttribute
+	// Now we can generate all entries into the byte array
+	// First the accessFlags
+	int accessFlags = fieldBinding.getAccessFlags();
+	contents[contentsOffset++] = (byte) (accessFlags >> 8);
+	contents[contentsOffset++] = (byte) accessFlags;
+	// Then the nameIndex
+	int nameIndex = constantPool.literalIndex(fieldBinding.name);
+	contents[contentsOffset++] = (byte) (nameIndex >> 8);
+	contents[contentsOffset++] = (byte) nameIndex;
+	// Then the descriptorIndex
+	int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
+	contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+	contents[contentsOffset++] = (byte) descriptorIndex;
+	// leave some space for the number of attributes
+	int fieldAttributeOffset = contentsOffset;
+	contentsOffset += 2;
+	// 4.7.2 only static constant fields get a ConstantAttribute
+	if (fieldBinding.isStatic() 
+		&& fieldBinding.constant != Constant.NotAConstant 
+		&& fieldBinding.constant.typeID() != T_null) {
+		// Now we generate the constant attribute corresponding to the fieldBinding
+		int constantValueNameIndex = constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
+		contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
+		contents[contentsOffset++] = (byte) constantValueNameIndex;
+		// The attribute length = 2 in case of a constantValue attribute
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 2;
+		attributeNumber++;
+		// Need to add the constant_value_index
+		switch (fieldBinding.constant.typeID()) {
+			case T_boolean :
+				int booleanValueIndex = constantPool.literalIndex(fieldBinding.constant.booleanValue() ? 1 : 0);
+				contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
+				contents[contentsOffset++] = (byte) booleanValueIndex;
+				break;
+			case T_byte :
+			case T_char :
+			case T_int :
+			case T_short :
+				int integerValueIndex = constantPool.literalIndex(fieldBinding.constant.intValue());
+				contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+				contents[contentsOffset++] = (byte) integerValueIndex;
+				break;
+			case T_float :
+				int floatValueIndex = constantPool.literalIndex(fieldBinding.constant.floatValue());
+				contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
+				contents[contentsOffset++] = (byte) floatValueIndex;
+				break;
+			case T_double :
+				int doubleValueIndex = constantPool.literalIndex(fieldBinding.constant.doubleValue());
+				contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
+				contents[contentsOffset++] = (byte) doubleValueIndex;
+				break;
+			case T_long :
+				int longValueIndex = constantPool.literalIndex(fieldBinding.constant.longValue());
+				contents[contentsOffset++] = (byte) (longValueIndex >> 8);
+				contents[contentsOffset++] = (byte) longValueIndex;
+				break;
+			case T_String :
+				int stringValueIndex = constantPool.literalIndex(((StringConstant) fieldBinding.constant).stringValue());
+				if (stringValueIndex == -1) {
+					if (!creatingProblemType) {
+						// report an error and abort: will lead to a problem type classfile creation
+						TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+						FieldDeclaration[] fieldDecls = typeDeclaration.fields;
+						for (int i = 0, max = fieldDecls.length; i < max; i++) {
+							if (fieldDecls[i].binding == fieldBinding) {
+								// problem should abort
+								typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(fieldDecls[i]);
+							}
+						}
+					} else {
+						// already inside a problem type creation : no constant for this field
+						contentsOffset = fieldAttributeOffset + 2; // +2 is necessary to keep the two byte space for the attribute number
+						attributeNumber--;
+					}
+				} else {
+					contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
+					contents[contentsOffset++] = (byte) stringValueIndex;
+				}
+		}
+	}
+	if (fieldBinding.isSynthetic()) {
+		int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+		contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+		contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+		// the length of a synthetic attribute is equals to 0
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		attributeNumber++;
+	}
+	if (fieldBinding.isDeprecated()) {
+		int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+		contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+		contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+		// the length of a deprecated attribute is equals to 0
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		attributeNumber++;
+	}
+	contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
+	contents[fieldAttributeOffset] = (byte) attributeNumber;
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods generate all the fields infos for the receiver.
+ * This includes:
+ * - a field info for each defined field of that class
+ * - a field info for each synthetic field (e.g. this$0)
+ */
+public void addFieldInfos() {
+	SourceTypeBinding currentBinding = referenceBinding;
+	FieldBinding[] syntheticFields = currentBinding.syntheticFields();
+	int fieldCount = currentBinding.fieldCount() + (syntheticFields == null ? 0 : syntheticFields.length);
+
+	// write the number of fields
+	contents[contentsOffset++] = (byte) (fieldCount >> 8);
+	contents[contentsOffset++] = (byte) fieldCount;
+
+	FieldBinding[] fieldBindings = currentBinding.fields();
+	for (int i = 0, max = fieldBindings.length; i < max; i++) {
+		addFieldInfo(fieldBindings[i]);
+	}
+	if (syntheticFields != null) {
+		for (int i = 0, max = syntheticFields.length; i < max; i++) {
+			addFieldInfo(syntheticFields[i]);
+		}
+	}
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods stores the bindings for each inner class. They will be used to know which entries
+ * have to be generated for the inner classes attributes.
+ * @param referenceBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding 
+ */
+public void addInnerClasses(ReferenceBinding referenceBinding) {
+	// check first if that reference binding is there
+	for (int i = 0; i < numberOfInnerClasses; i++) {
+		if (innerClassesBindings[i] == referenceBinding)
+			return;
+	}
+	int length = innerClassesBindings.length;
+	if (numberOfInnerClasses == length) {
+		System.arraycopy(innerClassesBindings, 0, (innerClassesBindings = new ReferenceBinding[length * 2]), 0, length);
+	}
+	innerClassesBindings[numberOfInnerClasses++] = referenceBinding;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem clinit method info that correspond to a boggus method.
+ *
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ */
+public void addProblemClinit(IProblem[] problems) {
+	generateMethodInfoHeaderForClinit();
+	// leave two spaces for the number of attributes
+	contentsOffset -= 2;
+	int attributeOffset = contentsOffset;
+	contentsOffset += 2;
+	ReferenceBinding[] thrownsExceptions;
+	int attributeNumber = 0;
+	int contentsLength;
+
+	int codeAttributeOffset = contentsOffset;
+	generateCodeAttributeHeader();
+	codeStream.resetForProblemClinit(this);
+	String problemString = ""/*nonNLS*/;
+	if (problems != null) {
+		int max = problems.length;
+		StringBuffer buffer = new StringBuffer(25);
+		int count = 0;
+		for (int i = 0; i < max; i++) {
+			IProblem problem = problems[i];
+			if ((problem != null) && (problem.isError())) {
+				buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
+				count++;
+				if (problemLine == 0) {
+					problemLine = problem.getSourceLineNumber();
+				}
+				problems[i] = null;
+			}
+		} // insert the top line afterwards, once knowing how many problems we have to consider
+		if (count > 1) {
+			buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
+		} else {
+			buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
+		}
+		problemString = buffer.toString();
+	}
+
+	// return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+	int[] exceptionHandler = codeStream.generateCodeAttributeForProblemMethod(referenceBinding.scope.problemReporter().options.runtimeExceptionNameForCompileError, problemString);
+	attributeNumber++; // code attribute
+	completeCodeAttributeForClinit(
+		codeAttributeOffset,
+		exceptionHandler,
+		referenceBinding
+			.scope
+			.referenceCompilationUnit()
+			.compilationResult
+			.lineSeparatorPositions);
+	contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+	contents[attributeOffset] = (byte) attributeNumber;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus constructor.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ */
+public void addProblemConstructor(
+	AbstractMethodDeclaration method, 
+	MethodBinding methodBinding, 
+	IProblem[] problems) {
+
+	// always clear the strictfp/native/abstract bit for a problem method
+	methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
+		
+	generateMethodInfoHeader(methodBinding); 
+	// We know that we won't get more than 1 attribute: the code attribute
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 1; // Code attribute
+	int codeAttributeOffset = contentsOffset;
+	generateCodeAttributeHeader();
+	final ProblemReporter problemReporter = method.scope.problemReporter();
+	codeStream.reset(method, this);
+	String problemString = ""/*nonNLS*/;
+	if (problems != null) {
+		int max = problems.length;
+		StringBuffer buffer = new StringBuffer(25);
+		int count = 0;
+		for (int i = 0; i < max; i++) {
+			IProblem problem = problems[i];
+			if ((problem != null) && (problem.isError())) {
+				buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
+				count++;
+				if (problemLine == 0) {
+					problemLine = problem.getSourceLineNumber();
+				}
+			}
+		} // insert the top line afterwards, once knowing how many problems we have to consider
+		if (count > 1) {
+			buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
+		} else {
+			buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
+		}
+		problemString = buffer.toString();
+	}
+	
+	// return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+	int[] exceptionHandler = 
+		codeStream.generateCodeAttributeForProblemMethod(
+			problemReporter.options.runtimeExceptionNameForCompileError, 
+			problemString);
+	completeCodeAttributeForProblemMethod(
+		method,
+		methodBinding, 
+		codeAttributeOffset, 
+		exceptionHandler, 
+		((SourceTypeBinding) methodBinding.declaringClass)
+			.scope
+			.referenceCompilationUnit()
+			.compilationResult
+			.lineSeparatorPositions); 
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus constructor.
+ * Reset the position inside the contents byte array to the savedOffset.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ * @param savedOffset <CODE>int</CODE>
+ */
+public void addProblemConstructor(AbstractMethodDeclaration method, MethodBinding methodBinding,IProblem[] problems, int savedOffset) {
+	// we need to move back the contentsOffset to the value at the beginning of the method
+	contentsOffset = savedOffset;
+	methodCount--; // we need to remove the method that causes the problem
+	addProblemConstructor(method, methodBinding, problems);
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus method.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ */
+public void addProblemMethod(
+	AbstractMethodDeclaration method, 
+	MethodBinding methodBinding, 
+	IProblem[] problems) {
+	if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
+		method.abort(AbstractMethodDeclaration.AbortType);
+	}	
+	// always clear the strictfp/native/abstract bit for a problem method
+	methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
+	
+	generateMethodInfoHeader(methodBinding);
+	// leave two spaces for the number of attributes
+	int attributeOffset = contentsOffset;
+	contentsOffset += 2;
+	ReferenceBinding[] thrownsExceptions;
+	int attributeNumber = 0;
+	int contentsLength;
+	
+	if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
+		// The method has a throw clause. So we need to add an exception attribute
+		// check that there is enough space to write all the bytes for the exception attribute
+		int length = thrownsExceptions.length;
+		if (contentsOffset + (8 + length * 2) >= (contentsLength = contents.length)) {
+			System.arraycopy(contents, 0, (contents = new byte[contentsLength + Math.max(INCREMENT_SIZE, (8 + length * 2))]), 0, contentsLength);
+		}
+		int exceptionNameIndex = constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
+		contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
+		contents[contentsOffset++] = (byte) exceptionNameIndex;
+		// The attribute length = length * 2 + 2 in case of a exception attribute
+		int attributeLength = length * 2 + 2;
+		contents[contentsOffset++] = (byte) (attributeLength >> 24);
+		contents[contentsOffset++] = (byte) (attributeLength >> 16);
+		contents[contentsOffset++] = (byte) (attributeLength >> 8);
+		contents[contentsOffset++] = (byte) attributeLength;
+		contents[contentsOffset++] = (byte) (length >> 8);
+		contents[contentsOffset++] = (byte) length;
+		for (int i = 0; i < length; i++) {
+			int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
+			contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
+			contents[contentsOffset++] = (byte) exceptionIndex;
+		}
+		attributeNumber++;
+	}
+
+	// Deprecated attribute
+	// Check that there is enough space to write the deprecated attribute
+	if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	if (methodBinding.isDeprecated()) {
+		int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+		contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+		contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+		// the length of a deprecated attribute is equals to 0
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+
+		attributeNumber++;
+	}
+	
+	int codeAttributeOffset = contentsOffset;
+	generateCodeAttributeHeader();
+	final ProblemReporter problemReporter = method.scope.problemReporter();
+	codeStream.reset(method, this);
+	String problemString = ""/*nonNLS*/;
+	if (problems != null) {
+		int max = problems.length;
+		StringBuffer buffer = new StringBuffer(25);
+		int count = 0;
+		for (int i = 0; i < max; i++) {
+			IProblem problem = problems[i];
+			if ((problem != null)
+				&& (problem.isError())
+				&& (problem.getSourceStart() >= method.declarationSourceStart)
+				&& (problem.getSourceEnd() <= method.declarationSourceEnd)) {
+				buffer.append("\t"/*nonNLS*/ + problem.getMessage() + "\n"/*nonNLS*/);
+				count++;
+				if (problemLine == 0) {
+					problemLine = problem.getSourceLineNumber();
+				}
+				problems[i] = null;
+			}
+		} // insert the top line afterwards, once knowing how many problems we have to consider
+		if (count > 1) {
+			buffer.insert(0, Util.bind("compilation.unresolvedProblems"/*nonNLS*/));
+		} else {
+			buffer.insert(0, Util.bind("compilation.unresolvedProblem"/*nonNLS*/));
+		}
+		problemString = buffer.toString();
+	}
+
+	// return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+	int[] exceptionHandler = 
+		codeStream.generateCodeAttributeForProblemMethod(
+			problemReporter.options.runtimeExceptionNameForCompileError, 
+			problemString);
+	attributeNumber++; // code attribute
+	completeCodeAttributeForProblemMethod(
+		method, 
+		methodBinding, 
+		codeAttributeOffset, 
+		exceptionHandler, 
+		((SourceTypeBinding) methodBinding.declaringClass)
+			.scope
+			.referenceCompilationUnit()
+			.compilationResult
+			.lineSeparatorPositions);
+	contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+	contents[attributeOffset] = (byte) attributeNumber;	
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a boggus method.
+ * Reset the position inside the contents byte array to the savedOffset.
+ *
+ * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+ * @param problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ * @param savedOffset <CODE>int</CODE>
+ */
+public void addProblemMethod(AbstractMethodDeclaration method, MethodBinding methodBinding,IProblem[] problems, int savedOffset) {
+	// we need to move back the contentsOffset to the value at the beginning of the method
+	contentsOffset = savedOffset;
+	methodCount--; // we need to remove the method that causes the problem
+	addProblemMethod(method, methodBinding, problems);
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for all the special method infos.
+ * They are:
+ * - synthetic access methods
+ * - default abstract methods
+ */
+public void addSpecialMethods() {
+	// add all methods (default abstract methods and synthetic)
+
+	// default abstract methods
+	SourceTypeBinding currentBinding = referenceBinding;
+	MethodBinding[] defaultAbstractMethods = currentBinding.getDefaultAbstractMethods();
+	for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
+		generateMethodInfoHeader(defaultAbstractMethods[i]);
+		int methodAttributeOffset = contentsOffset;
+		int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
+		completeMethodInfo(methodAttributeOffset, attributeNumber);
+	}
+
+	// add synthetic methods infos
+	SyntheticAccessMethodBinding[] syntheticAccessMethods = currentBinding.syntheticAccessMethods();
+	if (syntheticAccessMethods != null) {
+		for (int i = 0, max = syntheticAccessMethods.length; i < max; i++) {
+			SyntheticAccessMethodBinding accessMethodBinding = syntheticAccessMethods[i];
+			switch (accessMethodBinding.accessType) {
+				case SyntheticAccessMethodBinding.FieldReadAccess :
+					// generate a method info to emulate an reading access to
+					// a private field
+					addSyntheticFieldReadAccessMethod(syntheticAccessMethods[i]);
+					break;
+				case SyntheticAccessMethodBinding.FieldWriteAccess :
+					// generate a method info to emulate an writing access to
+					// a private field
+					addSyntheticFieldWriteAccessMethod(syntheticAccessMethods[i]);
+					break;
+				case SyntheticAccessMethodBinding.MethodAccess :
+					// generate a method info to emulate an access to a private method
+					addSyntheticMethodAccessMethod(syntheticAccessMethods[i]);
+					break;
+				case SyntheticAccessMethodBinding.ConstructorAccess :
+					// generate a method info to emulate an access to a private method
+					addSyntheticConstructorAccessMethod(syntheticAccessMethods[i]);
+			}
+		}
+	}
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a synthetic method that
+ * generate an access to a private constructor.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public void addSyntheticConstructorAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+	generateMethodInfoHeader(methodBinding);
+	// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 2;	
+	// Code attribute
+	int codeAttributeOffset = contentsOffset;
+	generateCodeAttributeHeader();
+	codeStream.init(this);
+	codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
+	completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
+	// add the synthetic attribute
+	int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+	contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+	contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+	// the length of a synthetic attribute is equals to 0
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a synthetic method that
+ * generate an read access to a private field.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public void addSyntheticFieldReadAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+	generateMethodInfoHeader(methodBinding);
+	// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 2;
+	// Code attribute
+	int codeAttributeOffset = contentsOffset;
+	generateCodeAttributeHeader();
+	codeStream.init(this);
+	codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
+	completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
+	// add the synthetic attribute
+	int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+	contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+	contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+	// the length of a synthetic attribute is equals to 0
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;	
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a synthetic method that
+ * generate an write access to a private field.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public void addSyntheticFieldWriteAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+	generateMethodInfoHeader(methodBinding);
+	// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 2;	
+	// Code attribute
+	int codeAttributeOffset = contentsOffset;
+	generateCodeAttributeHeader();
+	codeStream.init(this);
+	codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
+	completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
+	// add the synthetic attribute
+	int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+	contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+	contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+	// the length of a synthetic attribute is equals to 0
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;	
+}
+/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem method info that correspond to a synthetic method that
+ * generate an access to a private method.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public void addSyntheticMethodAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+	generateMethodInfoHeader(methodBinding);
+	// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 2;	
+	// Code attribute
+	int codeAttributeOffset = contentsOffset;
+	generateCodeAttributeHeader();
+	codeStream.init(this);
+	codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
+	completeCodeAttributeForSyntheticAccessMethod(methodBinding, codeAttributeOffset, ((SourceTypeBinding) methodBinding.declaringClass).scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions);
+	// add the synthetic attribute
+	int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+	contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+	contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+	// the length of a synthetic attribute is equals to 0
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 0;	
+}
+/**
+ * INTERNAL USE-ONLY
+ * Build all the directories and subdirectories corresponding to the packages names
+ * into the directory specified in parameters.
+ *
+ * outputPath is formed like:
+ *	   c:\temp\ the last character is a file separator
+ * relativeFileName is formed like:
+ *     java\lang\String.class *
+ * 
+ * @param outputPath java.lang.String
+ * @param relativeFileName java.lang.String
+ * @return java.lang.String
+ */
+public static String buildAllDirectoriesInto(String outputPath, String relativeFileName) throws IOException {
+	char fileSeparatorChar = File.separatorChar;
+	String fileSeparator = File.separator;
+	File f;
+	// First we ensure that the outputPath exists
+	outputPath = outputPath.replace('/', fileSeparatorChar);
+	// To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
+	if (outputPath.endsWith(fileSeparator)) {
+		outputPath = outputPath.substring(0, outputPath.length() - 1);
+	}
+	f = new File(outputPath);
+	if (f.exists()) {
+		if (!f.isDirectory()) {
+			System.out.println(Util.bind("output.isFile"/*nonNLS*/,f.getAbsolutePath()));
+			throw new IOException(Util.bind("output.isFileNotDirectory"/*nonNLS*/));
+		}
+	} else {
+		// we have to create that directory
+		if (!f.mkdirs()) {
+			System.out.println(Util.bind("output.dirName"/*nonNLS*/,f.getAbsolutePath()));
+			throw new IOException(Util.bind("output.notValidAll"/*nonNLS*/));
+		}
+	}
+	StringBuffer outDir = new StringBuffer(outputPath);
+	outDir.append(fileSeparator);
+	StringTokenizer tokenizer = new StringTokenizer(relativeFileName, fileSeparator);
+	String token = tokenizer.nextToken();
+	while (tokenizer.hasMoreTokens()) {
+		f = new File(outDir.append(token).append(fileSeparator).toString());
+		if (f.exists()) {
+			// The outDir already exists, so we proceed the next entry
+			// System.out.println("outDir: " + outDir + " already exists.");
+		} else {
+			// Need to add the outDir
+			if (!f.mkdir()) {
+				System.out.println(Util.bind("output.fileName"/*nonNLS*/,f.getName()));
+				throw new IOException(Util.bind("output.notValid"/*nonNLS*/));
+			}
+		}
+		token = tokenizer.nextToken();
+	}
+	// token contains the last one
+	return outDir.append(token).toString();
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ */
+public void completeCodeAttribute(int codeAttributeOffset) {
+	// reinitialize the localContents with the byte modified by the code stream
+	byte[] localContents = contents = codeStream.bCodeStream;
+	int localContentsOffset = codeStream.classFileOffset;
+	// codeAttributeOffset is the position inside localContents byte array before we started to write
+	// any information about the codeAttribute
+	// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+	// to get the right position, 6 for the max_stack etc...
+	int contentsLength;
+	int code_length = codeStream.position;
+	if (code_length > 65535) {
+		codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration);
+	}
+	if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	int max_stack = codeStream.stackMax;
+	localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+	localContents[codeAttributeOffset + 7] = (byte) max_stack;
+	int max_locals = codeStream.maxLocals;
+	localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+	localContents[codeAttributeOffset + 9] = (byte) max_locals;
+	localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+	localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+	localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+	localContents[codeAttributeOffset + 13] = (byte) code_length;
+
+	// write the exception table
+	int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+	ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+	int exSize;
+	if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2)) >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
+	}
+	// there is no exception table, so we need to offset by 2 the current offset and move 
+	// on the attribute generation
+	localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+	localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+	for (int i = 0; i < exceptionHandlersNumber; i++) {
+		ExceptionLabel exceptionHandler = exceptionHandlers[i];
+		int start = exceptionHandler.start;
+		localContents[localContentsOffset++] = (byte) (start >> 8);
+		localContents[localContentsOffset++] = (byte) start;
+		int end = exceptionHandler.end;
+		localContents[localContentsOffset++] = (byte) (end >> 8);
+		localContents[localContentsOffset++] = (byte) end;
+		int handlerPC = exceptionHandler.position;
+		localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+		localContents[localContentsOffset++] = (byte) handlerPC;
+		if (exceptionHandler.exceptionType == null) {
+			// any exception handler
+			localContents[localContentsOffset++] = 0;
+			localContents[localContentsOffset++] = 0;
+		} else {
+			int nameIndex;
+			if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
+				/* represents ClassNotFoundException, see class literal access*/
+				nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+			} else {
+				nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+			}
+			localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+			localContents[localContentsOffset++] = (byte) nameIndex;
+		}
+	}
+
+	// debug attributes
+	int codeAttributeAttributeOffset = localContentsOffset;
+	int attributeNumber = 0;
+	// leave two bytes for the attribute_length
+	localContentsOffset += 2;
+
+	// first we handle the linenumber attribute
+	if (codeStream.generateLineNumberAttributes) {
+		/* Create and add the line number attribute (used for debugging) 
+		 * Build the pairs of:
+		 * 	(bytecodePC lineNumber)
+		 * according to the table of start line indexes and the pcToSourceMap table
+		 * contained into the codestream
+		 */
+		/** OLD CODE
+				int[][] pcToSourceMapTable;
+		int previousLineNumber;
+		int[] flatTable;
+		int index;
+		int startLineIndexes[] = codeStream.methodDeclaration.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
+		int max = startLineIndexes.length;
+		*/ 
+		int[] pcToSourceMapTable;
+		if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null) && (codeStream.pcToSourceMapSize != 0)) {
+			int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+			if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+			}
+			localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+			localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+			int lineNumberTableOffset = localContentsOffset;
+			localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
+			/** OLD CODE
+			previousLineNumber = 0;
+
+			// Seems like do would be better, but this preserves the existing behavior.
+
+			flatTable = new int[code_length];
+			for (int i = codeStream.pcToSourceMapSize - 1; i >= 0; i--) {
+				// entry contains the following structure:
+				// position 1: startPC
+				// position 2: endPC
+				// position 3: sourceStart
+				// position 4: sourceEnd
+				// Compute the line number for a given source position
+				index = searchLineNumber(startLineIndexes, pcToSourceMapTable[i][2]);
+				for (int j = pcToSourceMapTable[i][0]; j < pcToSourceMapTable[i][1]; j++)
+					flatTable[j] = index;
+			}
+			previousLineNumber = -1;
+			
+			*/
+			int numberOfEntries = 0;
+			int length = codeStream.pcToSourceMapSize;
+			/** OLD CODE
+				int length = flatTable.length;
+						for (int i = 0; i < length; i++) {
+				if (flatTable[i] != previousLineNumber) {
+					previousLineNumber = flatTable[i];
+					// write the entry
+					if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
+						System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+					}
+					localContents[localContentsOffset++] = (byte) (i >> 8);
+					localContents[localContentsOffset++] = (byte) i;
+					localContents[localContentsOffset++] = (byte) (previousLineNumber >> 8);
+					localContents[localContentsOffset++] = (byte) previousLineNumber;
+					numberOfEntries++;
+				}
+			}
+			*/			
+			for (int i = 0; i < length;) {
+				// write the entry
+				if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
+					System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+				}
+				int pc = pcToSourceMapTable[i++];
+				localContents[localContentsOffset++] = (byte) (pc >> 8);
+				localContents[localContentsOffset++] = (byte) pc;
+				int lineNumber = pcToSourceMapTable[i++];
+				localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
+				localContents[localContentsOffset++] = (byte) lineNumber;
+				numberOfEntries++;
+			}
+			// now we change the size of the line number attribute
+			int lineNumberAttr_length = numberOfEntries * 4 + 2;
+			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+			localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+			localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+			localContents[lineNumberTableOffset++] = (byte) numberOfEntries;
+			attributeNumber++;
+		}
+	}
+
+
+
+	// then we do the local variable attribute
+	if (codeStream.generateLocalVariableTableAttributes) {
+		int localVariableTableOffset = localContentsOffset;
+		int numberOfEntries = 0;
+		int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+		if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+			System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+		}
+		localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+		localContents[localContentsOffset++] = (byte) localVariableNameIndex;
+		localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
+		int nameIndex;
+		int descriptorIndex;
+		if (!codeStream.methodDeclaration.isStatic()) {
+			numberOfEntries++;
+			if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+			}
+			localContentsOffset += 2; // the startPC for this is always 0
+			localContents[localContentsOffset++] = (byte) (code_length >> 8);
+			localContents[localContentsOffset++] = (byte) code_length;
+			nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+			localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+			localContents[localContentsOffset++] = (byte) nameIndex;
+			descriptorIndex = constantPool.literalIndex(codeStream.methodDeclaration.binding.declaringClass.signature());
+			localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+			localContents[localContentsOffset++] = (byte) descriptorIndex;
+			localContentsOffset += 2; // the resolved position for this is always 0
+		}
+		for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+			LocalVariableBinding localVariable = codeStream.locals[i];
+			for (int j = 0; j < localVariable.initializationCount; j++) {
+				int startPC = localVariable.initializationPCs[j << 1];
+				int endPC = localVariable.initializationPCs[(j << 1) + 1];
+				if (startPC != endPC) { // only entries for non zero length
+					int currentLength;
+					if (endPC == -1) {
+						localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
+					}
+					if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+						System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+					}
+					// now we can safely add the local entry
+					numberOfEntries++;
+					localContents[localContentsOffset++] = (byte) (startPC >> 8);
+					localContents[localContentsOffset++] = (byte) startPC;
+					int length = endPC - startPC;
+					localContents[localContentsOffset++] = (byte) (length >> 8);
+					localContents[localContentsOffset++] = (byte) length;
+					nameIndex = constantPool.literalIndex(localVariable.name);
+					localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					localContents[localContentsOffset++] = (byte) nameIndex;
+					descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+					localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+					localContents[localContentsOffset++] = (byte) descriptorIndex;
+					int resolvedPosition = localVariable.resolvedPosition;
+					localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+					localContents[localContentsOffset++] = (byte) resolvedPosition;
+				}
+			}
+		}
+		int value = numberOfEntries * 10 + 2;
+		localVariableTableOffset += 2;
+		localContents[localVariableTableOffset++] = (byte) (value >> 24);
+		localContents[localVariableTableOffset++] = (byte) (value >> 16);
+		localContents[localVariableTableOffset++] = (byte) (value >> 8);
+		localContents[localVariableTableOffset++] = (byte) value;
+		localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+		localContents[localVariableTableOffset] = (byte) numberOfEntries;
+		attributeNumber++;
+	}
+	// update the number of attributes
+	// ensure first that there is enough space available inside the localContents array
+	if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+	localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+
+	// update the attribute length
+	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+	localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+	localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+	localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+	localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+	contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ */
+public void completeCodeAttributeForClinit(int codeAttributeOffset) {
+	// reinitialize the contents with the byte modified by the code stream
+	byte[] localContents = contents = codeStream.bCodeStream;
+	int localContentsOffset = codeStream.classFileOffset;
+	// codeAttributeOffset is the position inside contents byte array before we started to write
+	// any information about the codeAttribute
+	// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+	// to get the right position, 6 for the max_stack etc...
+	int contentsLength;
+	int code_length = codeStream.position;
+	if (code_length > 65535) {
+		codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration.scope.referenceType());
+	}
+	if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	int max_stack = codeStream.stackMax;
+	localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+	localContents[codeAttributeOffset + 7] = (byte) max_stack;
+	int max_locals = codeStream.maxLocals;
+	localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+	localContents[codeAttributeOffset + 9] = (byte) max_locals;
+	localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+	localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+	localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+	localContents[codeAttributeOffset + 13] = (byte) code_length;
+
+	// write the exception table
+	int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+	ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+	int exSize;
+	if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2)) >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]), 0, contentsLength);
+	}
+	// there is no exception table, so we need to offset by 2 the current offset and move 
+	// on the attribute generation
+	localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+	localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+	for (int i = 0; i < exceptionHandlersNumber; i++) {
+		ExceptionLabel exceptionHandler = exceptionHandlers[i];
+		int start = exceptionHandler.start;
+		localContents[localContentsOffset++] = (byte) (start >> 8);
+		localContents[localContentsOffset++] = (byte) start;
+		int end = exceptionHandler.end;
+		localContents[localContentsOffset++] = (byte) (end >> 8);
+		localContents[localContentsOffset++] = (byte) end;
+		int handlerPC = exceptionHandler.position;
+		localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+		localContents[localContentsOffset++] = (byte) handlerPC;
+		if (exceptionHandler.exceptionType == null) {
+			// any exception handler
+			localContentsOffset += 2;
+		} else {
+			int nameIndex;
+			if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
+				/* represents denote ClassNotFoundException, see class literal access*/
+				nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+			} else {
+				nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+			}
+			localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+			localContents[localContentsOffset++] = (byte) nameIndex;
+		}
+	}
+
+	// debug attributes
+	int codeAttributeAttributeOffset = localContentsOffset;
+	int attributeNumber = 0;
+	// leave two bytes for the attribute_length
+	localContentsOffset += 2;
+
+	// first we handle the linenumber attribute
+	if (codeStream.generateLineNumberAttributes) {
+		/* Create and add the line number attribute (used for debugging) 
+		 * Build the pairs of:
+		 * 	(bytecodePC lineNumber)
+		 * according to the table of start line indexes and the pcToSourceMap table
+		 * contained into the codestream
+		 */
+		int[] pcToSourceMapTable;
+		if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null) && (codeStream.pcToSourceMapSize != 0)) {
+			int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+			if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+			}
+			localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+			localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+			int lineNumberTableOffset = localContentsOffset;
+			localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
+			int numberOfEntries = 0;
+			int length = codeStream.pcToSourceMapSize;
+			for (int i = 0; i < length;) {
+				// write the entry
+				if (localContentsOffset + 4 >= (contentsLength = localContents.length)) {
+					System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+				}
+				int pc = pcToSourceMapTable[i++];
+				localContents[localContentsOffset++] = (byte) (pc >> 8);
+				localContents[localContentsOffset++] = (byte) pc;
+				int lineNumber = pcToSourceMapTable[i++];
+				localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
+				localContents[localContentsOffset++] = (byte) lineNumber;
+				numberOfEntries++;
+			}
+			// now we change the size of the line number attribute
+			int lineNumberAttr_length = numberOfEntries * 4 + 2;
+			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+			localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+			localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+			localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+			localContents[lineNumberTableOffset++] = (byte) numberOfEntries;
+			attributeNumber++;
+		}
+	}
+
+
+
+	// then we do the local variable attribute
+	if (codeStream.generateLocalVariableTableAttributes) {
+		int localVariableTableOffset = localContentsOffset;
+		int numberOfEntries = 0;
+		//		codeAttribute.addLocalVariableTableAttribute(this);
+		if ((codeStream.pcToSourceMap != null) && (codeStream.pcToSourceMapSize != 0)) {
+			int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+			if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+			}
+			localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+			localContents[localContentsOffset++] = (byte) localVariableNameIndex;
+			localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
+			int nameIndex;
+			int descriptorIndex;
+			for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+				LocalVariableBinding localVariable = codeStream.locals[i];
+				for (int j = 0; j < localVariable.initializationCount; j++) {
+					int startPC = localVariable.initializationPCs[j << 1];
+					int endPC = localVariable.initializationPCs[ (j << 1) + 1];
+					if (startPC != endPC) { // only entries for non zero length
+						int currentLength;
+						if (endPC == -1) {
+							localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
+						}
+						if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+							System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+						}
+						// now we can safely add the local entry
+						numberOfEntries++;
+						localContents[localContentsOffset++] = (byte) (startPC >> 8);
+						localContents[localContentsOffset++] = (byte) startPC;
+						int length = endPC - startPC;
+						localContents[localContentsOffset++] = (byte) (length >> 8);
+						localContents[localContentsOffset++] = (byte) length;
+						nameIndex = constantPool.literalIndex(localVariable.name);
+						localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+						localContents[localContentsOffset++] = (byte) nameIndex;
+						descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+						localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+						localContents[localContentsOffset++] = (byte) descriptorIndex;
+						int resolvedPosition = localVariable.resolvedPosition;
+						localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+						localContents[localContentsOffset++] = (byte) resolvedPosition;
+					}
+				}
+			}
+			int value = numberOfEntries * 10 + 2;
+			localVariableTableOffset += 2;
+			localContents[localVariableTableOffset++] = (byte) (value >> 24);
+			localContents[localVariableTableOffset++] = (byte) (value >> 16);
+			localContents[localVariableTableOffset++] = (byte) (value >> 8);
+			localContents[localVariableTableOffset++] = (byte) value;
+			localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+			localContents[localVariableTableOffset] = (byte) numberOfEntries;
+			attributeNumber++;
+		}
+	}
+	// update the number of attributes
+	// ensure first that there is enough space available inside the contents array
+	if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+	localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+	// update the attribute length
+	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+	localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+	localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+	localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+	localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+	contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ * @param exceptionHandler int[]
+ * @param startIndexes int[]
+ */
+public void completeCodeAttributeForClinit(int codeAttributeOffset, int[] exceptionHandler, int[] startLineIndexes) {
+	// reinitialize the contents with the byte modified by the code stream
+	byte[] localContents = contents = codeStream.bCodeStream;
+	int localContentsOffset = codeStream.classFileOffset;
+	// codeAttributeOffset is the position inside contents byte array before we started to write
+	// any information about the codeAttribute
+	// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+	// to get the right position, 6 for the max_stack etc...
+	int contentsLength;
+	int code_length = codeStream.position;
+	if (code_length > 65535) {
+		codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(codeStream.methodDeclaration.scope.referenceType());
+	}
+	if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	int max_stack = codeStream.stackMax;
+	localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+	localContents[codeAttributeOffset + 7] = (byte) max_stack;
+	int max_locals = codeStream.maxLocals;
+	localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+	localContents[codeAttributeOffset + 9] = (byte) max_locals;
+	localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+	localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+	localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+	localContents[codeAttributeOffset + 13] = (byte) code_length;
+
+	// write the exception table
+	localContents[localContentsOffset++] = 0;
+	localContents[localContentsOffset++] = 1;
+	int start = exceptionHandler[0];
+	localContents[localContentsOffset++] = (byte) (start >> 8);
+	localContents[localContentsOffset++] = (byte) start;
+	int end = exceptionHandler[1];
+	localContents[localContentsOffset++] = (byte) (end >> 8);
+	localContents[localContentsOffset++] = (byte) end;
+	int handlerPC = exceptionHandler[2];
+	localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+	localContents[localContentsOffset++] = (byte) handlerPC;
+	int nameIndex = constantPool.literalIndexForJavaLangException();
+	localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+	localContents[localContentsOffset++] = (byte) nameIndex;
+	
+	// debug attributes
+	int codeAttributeAttributeOffset = localContentsOffset;
+	int attributeNumber = 0; // leave two bytes for the attribute_length
+	localContentsOffset += 2; // first we handle the linenumber attribute
+
+	// first we handle the linenumber attribute
+	if (codeStream.generateLineNumberAttributes) {
+		/* Create and add the line number attribute (used for debugging) 
+		    * Build the pairs of:
+		    * (bytecodePC lineNumber)
+		    * according to the table of start line indexes and the pcToSourceMap table
+		    * contained into the codestream
+		    */
+		int index = 0, max = startLineIndexes.length;
+		int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+		localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+		localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 6;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 1;
+		// first entry at pc = 0
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = (byte) (problemLine >> 8);
+		localContents[localContentsOffset++] = (byte) problemLine;
+		// now we change the size of the line number attribute
+		attributeNumber++;
+	}
+
+	// then we do the local variable attribute
+	if (codeStream.generateLocalVariableTableAttributes) {
+		int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+		if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+			System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+		}
+		localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+		localContents[localContentsOffset++] = (byte) localVariableNameIndex;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 2;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 0;
+		attributeNumber++;
+	}
+	
+	// update the number of attributes
+	// ensure first that there is enough space available inside the contents array
+	if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+	localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+	// update the attribute length
+	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+	localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+	localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+	localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+	localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+	contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ * @param exceptionHandler int[] 
+ */
+public void completeCodeAttributeForProblemMethod(AbstractMethodDeclaration method, MethodBinding binding, int codeAttributeOffset, int[] exceptionHandler, int[] startLineIndexes) {
+	// reinitialize the localContents with the byte modified by the code stream
+	byte[] localContents = contents = codeStream.bCodeStream;
+	int localContentsOffset = codeStream.classFileOffset;
+	// codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
+	int max_stack = codeStream.stackMax;
+	localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+	localContents[codeAttributeOffset + 7] = (byte) max_stack;
+	int max_locals = codeStream.maxLocals;
+	localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+	localContents[codeAttributeOffset + 9] = (byte) max_locals;
+	int code_length = codeStream.position;
+	localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+	localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+	localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+	localContents[codeAttributeOffset + 13] = (byte) code_length;
+	// write the exception table
+	int contentsLength;
+	if (localContentsOffset + 50 >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	localContents[localContentsOffset++] = 0;
+	localContents[localContentsOffset++] = 1;
+	int start = exceptionHandler[0];
+	localContents[localContentsOffset++] = (byte) (start >> 8);
+	localContents[localContentsOffset++] = (byte) start;
+	int end = exceptionHandler[1];
+	localContents[localContentsOffset++] = (byte) (end >> 8);
+	localContents[localContentsOffset++] = (byte) end;
+	int handlerPC = exceptionHandler[2];
+	localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+	localContents[localContentsOffset++] = (byte) handlerPC;
+	int nameIndex = constantPool.literalIndexForJavaLangException();
+	localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+	localContents[localContentsOffset++] = (byte) nameIndex; // debug attributes
+	int codeAttributeAttributeOffset = localContentsOffset;
+	int attributeNumber = 0; // leave two bytes for the attribute_length
+	localContentsOffset += 2; // first we handle the linenumber attribute
+
+	if (codeStream.generateLineNumberAttributes) {
+		/* Create and add the line number attribute (used for debugging) 
+		    * Build the pairs of:
+		    * (bytecodePC lineNumber)
+		    * according to the table of start line indexes and the pcToSourceMap table
+		    * contained into the codestream
+		    */
+		int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+		localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+		localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 6;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 1;
+		if (problemLine == 0) {
+			problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
+		}
+		// first entry at pc = 0
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = 0;
+		localContents[localContentsOffset++] = (byte) (problemLine >> 8);
+		localContents[localContentsOffset++] = (byte) problemLine;
+		// now we change the size of the line number attribute
+		attributeNumber++;
+	}
+
+	// then we do the local variable attribute
+	if (codeStream.generateLocalVariableTableAttributes) {
+		// compute the resolved position for the arguments of the method
+		int argSize;
+		int localVariableTableOffset = localContentsOffset;
+		int numberOfEntries = 0;
+		//		codeAttribute.addLocalVariableTableAttribute(this);
+		int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+		if (localContentsOffset + 8 >= (contentsLength = localContents.length)) {
+			System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+		}
+		localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+		localContents[localContentsOffset++] = (byte) localVariableNameIndex;
+		localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
+		int descriptorIndex;
+		if (!codeStream.methodDeclaration.isStatic()) {
+			numberOfEntries++;
+			if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+				System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+			}
+			localContents[localContentsOffset++] = 0;
+			localContents[localContentsOffset++] = 0;
+			localContents[localContentsOffset++] = (byte) (code_length >> 8);
+			localContents[localContentsOffset++] = (byte) code_length;
+			nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+			localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+			localContents[localContentsOffset++] = (byte) nameIndex;
+			descriptorIndex = constantPool.literalIndex(codeStream.methodDeclaration.binding.declaringClass.signature());
+			localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+			localContents[localContentsOffset++] = (byte) descriptorIndex;
+			// the resolved position for this is always 0
+			localContents[localContentsOffset++] = 0;
+			localContents[localContentsOffset++] = 0;
+		}
+		if (binding.isConstructor()) {
+			ReferenceBinding declaringClass = binding.declaringClass;
+			if (declaringClass.isNestedType()) {
+				NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
+				argSize = methodDeclaringClass.syntheticArgumentsOffset;
+				SyntheticArgumentBinding[] syntheticArguments;
+				if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
+					for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+						LocalVariableBinding localVariable = syntheticArguments[i];
+						int currentLength;
+						if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+							System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+						}
+						// now we can safely add the local entry
+						numberOfEntries++;
+						localContents[localContentsOffset++] = 0;
+						localContents[localContentsOffset++] = 0;
+						localContents[localContentsOffset++] = (byte) (code_length >> 8);
+						localContents[localContentsOffset++] = (byte) code_length;
+						nameIndex = constantPool.literalIndex(localVariable.name);
+						localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+						localContents[localContentsOffset++] = (byte) nameIndex;
+						descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+						localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+						localContents[localContentsOffset++] = (byte) descriptorIndex;
+						int resolvedPosition = localVariable.resolvedPosition;
+						localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+						localContents[localContentsOffset++] = (byte) resolvedPosition;
+					}
+				}
+			} else {
+				argSize = 1;
+			}
+		} else {
+			argSize = binding.isStatic() ? 0 : 1;
+		}
+		if (method.binding != null) {
+			TypeBinding[] parameters = method.binding.parameters;
+			Argument[] arguments = method.arguments;
+			if ((parameters != null) && (arguments != null)) {
+				for (int i = 0, max = parameters.length; i < max; i++) {
+					TypeBinding argumentBinding = parameters[i];
+					int currentLength;
+					if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+						System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+					}
+					// now we can safely add the local entry
+					numberOfEntries++;
+					localContents[localContentsOffset++] = 0;
+					localContents[localContentsOffset++] = 0;
+					localContents[localContentsOffset++] = (byte) (code_length >> 8);
+					localContents[localContentsOffset++] = (byte) code_length;
+					nameIndex = constantPool.literalIndex(arguments[i].name);
+					localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					localContents[localContentsOffset++] = (byte) nameIndex;
+					descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
+					localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+					localContents[localContentsOffset++] = (byte) descriptorIndex;
+					int resolvedPosition = argSize;
+					if ((argumentBinding == TypeBinding.LongBinding) || (argumentBinding == TypeBinding.DoubleBinding))
+						argSize += 2;
+					else
+						argSize++;
+					localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+					localContents[localContentsOffset++] = (byte) resolvedPosition;
+				}
+			}
+		}
+		int value = numberOfEntries * 10 + 2;
+		localVariableTableOffset += 2;
+		localContents[localVariableTableOffset++] = (byte) (value >> 24);
+		localContents[localVariableTableOffset++] = (byte) (value >> 16);
+		localContents[localVariableTableOffset++] = (byte) (value >> 8);
+		localContents[localVariableTableOffset++] = (byte) value;
+		localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+		localContents[localVariableTableOffset] = (byte) numberOfEntries;
+		attributeNumber++;
+	}
+
+	// update the number of attributes// ensure first that there is enough space available inside the localContents array
+	if (codeAttributeAttributeOffset + 2 >= (contentsLength = localContents.length)) {
+		System.arraycopy(contents, 0, (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+	localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+	// update the attribute length
+	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+	localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+	localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+	localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+	localContents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+	contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method completes the creation of the code attribute by setting
+ * - the attribute_length
+ * - max_stack
+ * - max_locals
+ * - code_length
+ * - exception table
+ * - and debug attributes if necessary.
+ *
+ * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ */
+public void completeCodeAttributeForSyntheticAccessMethod(SyntheticAccessMethodBinding binding, int codeAttributeOffset, int[] startLineIndexes) {
+	// reinitialize the contents with the byte modified by the code stream
+	contents = codeStream.bCodeStream;
+	int localContentsOffset = codeStream.classFileOffset;
+	// codeAttributeOffset is the position inside contents byte array before we started to write
+	// any information about the codeAttribute
+	// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+	// to get the right position, 6 for the max_stack etc...
+	int max_stack = codeStream.stackMax;
+	contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+	contents[codeAttributeOffset + 7] = (byte) max_stack;
+	int max_locals = codeStream.maxLocals;
+	contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+	contents[codeAttributeOffset + 9] = (byte) max_locals;
+	int code_length = codeStream.position;
+	contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+	contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+	contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+	contents[codeAttributeOffset + 13] = (byte) code_length;
+	int contentsLength;
+	if ((localContentsOffset + 40) >= (contentsLength = contents.length)) {
+		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	// there is no exception table, so we need to offset by 2 the current offset and move 
+	// on the attribute generation
+	localContentsOffset += 2;
+	// debug attributes
+	int codeAttributeAttributeOffset = localContentsOffset;
+	int attributeNumber = 0;
+	// leave two bytes for the attribute_length
+	localContentsOffset += 2;
+
+	// first we handle the linenumber attribute
+	if (codeStream.generateLineNumberAttributes) {
+		int index = 0, max = startLineIndexes.length;
+		int lineNumberNameIndex = constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+		contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+		contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+		int lineNumberTableOffset = localContentsOffset;
+		localContentsOffset += 6; // leave space for attribute_length and line_number_table_length
+		// Seems like do would be better, but this preserves the existing behavior.
+		index = searchLineNumber(startLineIndexes, binding.sourceStart);
+		contents[localContentsOffset++] = 0;
+		contents[localContentsOffset++] = 0;
+		contents[localContentsOffset++] = (byte) (index >> 8);
+		contents[localContentsOffset++] = (byte) index;
+		// now we change the size of the line number attribute
+		contents[lineNumberTableOffset++] = 0;
+		contents[lineNumberTableOffset++] = 0;
+		contents[lineNumberTableOffset++] = 0;
+		contents[lineNumberTableOffset++] = 6;
+		contents[lineNumberTableOffset++] = 0;
+		contents[lineNumberTableOffset++] = 1;
+		attributeNumber++;
+	}
+
+	// then we do the local variable attribute
+	if (codeStream.generateLocalVariableTableAttributes) {
+		int localVariableTableOffset = localContentsOffset;
+		int numberOfEntries = 0;
+		int localVariableNameIndex = constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+		if (localContentsOffset + 8 > (contentsLength = contents.length)) {
+			System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+		}
+		contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+		contents[localContentsOffset++] = (byte) localVariableNameIndex;
+		localContentsOffset += 6; // leave space for attribute_length and local_variable_table_length
+		int nameIndex;
+		int descriptorIndex;
+		for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+			LocalVariableBinding localVariable = codeStream.locals[i];
+			for (int j = 0; j < localVariable.initializationCount; j++) {
+				int startPC = localVariable.initializationPCs[j << 1];
+				int endPC = localVariable.initializationPCs[(j << 1) + 1];
+				if (startPC != endPC) { // only entries for non zero length
+					int currentLength;
+					if (endPC == -1) {
+						localVariable.declaringScope.problemReporter().abortDueToInternalError(Util.bind("abort.invalidAttribute"/*nonNLS*/,new String(localVariable.name)), (AstNode) localVariable.declaringScope.methodScope().referenceContext);
+					}
+					if (localContentsOffset + 10 > (contentsLength = contents.length)) {
+						System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+					}
+					// now we can safely add the local entry
+					numberOfEntries++;
+					contents[localContentsOffset++] = (byte) (startPC >> 8);
+					contents[localContentsOffset++] = (byte) startPC;
+					int length = endPC - startPC;
+					contents[localContentsOffset++] = (byte) (length >> 8);
+					contents[localContentsOffset++] = (byte) length;
+					nameIndex = constantPool.literalIndex(localVariable.name);
+					contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+					contents[localContentsOffset++] = (byte) nameIndex;
+					descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+					contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+					contents[localContentsOffset++] = (byte) descriptorIndex;
+					int resolvedPosition = localVariable.resolvedPosition;
+					contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+					contents[localContentsOffset++] = (byte) resolvedPosition;
+				}
+			}
+		}
+		int value = numberOfEntries * 10 + 2;
+		localVariableTableOffset += 2;
+		contents[localVariableTableOffset++] = (byte) (value >> 24);
+		contents[localVariableTableOffset++] = (byte) (value >> 16);
+		contents[localVariableTableOffset++] = (byte) (value >> 8);
+		contents[localVariableTableOffset++] = (byte) value;
+		contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+		contents[localVariableTableOffset] = (byte) numberOfEntries;
+		attributeNumber++;
+	}
+
+	// update the number of attributes
+	// ensure first that there is enough space available inside the contents array
+	if (codeAttributeAttributeOffset + 2 >= (contentsLength = contents.length)) {
+		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+	contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+
+	// update the attribute length
+	int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+	contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+	contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+	contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+	contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+	contentsOffset = localContentsOffset;
+}
+/**
+ * INTERNAL USE-ONLY
+ * Complete the creation of a method info by setting up the number of attributes at the right offset.
+ *
+ * @param methodAttributeOffset <CODE>int</CODE>
+ * @param attributeNumber <CODE>int</CODE> 
+ */
+public void completeMethodInfo(int methodAttributeOffset, int attributeNumber) {
+	// update the number of attributes
+	contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+	contents[methodAttributeOffset] = (byte) attributeNumber;
+}
+/*
+ * INTERNAL USE-ONLY
+ * Innerclasses get their name computed as they are generated, since some may not
+ * be actually outputed if sitting inside unreachable code.
+ *
+ * @param localType org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding
+ */
+public char[] computeConstantPoolName(LocalTypeBinding localType) {
+	if (localType.constantPoolName() != null) {
+		return localType.constantPoolName();
+	}
+
+	// delegates to the outermost enclosing classfile, since it is the only one with a global vision of its innertypes.
+	if (enclosingClassFile != null) {
+		return this.outerMostEnclosingClassFile().computeConstantPoolName(localType);
+	}
+
+	if (nameUsage == null) {
+		nameUsage = new CharArrayCache();
+	}
+	if (localType.isMemberType()) { // catches member types of local types
+		return CharOperation.concat(
+			localType.enclosingType().constantPoolName(),
+			localType.sourceName,
+			'$');
+	} else {
+		char[][] compoundName =  (char[][]) referenceBinding.compoundName.clone();
+		int last = compoundName.length - 1;
+		StringBuffer nameBuffer = new StringBuffer().append(compoundName[last]);
+		// retrieve the number of use of the combination
+		char[] simpleName = localType.sourceName;
+		//if (simpleName == null) simpleName = new char[]{}; // for anonymous
+		int nameCount = nameUsage.get(simpleName); // -1 if not found
+		nameCount =  nameCount == -1 ? 1 : nameCount + 1;
+		nameBuffer.append('$').append(nameCount);
+		nameUsage.put(simpleName, nameCount);
+		if (!localType.isAnonymousType()) { // named local type
+			nameBuffer.append('$').append(simpleName);
+		}
+		compoundName[last] = nameBuffer.toString().toCharArray();
+		return CharOperation.concatWith(compoundName, '/');
+	}
+}
+/**
+ * INTERNAL USE-ONLY
+ * Request the creation of a ClassFile compatible representation of a problematic type
+ *
+ * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
+ * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
+ */
+public static void createProblemType(TypeDeclaration typeDeclaration, CompilationResult unitResult) {
+	SourceTypeBinding typeBinding = typeDeclaration.binding;
+	ClassFile classFile = new ClassFile(typeBinding, null, true);
+
+	// inner attributes
+	if (typeBinding.isMemberType())
+		classFile.recordEnclosingTypeAttributes(typeBinding);
+
+	// add its fields
+	FieldBinding[] fields = typeBinding.fields;
+	if ((fields != null) && (fields != NoFields)) {
+		for (int i = 0, max = fields.length; i < max; i++) {
+			if (fields[i].constant == null) {
+				FieldReference.getConstantFor(fields[i], false, null, 0);
+			}
+		}
+		classFile.addFieldInfos();
+	} else {
+		// we have to set the number of fields to be equals to 0
+		classFile.contents[classFile.contentsOffset++] = 0;
+		classFile.contents[classFile.contentsOffset++] = 0;
+	}
+	// leave some space for the methodCount
+	classFile.setForMethodInfos();
+	// add its user defined methods
+	MethodBinding[] methods = typeBinding.methods;
+	AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
+	int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
+	int problemsLength;
+	IProblem[] problems = unitResult.getProblems();
+	if (problems == null) {
+		problems = new IProblem[0];
+	}
+	IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+	System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+	if (methods != null) {
+		if (typeBinding.isInterface()) {
+			// we cannot create problem methods for an interface. So we have to generate a clinit
+			// which should contain all the problem
+			classFile.addProblemClinit(problemsCopy);
+			for (int i = 0, max = methods.length; i < max; i++) {
+				MethodBinding methodBinding;
+				if ((methodBinding = methods[i]) != null) {
+					// find the corresponding method declaration
+					for (int j = 0; j < maxMethodDecl; j++) {
+						if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
+							if (!methodBinding.isConstructor()) {
+								classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
+							}
+							break;
+						}
+					}
+				}
+			}			
+		} else {
+			for (int i = 0, max = methods.length; i < max; i++) {
+				MethodBinding methodBinding;
+				if ((methodBinding = methods[i]) != null) {
+					// find the corresponding method declaration
+					for (int j = 0; j < maxMethodDecl; j++) {
+						if ((methodDeclarations[j] != null) && (methodDeclarations[j].binding == methods[i])) {
+							AbstractMethodDeclaration methodDecl;
+							if ((methodDecl = methodDeclarations[j]).isConstructor()) {
+								classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
+							} else {
+								classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
+							}
+							break;
+						}
+					}
+				}
+			}
+		}
+		// add abstract methods
+		classFile.addDefaultAbstractMethods();
+	}
+	// propagate generation of (problem) member types
+	if (typeDeclaration.memberTypes != null) {
+		CompilationResult result = typeDeclaration.scope.referenceCompilationUnit().compilationResult;
+		for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
+			TypeDeclaration memberType = typeDeclaration.memberTypes[i];
+			if (memberType.binding != null) {
+				classFile.recordNestedMemberAttribute(memberType.binding);
+				ClassFile.createProblemType(memberType, unitResult);
+			}
+		}
+	}
+	classFile.addAttributes();
+	unitResult.record(typeBinding.constantPoolName(), classFile);
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods returns a char[] representing the file name of the receiver
+ *
+ * @return char[]
+ */
+public char[] fileName() {
+	return constantPool.UTF8Cache.returnKeyFor(1);
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method generates the header of a code attribute.
+ * - the index inside the constant pool for the attribute name (i.e. Code)
+ * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
+ */
+public void generateCodeAttributeHeader() {
+	int contentsLength;
+	if (contentsOffset + 20 >= (contentsLength = contents.length)) {
+		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	int constantValueNameIndex = constantPool.literalIndex(AttributeNamesConstants.CodeName);
+	contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
+	contents[contentsOffset++] = (byte) constantValueNameIndex;
+	// leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
+	contentsOffset += 12;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method generates the attributes of a code attribute.
+ * They could be:
+ * - an exception attribute for each try/catch found inside the method
+ * - a deprecated attribute
+ * - a synthetic attribute for synthetic access methods
+ *
+ * It returns the number of attributes created for the code attribute.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+ * @return <CODE>int</CODE>
+ */
+public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+	// leave two bytes for the attribute_number
+	contentsOffset += 2;
+	// now we can handle all the attribute for that method info:
+	// it could be:
+	// - a CodeAttribute
+	// - a ExceptionAttribute
+	// - a DeprecatedAttribute
+	// - a SyntheticAttribute
+
+	// Exception attribute
+	ReferenceBinding[] thrownsExceptions;
+	int contentsLength;
+	int attributeNumber = 0;
+	if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
+		// The method has a throw clause. So we need to add an exception attribute
+		// check that there is enough space to write all the bytes for the exception attribute
+		int length = thrownsExceptions.length;
+		if (contentsOffset + (8 + length * 2) >= (contentsLength = contents.length)) {
+			System.arraycopy(contents, 0, (contents = new byte[contentsLength + Math.max(INCREMENT_SIZE, (8 + length * 2))]), 0, contentsLength);
+		}
+		int exceptionNameIndex = constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
+		contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
+		contents[contentsOffset++] = (byte) exceptionNameIndex;
+		// The attribute length = length * 2 + 2 in case of a exception attribute
+		int attributeLength = length * 2 + 2;
+		contents[contentsOffset++] = (byte) (attributeLength >> 24);
+		contents[contentsOffset++] = (byte) (attributeLength >> 16);
+		contents[contentsOffset++] = (byte) (attributeLength >> 8);
+		contents[contentsOffset++] = (byte) attributeLength;
+		contents[contentsOffset++] = (byte) (length >> 8);
+		contents[contentsOffset++] = (byte) length;
+		for (int i = 0; i < length; i++) {
+			int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
+			contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
+			contents[contentsOffset++] = (byte) exceptionIndex;
+		}
+		attributeNumber++;
+	}
+
+	// Deprecated attribute
+	// Check that there is enough space to write the deprecated attribute
+	if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	if (methodBinding.isDeprecated()) {
+		int deprecatedAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+		contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+		contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+		// the length of a deprecated attribute is equals to 0
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+
+		attributeNumber++;
+	}
+
+	// Synthetic attribute
+	// Check that there is enough space to write the deprecated attribute
+	if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	if (methodBinding.isSynthetic()) {
+		int syntheticAttributeNameIndex = constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+		contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+		contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+		// the length of a synthetic attribute is equals to 0
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+		contents[contentsOffset++] = 0;
+
+		attributeNumber++;
+	}
+	return attributeNumber;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method generates the header of a method info:
+ * The header consists in:
+ * - the access flags
+ * - the name index of the method name inside the constant pool
+ * - the descriptor index of the signature of the method inside the constant pool.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+ */
+public void generateMethodInfoHeader(MethodBinding methodBinding) {
+	// check that there is enough space to write all the bytes for the method info corresponding
+	// to the @methodBinding
+	int contentsLength;
+	methodCount++; // add one more method
+	if (contentsOffset + 10 >= (contentsLength = contents.length)) {
+		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	int accessFlags = methodBinding.getAccessFlags();
+	if (methodBinding.isRequiredToClearPrivateModifier()) {
+		accessFlags &= ~AccPrivate;
+	}
+	contents[contentsOffset++] = (byte) (accessFlags >> 8);
+	contents[contentsOffset++] = (byte) accessFlags;
+	int nameIndex = constantPool.literalIndex(methodBinding.selector);
+	contents[contentsOffset++] = (byte) (nameIndex >> 8);
+	contents[contentsOffset++] = (byte) nameIndex;
+	int descriptorIndex = constantPool.literalIndex(methodBinding.signature());
+	contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+	contents[contentsOffset++] = (byte) descriptorIndex;
+}
+/**
+ * INTERNAL USE-ONLY
+ * That method generates the method info header of a clinit:
+ * The header consists in:
+ * - the access flags (always default access + static)
+ * - the name index of the method name (always <clinit>) inside the constant pool 
+ * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+ */
+public void generateMethodInfoHeaderForClinit() {
+	// check that there is enough space to write all the bytes for the method info corresponding
+	// to the @methodBinding
+	int contentsLength;
+	methodCount++; // add one more method
+	if (contentsOffset + 10 >= (contentsLength = contents.length)) {
+		System.arraycopy(contents, 0, (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+	}
+	contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
+	contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
+	int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.Clinit);
+	contents[contentsOffset++] = (byte) (nameIndex >> 8);
+	contents[contentsOffset++] = (byte) nameIndex;
+	int descriptorIndex = constantPool.literalIndex(QualifiedNamesConstants.ClinitSignature);
+	contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+	contents[contentsOffset++] = (byte) descriptorIndex;
+	// We know that we won't get more than 1 attribute: the code attribute
+	contents[contentsOffset++] = 0;
+	contents[contentsOffset++] = 1;
+}
+/**
+ * EXTERNAL API
+ * Answer the actual bytes of the class file
+ *
+ * This method encodes the receiver structure into a byte array which is the content of the classfile.
+ * Returns the byte array that represents the encoded structure of the receiver.
+ *
+ * @return byte[]
+ */
+public byte[] getBytes() {
+	byte[] fullContents = new byte[headerOffset + contentsOffset];
+	System.arraycopy(header, 0, fullContents, 0, headerOffset);
+	System.arraycopy(contents, 0, fullContents, headerOffset, contentsOffset);
+	return fullContents;
+}
+/**
+ * EXTERNAL API
+ * Answer the compound name of the class file.
+ * @return char[][]
+ * e.g. {{java}, {util}, {Hashtable}}.
+ */
+public char[][] getCompoundName() {
+	return CharOperation.splitOn('/', fileName());
+}
+/**
+ * EXTERNAL API
+ * Answer a smaller byte format, which is only contains some structural information.
+ *
+ * Those bytes are decodable with a regular class file reader, such as:
+ * DietClassFileReader
+ */
+ 
+public byte[] getReducedBytes() {
+	return getBytes(); // might be improved
+}
+/**
+ * INTERNAL USE-ONLY
+ * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
+ * for all inner types of the receiver.
+ * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
+ */
+public ClassFile outerMostEnclosingClassFile() {
+	ClassFile current = this;
+	while (current.enclosingClassFile != null)
+		current = current.enclosingClassFile;
+	return current;
+}
+/**
+ * INTERNAL USE-ONLY
+ * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+ * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+ *
+ * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+ */
+public void recordEnclosingTypeAttributes(ReferenceBinding binding) {
+	// add all the enclosing types
+	ReferenceBinding enclosingType = referenceBinding.enclosingType();
+	int depth = 0;
+	while (enclosingType != null) {
+		depth++;
+		enclosingType = enclosingType.enclosingType();
+	}
+	enclosingType = referenceBinding;
+	ReferenceBinding enclosingTypes[];
+	if (depth >= 2) {
+		enclosingTypes = new ReferenceBinding[depth];
+		for (int i = depth - 1; i >= 0; i--) {
+			enclosingTypes[i] = enclosingType;
+			enclosingType = enclosingType.enclosingType();
+		}
+		for (int i = 0; i < depth; i++) {
+			addInnerClasses(enclosingTypes[i]);
+		}
+	} else {
+		addInnerClasses(referenceBinding);
+	}
+}
+/**
+ * INTERNAL USE-ONLY
+ * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+ * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+ *
+ * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+ */
+public void recordNestedLocalAttribute(ReferenceBinding binding) {
+	// add all the enclosing types
+	ReferenceBinding enclosingType = referenceBinding.enclosingType();
+	int depth = 0;
+	while (enclosingType != null) {
+		depth++;
+		enclosingType = enclosingType.enclosingType();
+	}
+	enclosingType = referenceBinding;
+	ReferenceBinding enclosingTypes[];
+	if (depth >= 2) {
+		enclosingTypes = new ReferenceBinding[depth];
+		for (int i = depth - 1; i >= 0; i--) {
+			enclosingTypes[i] = enclosingType;
+			enclosingType = enclosingType.enclosingType();
+		}
+		for (int i = 0; i < depth; i++)
+			addInnerClasses(enclosingTypes[i]);
+	} else {
+		addInnerClasses(binding);
+	}
+}
+/**
+ * INTERNAL USE-ONLY
+ * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+ * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+ *
+ * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+ */
+public void recordNestedMemberAttribute(ReferenceBinding binding) {
+	addInnerClasses(binding);
+}
+/**
+ * INTERNAL USE-ONLY
+ * Search the line number corresponding to a specific position
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+public static final int searchLineNumber(int[] startLineIndexes, int position) {
+	// this code is completely useless, but it is the same implementation than
+	// org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
+	// if (startLineIndexes == null)
+	//	return 1;
+	int length = startLineIndexes.length;
+	if (length == 0)
+		return 1;
+	int g = 0, d = length - 1;
+	int m = 0;
+	while (g <= d) {
+		m = (g + d) /2;
+		if (position < startLineIndexes[m]) {
+			d = m-1;
+		} else if (position > startLineIndexes[m]) {
+			g = m+1;
+		} else {
+			return m + 1;
+		}
+	}
+	if (position < startLineIndexes[m]) {
+		return m+1;
+	}
+	return m+2;
+}
+/**
+ * INTERNAL USE-ONLY
+ * This methods leaves the space for method counts recording.
+ */
+public void setForMethodInfos() {
+	// leave some space for the methodCount
+	methodCountOffset = contentsOffset;
+	contentsOffset += 2;
+}
+/**
+ * INTERNAL USE-ONLY
+ * outputPath is formed like:
+ *	   c:\temp\ the last character is a file separator
+ * relativeFileName is formed like:
+ *     java\lang\String.class
+ * @param fileName java.lang.String
+ * @param content byte[]
+ */
+public static void writeToDisk(String outputPath, String relativeFileName, byte[] contents) throws IOException {
+	String fileName;
+	File file;
+	FileOutputStream output = new FileOutputStream(file = new File((fileName = buildAllDirectoriesInto(outputPath, relativeFileName))));
+	output.write(contents);
+	output.flush();
+	output.close();
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index f7cf45e..a38d0e9 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -1,438 +1,437 @@
-package org.eclipse.jdt.internal.compiler;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.impl.*;
-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 java.io.*;
-import java.util.*;
-
-public class Compiler implements ITypeRequestor, ProblemSeverities {
-	public Parser parser;	
-	ICompilerRequestor requestor;
-	public CompilerOptions options;
-	public ProblemReporter problemReporter;
-	
-	// management of unit to be processed
-	//public CompilationUnitResult currentCompilationUnitResult;
-	CompilationUnitDeclaration[] unitsToProcess;
-	int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
-
-	// name lookup
-	public LookupEnvironment lookupEnvironment;
-
-	// ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD
-	public static final boolean DEBUG = false; 
-	public int parseThreshold = -1; // number of initial units parsed at once (-1: none)
-/**
- * Answer a new compiler using the given name environment and compiler options.
- * The environment and options will be in effect for the lifetime of the compiler.
- * When the compiler is run, compilation results are sent to the given requestor.
- *
- *  @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
- *      Environment used by the compiler in order to resolve type and package
- *      names. The name environment implements the actual connection of the compiler
- *      to the outside world (e.g. in batch mode the name environment is performing
- *      pure file accesses, reuse previous build state or connection to repositories).
- *      Note: the name environment is responsible for implementing the actual classpath
- *            rules.
- *
- *  @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
- *      Configurable part for problem handling, allowing the compiler client to
- *      specify the rules for handling problems (stop on first error or accumulate
- *      them all) and at the same time perform some actions such as opening a dialog
- *      in UI when compiling interactively.
- *      @see org.eclipse.jdt.internal.compiler.api.problem.DefaultErrorHandlingPolicies
- *      
- *  @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
- *      Component which will receive and persist all compilation results and is intended
- *      to consume them as they are produced. Typically, in a batch compiler, it is 
- *      responsible for writing out the actual .class files to the file system.
- *      @see org.eclipse.jdt.internal.compiler.api.CompilationResult
- *
- *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
- *      Factory used inside the compiler to create problem descriptors. It allows the
- *      compiler client to supply its own representation of compilation problems in
- *      order to avoid object conversions. Note that the factory is not supposed
- *      to accumulate the created problems, the compiler will gather them all and hand
- *      them back as part of the compilation unit result.
- */
-public Compiler(
-	INameEnvironment environment, 
-	IErrorHandlingPolicy policy, 
-	ConfigurableOption[] settings, 
-	ICompilerRequestor requestor, 
-	IProblemFactory problemFactory) {
-
-	// create a problem handler given a handling policy
-	this.options = new CompilerOptions(settings);
-	this.requestor = requestor;
-	this.problemReporter = 
-		new ProblemReporter(
-			policy, 
-			this.options, 
-			problemFactory);
-	this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, environment);
-	this.parser = 
-		new Parser(problemReporter, this.options.parseLiteralExpressionsAsConstants); 
-}
-/**
- * Add an additional binary type
- */
-
-public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
-	lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
-}
-/**
- * Add an additional compilation unit into the loop
- *  ->  build compilation unit declarations, their bindings and record their results.
- */
-
-public void accept(ICompilationUnit sourceUnit) {
-	// Switch the current policy and compilation result for this unit to the requested one.
-	CompilationResult unitResult = 
-		new CompilationResult(sourceUnit, totalUnits, totalUnits); 
-	try {
-		// diet parsing for large collection of unit
-		CompilationUnitDeclaration parsedUnit;
-		if (totalUnits < parseThreshold) {
-			parsedUnit = parser.parse(sourceUnit, unitResult);
-		} else {
-			parsedUnit = parser.dietParse(sourceUnit, unitResult);
-		}
-
-		if (options.verbose) {
-			System.out.println(Util.bind("compilation.request"/*nonNLS*/,new String[]{String.valueOf(totalUnits + 1),String.valueOf(totalUnits + 1),new String(sourceUnit.getFileName())})); 
-		}
-
-		// initial type binding creation
-		lookupEnvironment.buildTypeBindings(parsedUnit);
-		this.addCompilationUnit(sourceUnit, parsedUnit);
-
-		// binding resolution
-		lookupEnvironment.completeTypeBindings(parsedUnit);
-	} catch (AbortCompilationUnit e) {
-		// at this point, currentCompilationUnitResult may not be sourceUnit, but some other
-		// one requested further along to resolve sourceUnit.
-		if (unitResult.compilationUnit == sourceUnit) { // only report once
-			requestor.acceptResult(unitResult.tagAsAccepted());
-		} else {
-			throw e; // want to abort enclosing request to compile
-		}
-	}
-}
-/**
- * Add an additional source type
- */
-
-public void accept(ISourceType sourceType, PackageBinding packageBinding) {
-	problemReporter.abortDueToInternalError(Util.bind("abort.againstSourceModel "/*nonNLS*/,String.valueOf(sourceType.getName()),String.valueOf(sourceType.getFileName())));
-}
-protected void addCompilationUnit(ICompilationUnit sourceUnit, CompilationUnitDeclaration parsedUnit) {
-
-	// append the unit to the list of ones to process later on
-	int size = unitsToProcess.length;
-	if (totalUnits == size)	// when growing reposition units starting at position 0
-		System.arraycopy(unitsToProcess, 0, (unitsToProcess = new CompilationUnitDeclaration[size * 2]), 0, totalUnits);
-	unitsToProcess[totalUnits++] = parsedUnit;
-}
-/**
- * Add the initial set of compilation units into the loop
- *  ->  build compilation unit declarations, their bindings and record their results.
- */
-protected void beginToCompile(ICompilationUnit[] sourceUnits) {
-	int maxUnits = sourceUnits.length;
-	totalUnits = 0; 
-	unitsToProcess = new CompilationUnitDeclaration[maxUnits];
-
-	// Switch the current policy and compilation result for this unit to the requested one.
-	for (int i = 0; i < maxUnits; i++) {
-		CompilationUnitDeclaration parsedUnit;
-		CompilationResult unitResult = new CompilationResult(sourceUnits[i], i, maxUnits);
-		try {
-			// diet parsing for large collection of units
-			if (totalUnits < parseThreshold)
-			{	parsedUnit = parser.parse(sourceUnits[i], unitResult);}
-			else
-			{	parsedUnit = parser.dietParse(sourceUnits[i], unitResult);}
-			if (options.verbose) {
-				System.out.println(Util.bind("compilation.request"/*nonNLS*/,new String[]{String.valueOf(i+1),String.valueOf(maxUnits),new String(sourceUnits[i].getFileName())}));
-			}
-			// initial type binding creation
-			lookupEnvironment.buildTypeBindings(parsedUnit);
-			this.addCompilationUnit(sourceUnits[i], parsedUnit);
-		//} catch (AbortCompilationUnit e) {
-		//	requestor.acceptResult(unitResult.tagAsAccepted());
-		} finally {
-			sourceUnits[i] = null; // no longer hold onto the unit
-		}
-	}
-	// binding resolution
-	lookupEnvironment.completeTypeBindings();
-}
-/**
- * General API
- * -> compile each of supplied files
- * -> recompile any required types for which we have an incomplete principle structure
- */
-
-public void compile(ICompilationUnit[] sourceUnits) {
-	CompilationUnitDeclaration unit = null;
-	int i = 0;
-	try {
-		// build and record parsed units
-
-		beginToCompile(sourceUnits);
-
-		// process all units (some more could be injected in the loop by the lookup environment)
-		for (; i < totalUnits; i++) {
-			unit = unitsToProcess[i];
-			try {
-				if (options.verbose) System.out.println(Util.bind("compilation.process"/*nonNLS*/,new String[]{String.valueOf(i + 1),String.valueOf(totalUnits),new String(unitsToProcess[i].getFileName())})); 
-				process(unit, i);
-			} finally {
-				// cleanup compilation unit result
-				unit.cleanUp();
-				if (options.verbose) 
-					System.out.println(Util.bind("compilation.done"/*nonNLS*/,new String[]{String.valueOf(i + 1),String.valueOf(totalUnits),new String(unitsToProcess[i].getFileName())}));  
-			}
-			unitsToProcess[i] = null; // release reference to processed unit declaration
-			requestor.acceptResult(unit.compilationResult.tagAsAccepted());
-		}
-	} catch (AbortCompilation e) {
-		this.handleInternalException(e, unit);
-	} catch (Error e) {
-		this.handleInternalException(e, unit, null);
-		throw e; // rethrow
-	} catch (RuntimeException e) {
-		this.handleInternalException(e, unit, null);
-		throw e; // rethrow
-	} finally {
-		this.reset();
-	}
-	if (options.verbose) {
-		if (totalUnits > 1) {
-			System.out.println(Util.bind("compilation.units"/*nonNLS*/,String.valueOf(totalUnits)));
-		} else {
-			System.out.println(Util.bind("compilation.unit"/*nonNLS*/,String.valueOf(totalUnits)));
-		}
-	}
-}
-/**
- * Answer an array of descriptions for the configurable options.
- * The descriptions may be changed and passed back to a different
- * compiler.
- *
- *  @return ConfigurableOption[] - array of configurable options
- */
-public static ConfigurableOption[] getDefaultOptions(Locale locale) {
-	return new CompilerOptions().getConfigurableOptions(locale);
-}
-protected void getMethodBodies(CompilationUnitDeclaration unit, int place) {
-	//fill the methods bodies in order for the code to be generated
-	
-	if (unit.ignoreMethodBodies) {
-		unit.ignoreFurtherInvestigation = true;
-		return; // if initial diet parse did not work, no need to dig into method bodies.
-	}
-	
-	if (place < parseThreshold)
-		return; //work already done ...
-
-	//real parse of the method....
-	parser.scanner.setSourceBuffer(unit.compilationResult.compilationUnit.getContents());
-	if (unit.types != null) {
-		for (int i = unit.types.length; --i >= 0;)
-			unit.types[i].parseMethod(parser, unit);
-	}
-}
-/*
- * Compiler crash recovery in case of unexpected runtime exceptions
- */
-protected void handleInternalException(Throwable internalException, CompilationUnitDeclaration unit, CompilationResult result) {
-
-	/* dump a stack trace to the console */
-	internalException.printStackTrace(); 
-		
-	/* find a compilation result */
-	if ((unit != null)) // basing result upon the current unit if available
-		result = unit.compilationResult; // current unit being processed ?
-	if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
-		result = unitsToProcess[totalUnits - 1].compilationResult; // last unit in beginToCompile ?
-		
-	if (result != null) {
-		/* create and record a compilation problem */
-		StringWriter stringWriter = new StringWriter();
-		PrintWriter writer = new PrintWriter(stringWriter);
-		internalException.printStackTrace(writer);
-		StringBuffer buffer = stringWriter.getBuffer();
-
-		result.record(
-			problemReporter.createProblem(
-				result.getFileName(), 
-				ProblemIrritants.UnclassifiedProblem, 
-				new String[] {Util.bind("compilation.internalError"/*nonNLS*/)+"\n"/*nonNLS*/ + buffer.toString()},
-				Error, // severity
-				0, // source start
-				0, // source end
-				0)); // line number		
-
-		/* hand back the compilation result */
-		if (!result.hasBeenAccepted) {
-			requestor.acceptResult(result.tagAsAccepted());
-		}
-	}
-}
-/*
- * Compiler recovery in case of internal AbortCompilation event
- */
-protected void handleInternalException(AbortCompilation abortException, CompilationUnitDeclaration unit){
-
-	/* special treatment for SilentAbort: silently cancelling the compilation process */
-	if (abortException.isSilent){
-		if (abortException.silentException == null) {
-			return;
-		} else {
-			throw abortException.silentException;
-		}
-	}
-	
-	/* uncomment following line to see where the abort came from */
-	// abortException.printStackTrace(); 
-		
-	// Exception may tell which compilation result it is related, and which problem caused it
-	CompilationResult result = abortException.compilationResult; 
-	if ((result == null) && (unit != null)) result = unit.compilationResult; // current unit being processed ?
-	if ((result == null) && (unitsToProcess != null) && (totalUnits > 0)) result = unitsToProcess[totalUnits - 1].compilationResult; // last unit in beginToCompile ?
-	if (result != null && !result.hasBeenAccepted){
-		/* distant problem which could not be reported back there */
-		if (abortException.problemId != 0){ 
-			result.record(
-				problemReporter.createProblem(
-					result.getFileName(),
-					abortException.problemId, 
-					abortException.problemArguments, 
-					Error, // severity
-					0, // source start
-					0, // source end
-					0)); // line number
-		} else {
-			/* distant internal exception which could not be reported back there */
-			if (abortException.exception != null){
-				this.handleInternalException(abortException.exception, 	null, result);
-				return;
-			}
-		}
-		/* hand back the compilation result */
-		if (!result.hasBeenAccepted) { 
-			requestor.acceptResult(result.tagAsAccepted());
-		}
-	} else {
-		/*
-		if (abortException.problemId != 0){ 
-			IProblem problem =
-				problemReporter.createProblem(
-					"???".toCharArray(),
-					abortException.problemId, 
-					abortException.problemArguments, 
-					Error, // severity
-					0, // source start
-					0, // source end
-					0); // line number
-			System.out.println(problem.getMessage());
-		}
-		*/
-		abortException.printStackTrace();
-	}
-}
-/**
- * Process a compilation unit already parsed and build.
- */
-private void process(CompilationUnitDeclaration unit,int i) {
-
-	getMethodBodies(unit,i);
-
-	// fault in fields & methods
-	if (unit.scope != null)
-		unit.scope.faultInTypes();
-
-	// verify inherited methods
-	if (unit.scope != null)
-		unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
-
-	// type checking
-	long startTime = System.currentTimeMillis();
-	unit.resolve();
-
-	// flow analysis
-	startTime = System.currentTimeMillis();
-	unit.analyseCode();
-
-	// code generation
-	startTime = System.currentTimeMillis();
-	unit.generateCode();
-
-	// reference info
-	if (options.produceReferenceInfo && unit.scope != null)
-		unit.scope.storeDependencyInfo();
-
-	// refresh the total number of units known at this stage
-	unit.compilationResult.totalUnitsKnown = totalUnits;
-}
-public void reset(){
-	lookupEnvironment.reset();
-	parser.scanner.source = null;
-	unitsToProcess	 = null;
-}
-/**
- * Internal API used to resolve a compilation unit minimally for code assist engine
- */
-
-public CompilationUnitDeclaration resolve(ICompilationUnit sourceUnit) {
-	CompilationUnitDeclaration unit = null;
-	try {
-		// build and record parsed units
-		parseThreshold = 1; // will request a full parse
-		beginToCompile(new ICompilationUnit[] { sourceUnit });
-		// process all units (some more could be injected in the loop by the lookup environment)
-		unit = unitsToProcess[0];
-		//getMethodBodies(unit,i);
-		if (unit.scope != null) {
-			// fault in fields & methods
-			unit.scope.faultInTypes();
-			// type checking
-			unit.resolve();
-		}
-		unitsToProcess[0] = null; // release reference to processed unit declaration
-		requestor.acceptResult(unit.compilationResult.tagAsAccepted());
-		return unit;
-	} catch (AbortCompilation e) {
-		this.handleInternalException(e, unit);
-		return unit == null ? unitsToProcess[0] : unit;
-	} catch (Error e) {
-		this.handleInternalException(e, unit, null);
-		throw e; // rethrow
-	} catch (RuntimeException e) {
-		this.handleInternalException(e, unit, null);
-		throw e; // rethrow
-	} finally {
-		// No reset is performed there anymore since,
-		// within the CodeAssist (or related tools),
-		// the compiler may be called *after* a call
-		// to this resolve(...) method. And such a call
-		// needs to have a compiler with a non-empty
-		// environment.
-		// this.reset();
-	}
-}
-}
+package org.eclipse.jdt.internal.compiler;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.compiler.impl.*;
+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 java.io.*;
+import java.util.*;
+
+public class Compiler implements ITypeRequestor, ProblemSeverities {
+	public Parser parser;	
+	ICompilerRequestor requestor;
+	public CompilerOptions options;
+	public ProblemReporter problemReporter;
+	
+	// management of unit to be processed
+	//public CompilationUnitResult currentCompilationUnitResult;
+	CompilationUnitDeclaration[] unitsToProcess;
+	int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
+
+	// name lookup
+	public LookupEnvironment lookupEnvironment;
+
+	// ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD
+	public static final boolean DEBUG = false; 
+	public int parseThreshold = -1; // number of initial units parsed at once (-1: none)
+/**
+ * Answer a new compiler using the given name environment and compiler options.
+ * The environment and options will be in effect for the lifetime of the compiler.
+ * When the compiler is run, compilation results are sent to the given requestor.
+ *
+ *  @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
+ *      Environment used by the compiler in order to resolve type and package
+ *      names. The name environment implements the actual connection of the compiler
+ *      to the outside world (e.g. in batch mode the name environment is performing
+ *      pure file accesses, reuse previous build state or connection to repositories).
+ *      Note: the name environment is responsible for implementing the actual classpath
+ *            rules.
+ *
+ *  @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
+ *      Configurable part for problem handling, allowing the compiler client to
+ *      specify the rules for handling problems (stop on first error or accumulate
+ *      them all) and at the same time perform some actions such as opening a dialog
+ *      in UI when compiling interactively.
+ *      @see org.eclipse.jdt.internal.compiler.api.problem.DefaultErrorHandlingPolicies
+ *      
+ *  @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
+ *      Component which will receive and persist all compilation results and is intended
+ *      to consume them as they are produced. Typically, in a batch compiler, it is 
+ *      responsible for writing out the actual .class files to the file system.
+ *      @see org.eclipse.jdt.internal.compiler.api.CompilationResult
+ *
+ *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
+ *      Factory used inside the compiler to create problem descriptors. It allows the
+ *      compiler client to supply its own representation of compilation problems in
+ *      order to avoid object conversions. Note that the factory is not supposed
+ *      to accumulate the created problems, the compiler will gather them all and hand
+ *      them back as part of the compilation unit result.
+ */
+public Compiler(
+	INameEnvironment environment, 
+	IErrorHandlingPolicy policy, 
+	ConfigurableOption[] settings, 
+	ICompilerRequestor requestor, 
+	IProblemFactory problemFactory) {
+
+	// create a problem handler given a handling policy
+	this.options = new CompilerOptions(settings);
+	this.requestor = requestor;
+	this.problemReporter = 
+		new ProblemReporter(
+			policy, 
+			this.options, 
+			problemFactory);
+	this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, environment);
+	this.parser = 
+		new Parser(problemReporter, this.options.parseLiteralExpressionsAsConstants); 
+}
+/**
+ * Add an additional binary type
+ */
+
+public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
+	lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+}
+/**
+ * Add an additional compilation unit into the loop
+ *  ->  build compilation unit declarations, their bindings and record their results.
+ */
+
+public void accept(ICompilationUnit sourceUnit) {
+	// Switch the current policy and compilation result for this unit to the requested one.
+	CompilationResult unitResult = 
+		new CompilationResult(sourceUnit, totalUnits, totalUnits); 
+	try {
+		// diet parsing for large collection of unit
+		CompilationUnitDeclaration parsedUnit;
+		if (totalUnits < parseThreshold) {
+			parsedUnit = parser.parse(sourceUnit, unitResult);
+		} else {
+			parsedUnit = parser.dietParse(sourceUnit, unitResult);
+		}
+
+		if (options.verbose) {
+			System.out.println(Util.bind("compilation.request"/*nonNLS*/,new String[]{String.valueOf(totalUnits + 1),String.valueOf(totalUnits + 1),new String(sourceUnit.getFileName())})); 
+		}
+
+		// initial type binding creation
+		lookupEnvironment.buildTypeBindings(parsedUnit);
+		this.addCompilationUnit(sourceUnit, parsedUnit);
+
+		// binding resolution
+		lookupEnvironment.completeTypeBindings(parsedUnit);
+	} catch (AbortCompilationUnit e) {
+		// at this point, currentCompilationUnitResult may not be sourceUnit, but some other
+		// one requested further along to resolve sourceUnit.
+		if (unitResult.compilationUnit == sourceUnit) { // only report once
+			requestor.acceptResult(unitResult.tagAsAccepted());
+		} else {
+			throw e; // want to abort enclosing request to compile
+		}
+	}
+}
+/**
+ * Add an additional source type
+ */
+
+public void accept(ISourceType sourceType, PackageBinding packageBinding) {
+	problemReporter.abortDueToInternalError(Util.bind("abort.againstSourceModel "/*nonNLS*/,String.valueOf(sourceType.getName()),String.valueOf(sourceType.getFileName())));
+}
+protected void addCompilationUnit(ICompilationUnit sourceUnit, CompilationUnitDeclaration parsedUnit) {
+
+	// append the unit to the list of ones to process later on
+	int size = unitsToProcess.length;
+	if (totalUnits == size)	// when growing reposition units starting at position 0
+		System.arraycopy(unitsToProcess, 0, (unitsToProcess = new CompilationUnitDeclaration[size * 2]), 0, totalUnits);
+	unitsToProcess[totalUnits++] = parsedUnit;
+}
+/**
+ * Add the initial set of compilation units into the loop
+ *  ->  build compilation unit declarations, their bindings and record their results.
+ */
+protected void beginToCompile(ICompilationUnit[] sourceUnits) {
+	int maxUnits = sourceUnits.length;
+	totalUnits = 0; 
+	unitsToProcess = new CompilationUnitDeclaration[maxUnits];
+
+	// Switch the current policy and compilation result for this unit to the requested one.
+	for (int i = 0; i < maxUnits; i++) {
+		CompilationUnitDeclaration parsedUnit;
+		CompilationResult unitResult = new CompilationResult(sourceUnits[i], i, maxUnits);
+		try {
+			// diet parsing for large collection of units
+			if (totalUnits < parseThreshold)
+			{	parsedUnit = parser.parse(sourceUnits[i], unitResult);}
+			else
+			{	parsedUnit = parser.dietParse(sourceUnits[i], unitResult);}
+			if (options.verbose) {
+				System.out.println(Util.bind("compilation.request"/*nonNLS*/,new String[]{String.valueOf(i+1),String.valueOf(maxUnits),new String(sourceUnits[i].getFileName())}));
+			}
+			// initial type binding creation
+			lookupEnvironment.buildTypeBindings(parsedUnit);
+			this.addCompilationUnit(sourceUnits[i], parsedUnit);
+		//} catch (AbortCompilationUnit e) {
+		//	requestor.acceptResult(unitResult.tagAsAccepted());
+		} finally {
+			sourceUnits[i] = null; // no longer hold onto the unit
+		}
+	}
+	// binding resolution
+	lookupEnvironment.completeTypeBindings();
+}
+/**
+ * General API
+ * -> compile each of supplied files
+ * -> recompile any required types for which we have an incomplete principle structure
+ */
+
+public void compile(ICompilationUnit[] sourceUnits) {
+	CompilationUnitDeclaration unit = null;
+	int i = 0;
+	try {
+		// build and record parsed units
+
+		beginToCompile(sourceUnits);
+
+		// process all units (some more could be injected in the loop by the lookup environment)
+		for (; i < totalUnits; i++) {
+			unit = unitsToProcess[i];
+			try {
+				if (options.verbose) System.out.println(Util.bind("compilation.process"/*nonNLS*/,new String[]{String.valueOf(i + 1),String.valueOf(totalUnits),new String(unitsToProcess[i].getFileName())})); 
+				process(unit, i);
+			} finally {
+				// cleanup compilation unit result
+				unit.cleanUp();
+				if (options.verbose) 
+					System.out.println(Util.bind("compilation.done"/*nonNLS*/,new String[]{String.valueOf(i + 1),String.valueOf(totalUnits),new String(unitsToProcess[i].getFileName())}));  
+			}
+			unitsToProcess[i] = null; // release reference to processed unit declaration
+			requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+		}
+	} catch (AbortCompilation e) {
+		this.handleInternalException(e, unit);
+	} catch (Error e) {
+		this.handleInternalException(e, unit, null);
+		throw e; // rethrow
+	} catch (RuntimeException e) {
+		this.handleInternalException(e, unit, null);
+		throw e; // rethrow
+	} finally {
+		this.reset();
+	}
+	if (options.verbose) {
+		if (totalUnits > 1) {
+			System.out.println(Util.bind("compilation.units"/*nonNLS*/,String.valueOf(totalUnits)));
+		} else {
+			System.out.println(Util.bind("compilation.unit"/*nonNLS*/,String.valueOf(totalUnits)));
+		}
+	}
+}
+/**
+ * Answer an array of descriptions for the configurable options.
+ * The descriptions may be changed and passed back to a different
+ * compiler.
+ *
+ *  @return ConfigurableOption[] - array of configurable options
+ */
+public static ConfigurableOption[] getDefaultOptions(Locale locale) {
+	return new CompilerOptions().getConfigurableOptions(locale);
+}
+protected void getMethodBodies(CompilationUnitDeclaration unit, int place) {
+	//fill the methods bodies in order for the code to be generated
+	
+	if (unit.ignoreMethodBodies) {
+		unit.ignoreFurtherInvestigation = true;
+		return; // if initial diet parse did not work, no need to dig into method bodies.
+	}
+	
+	if (place < parseThreshold)
+		return; //work already done ...
+
+	//real parse of the method....
+	parser.scanner.setSourceBuffer(unit.compilationResult.compilationUnit.getContents());
+	if (unit.types != null) {
+		for (int i = unit.types.length; --i >= 0;)
+			unit.types[i].parseMethod(parser, unit);
+	}
+}
+/*
+ * Compiler crash recovery in case of unexpected runtime exceptions
+ */
+protected void handleInternalException(Throwable internalException, CompilationUnitDeclaration unit, CompilationResult result) {
+
+	/* dump a stack trace to the console */
+	internalException.printStackTrace(); 
+		
+	/* find a compilation result */
+	if ((unit != null)) // basing result upon the current unit if available
+		result = unit.compilationResult; // current unit being processed ?
+	if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
+		result = unitsToProcess[totalUnits - 1].compilationResult; // last unit in beginToCompile ?
+		
+	if (result != null) {
+		/* create and record a compilation problem */
+		StringWriter stringWriter = new StringWriter();
+		PrintWriter writer = new PrintWriter(stringWriter);
+		internalException.printStackTrace(writer);
+		StringBuffer buffer = stringWriter.getBuffer();
+
+		result.record(
+			problemReporter.createProblem(
+				result.getFileName(), 
+				ProblemIrritants.UnclassifiedProblem, 
+				new String[] {Util.bind("compilation.internalError"/*nonNLS*/)+"\n"/*nonNLS*/ + buffer.toString()},
+				Error, // severity
+				0, // source start
+				0, // source end
+				0)); // line number		
+
+		/* hand back the compilation result */
+		if (!result.hasBeenAccepted) {
+			requestor.acceptResult(result.tagAsAccepted());
+		}
+	}
+}
+/*
+ * Compiler recovery in case of internal AbortCompilation event
+ */
+protected void handleInternalException(AbortCompilation abortException, CompilationUnitDeclaration unit){
+
+	/* special treatment for SilentAbort: silently cancelling the compilation process */
+	if (abortException.isSilent){
+		if (abortException.silentException == null) {
+			return;
+		} else {
+			throw abortException.silentException;
+		}
+	}
+	
+	/* uncomment following line to see where the abort came from */
+	// abortException.printStackTrace(); 
+		
+	// Exception may tell which compilation result it is related, and which problem caused it
+	CompilationResult result = abortException.compilationResult; 
+	if ((result == null) && (unit != null)) result = unit.compilationResult; // current unit being processed ?
+	if ((result == null) && (unitsToProcess != null) && (totalUnits > 0)) result = unitsToProcess[totalUnits - 1].compilationResult; // last unit in beginToCompile ?
+	if (result != null && !result.hasBeenAccepted){
+		/* distant problem which could not be reported back there */
+		if (abortException.problemId != 0){ 
+			result.record(
+				problemReporter.createProblem(
+					result.getFileName(),
+					abortException.problemId, 
+					abortException.problemArguments, 
+					Error, // severity
+					0, // source start
+					0, // source end
+					0)); // line number
+		} else {
+			/* distant internal exception which could not be reported back there */
+			if (abortException.exception != null){
+				this.handleInternalException(abortException.exception, 	null, result);
+				return;
+			}
+		}
+		/* hand back the compilation result */
+		if (!result.hasBeenAccepted) { 
+			requestor.acceptResult(result.tagAsAccepted());
+		}
+	} else {
+		/*
+		if (abortException.problemId != 0){ 
+			IProblem problem =
+				problemReporter.createProblem(
+					"???".toCharArray(),
+					abortException.problemId, 
+					abortException.problemArguments, 
+					Error, // severity
+					0, // source start
+					0, // source end
+					0); // line number
+			System.out.println(problem.getMessage());
+		}
+		*/
+		abortException.printStackTrace();
+	}
+}
+/**
+ * Process a compilation unit already parsed and build.
+ */
+private void process(CompilationUnitDeclaration unit,int i) {
+
+	getMethodBodies(unit,i);
+
+	// fault in fields & methods
+	if (unit.scope != null)
+		unit.scope.faultInTypes();
+
+	// verify inherited methods
+	if (unit.scope != null)
+		unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+
+	// type checking
+	long startTime = System.currentTimeMillis();
+	unit.resolve();
+
+	// flow analysis
+	startTime = System.currentTimeMillis();
+	unit.analyseCode();
+
+	// code generation
+	startTime = System.currentTimeMillis();
+	unit.generateCode();
+
+	// reference info
+	if (options.produceReferenceInfo && unit.scope != null)
+		unit.scope.storeDependencyInfo();
+
+	// refresh the total number of units known at this stage
+	unit.compilationResult.totalUnitsKnown = totalUnits;
+}
+public void reset(){
+	lookupEnvironment.reset();
+	parser.scanner.source = null;
+	unitsToProcess	 = null;
+}
+/**
+ * Internal API used to resolve a compilation unit minimally for code assist engine
+ */
+
+public CompilationUnitDeclaration resolve(ICompilationUnit sourceUnit) {
+	CompilationUnitDeclaration unit = null;
+	try {
+		// build and record parsed units
+		parseThreshold = 1; // will request a full parse
+		beginToCompile(new ICompilationUnit[] { sourceUnit });
+		// process all units (some more could be injected in the loop by the lookup environment)
+		unit = unitsToProcess[0];
+		//getMethodBodies(unit,i);
+		if (unit.scope != null) {
+			// fault in fields & methods
+			unit.scope.faultInTypes();
+			// type checking
+			unit.resolve();
+		}
+		unitsToProcess[0] = null; // release reference to processed unit declaration
+		requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+		return unit;
+	} catch (AbortCompilation e) {
+		this.handleInternalException(e, unit);
+		return unit == null ? unitsToProcess[0] : unit;
+	} catch (Error e) {
+		this.handleInternalException(e, unit, null);
+		throw e; // rethrow
+	} catch (RuntimeException e) {
+		this.handleInternalException(e, unit, null);
+		throw e; // rethrow
+	} finally {
+		// No reset is performed there anymore since,
+		// within the CodeAssist (or related tools),
+		// the compiler may be called *after* a call
+		// to this resolve(...) method. And such a call
+		// needs to have a compiler with a non-empty
+		// environment.
+		// this.reset();
+	}
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java b/compiler/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java
index 70e19d2..b672313 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java
@@ -1,74 +1,69 @@
-package org.eclipse.jdt.internal.compiler;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.problem.ProblemHandler; 
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-public class DefaultErrorHandlingPolicies {
- 
-/*
- * Accumulate all problems, then exit without proceeding.
- *
- * Typically, the #proceedWithProblems(Problem[]) should
- * show the problems.
- *
- */
-public static IErrorHandlingPolicy exitAfterAllProblems() {
-	return new IErrorHandlingPolicy() {
-		public boolean stopOnFirstError() {
-			return false;
-		}
-		public boolean proceedOnErrors(){
-			return false;
-		}
-	};
-}
-/*
- * Exit without proceeding on the first problem wich appears
- * to be an error.
- *
- */
-public static IErrorHandlingPolicy exitOnFirstError() {
-	return new IErrorHandlingPolicy() {
-		public boolean stopOnFirstError() {
-			return true;
-		}
-		public boolean proceedOnErrors(){
-			return false;
-		}
-	};
-}
-/*
- * Proceed on the first error met.
- *
- */
-public static IErrorHandlingPolicy proceedOnFirstError() {
-	return new IErrorHandlingPolicy() {
-		public boolean stopOnFirstError() {
-			return true;
-		}
-		public boolean proceedOnErrors(){
-			return true;
-		}
-	};
-}
-/*
- * Accumulate all problems, then proceed with them.
- *
- */
-public static IErrorHandlingPolicy proceedWithAllProblems() {
-	return new IErrorHandlingPolicy() {
-		public boolean stopOnFirstError() {
-			return false;
-		}
-		public boolean proceedOnErrors(){
-			return true;
-		}
-	};
-}
-}
+package org.eclipse.jdt.internal.compiler; 
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+public class DefaultErrorHandlingPolicies {
+ 
+/*
+ * Accumulate all problems, then exit without proceeding.
+ *
+ * Typically, the #proceedWithProblems(Problem[]) should
+ * show the problems.
+ *
+ */
+public static IErrorHandlingPolicy exitAfterAllProblems() {
+	return new IErrorHandlingPolicy() {
+		public boolean stopOnFirstError() {
+			return false;
+		}
+		public boolean proceedOnErrors(){
+			return false;
+		}
+	};
+}
+/*
+ * Exit without proceeding on the first problem wich appears
+ * to be an error.
+ *
+ */
+public static IErrorHandlingPolicy exitOnFirstError() {
+	return new IErrorHandlingPolicy() {
+		public boolean stopOnFirstError() {
+			return true;
+		}
+		public boolean proceedOnErrors(){
+			return false;
+		}
+	};
+}
+/*
+ * Proceed on the first error met.
+ *
+ */
+public static IErrorHandlingPolicy proceedOnFirstError() {
+	return new IErrorHandlingPolicy() {
+		public boolean stopOnFirstError() {
+			return true;
+		}
+		public boolean proceedOnErrors(){
+			return true;
+		}
+	};
+}
+/*
+ * Accumulate all problems, then proceed with them.
+ *
+ */
+public static IErrorHandlingPolicy proceedWithAllProblems() {
+	return new IErrorHandlingPolicy() {
+		public boolean stopOnFirstError() {
+			return false;
+		}
+		public boolean proceedOnErrors(){
+			return true;
+		}
+	};
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java b/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
index d49cd5c..b013059 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
@@ -1,1318 +1,1317 @@
-package org.eclipse.jdt.internal.compiler;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/*
- * A document element parser extracts structural information
- * from a piece of source, providing detailed source positions info.
- *
- * also see @IDocumentElementRequestor
- *
- * The structural investigation includes:
- * - the package statement
- * - import statements
- * - top-level types: package member, member types (member types of member types...)
- * - fields
- * - methods
- *
- * Any (parsing) problem encountered is also provided.
- */
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.env.*;
-
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
- 
-public class DocumentElementParser extends Parser {
-	IDocumentElementRequestor requestor;
-	private int localIntPtr;
-	private int lastFieldEndPosition;
-	private int lastFieldBodyEndPosition;	
-	private int typeStartPosition;
-	private long selectorSourcePositions;
-	private int typeDims;
-	private int extendsDim;
-	private int declarationSourceStart;
-
-	/* int[] stack for storing javadoc positions */
-	int[][] intArrayStack;
-	int intArrayPtr;
-public DocumentElementParser(
-	final IDocumentElementRequestor requestor, 
-	IProblemFactory problemFactory) {
-	super(new ProblemReporter(
-		DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
-		new CompilerOptions(), 
-		problemFactory) {
-		public void record(IProblem problem, CompilationResult unitResult) {
-			requestor.acceptProblem(problem);
-		}
-	}, false);
-	this.requestor = requestor;
-	intArrayStack = new int[30][];
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void adjustInterfaceModifiers() {
-	intStack[intPtr - 2] |= AccInterface;
-}
-/*
- * Will clear the comment stack when looking
- * for a potential JavaDoc which might contain @deprecated.
- *
- * Additionally, before investigating for @deprecated, retrieve the positions
- * of the JavaDoc comments so as to notify requestor with them.
- */
-public void checkAnnotation() {
-
-	/* persisting javadoc positions */
-	pushOnIntArrayStack(this.getJavaDocPositions());
-	boolean deprecated = false;
-	int lastAnnotationIndex = -1;
-
-	//since jdk1.2 look only in the last java doc comment...
-	found : {
-		if ((lastAnnotationIndex = scanner.commentPtr) >= 0) { //look for @deprecated
-			scanner.commentPtr = -1;
-			// reset the comment stack, since not necessary after having checked
-			int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
-			// javadoc only (non javadoc comment have negative end positions.)
-			int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1;
-			//stop is one over
-			char[] comment = scanner.source;
-
-			for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
-				if ((comment[i] == '@')
-					&& (comment[i + 1] == 'd')
-					&& (comment[i + 2] == 'e')
-					&& (comment[i + 3] == 'p')
-					&& (comment[i + 4] == 'r')
-					&& (comment[i + 5] == 'e')
-					&& (comment[i + 6] == 'c')
-					&& (comment[i + 7] == 'a')
-					&& (comment[i + 8] == 't')
-					&& (comment[i + 9] == 'e')
-					&& (comment[i + 10] == 'd')) {
-					// ensure the tag is properly ended: either followed by a space, line end or asterisk.
-					int nextPos = i + 11;
-					deprecated = 
-						(comment[nextPos] == ' ')
-							|| (comment[nextPos] == '\n')
-							|| (comment[nextPos] == '\r')
-							|| (comment[nextPos] == '*'); 
-					break found;
-				}
-			}
-		}
-	}
-	if (deprecated) {
-		checkAndSetModifiers(AccDeprecated);
-	}
-	// modify the modifier source start to point at the first comment
-	if (lastAnnotationIndex >= 0) {
-		declarationSourceStart = scanner.commentStarts[0];
-	}
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeClassBodyDeclaration() {
-	// ClassBodyDeclaration ::= Diet Block
-	//push an Initializer
-	//optimize the push/pop
-
-	super.consumeClassBodyDeclaration();
-	Initializer initializer = (Initializer) astStack[astPtr];
-	requestor.acceptInitializer(
-		initializer.declarationSourceStart,
-		initializer.declarationSourceEnd,
-		intArrayStack[intArrayPtr--], 
-		0,
-		modifiersSourceStart, 
-		initializer.block.sourceStart,
-		initializer.block.sourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeClassDeclaration() {
-	super.consumeClassDeclaration();
-	// we know that we have a TypeDeclaration on the top of the astStack
-	if (isLocalDeclaration()) {
-		// we ignore the local variable declarations
-		return;
-	}
-	requestor.exitClass(endStatementPosition, // '}' is the end of the body 
-	 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeClassHeader() {
-	//ClassHeader ::= $empty
-	super.consumeClassHeader();
-	if (isLocalDeclaration()) {
-		// we ignore the local variable declarations
-		intArrayPtr--;
-		return;
-	}
-	TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
-	TypeReference[] superInterfaces = typeDecl.superInterfaces;
-	char[][] interfaceNames = null;
-	int[] interfaceNameStarts = null;
-	int[] interfaceNameEnds = null;
-	if (superInterfaces != null) {
-		int superInterfacesLength = superInterfaces.length;
-		interfaceNames = new char[superInterfacesLength][];
-		interfaceNameStarts = new int[superInterfacesLength];
-		interfaceNameEnds = new int[superInterfacesLength];
-		for (int i = 0; i < superInterfacesLength; i++) {
-			TypeReference superInterface = superInterfaces[i];
-			interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.'); 
-			interfaceNameStarts[i] = superInterface.sourceStart();
-			interfaceNameEnds[i] = superInterface.sourceEnd();
-		}
-	}
-	// flush the comments related to the class header
-	scanner.commentPtr = -1;
-	TypeReference superclass = typeDecl.superclass;
-	if (superclass == null) {
-		requestor.enterClass(
-			typeDecl.declarationSourceStart, 
-			intArrayStack[intArrayPtr--], 
-			typeDecl.modifiers, 
-			typeDecl.modifiersSourceStart, 
-			typeStartPosition, 
-			typeDecl.name, 
-			typeDecl.sourceStart(), 
-			typeDecl.sourceEnd(), 
-			null, 
-			-1, 
-			-1, 
-			interfaceNames, 
-			interfaceNameStarts, 
-			interfaceNameEnds, 
-			scanner.currentPosition - 1); 
-	} else {
-		requestor.enterClass(
-			typeDecl.declarationSourceStart, 
-			intArrayStack[intArrayPtr--], 
-			typeDecl.modifiers, 
-			typeDecl.modifiersSourceStart, 
-			typeStartPosition, 
-			typeDecl.name, 
-			typeDecl.sourceStart(), 
-			typeDecl.sourceEnd(), 
-			CharOperation.concatWith(superclass.getTypeName(), '.'), 
-			superclass.sourceStart(), 
-			superclass.sourceEnd(), 
-			interfaceNames, 
-			interfaceNameStarts, 
-			interfaceNameEnds, 
-			scanner.currentPosition - 1); 
-
-	}
-}
-protected void consumeClassHeaderName() {
-	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
-	TypeDeclaration typeDecl;
-	int length;
-	if (nestedMethod[nestedType] == 0) {
-		if (nestedType != 0) {
-			typeDecl = new MemberTypeDeclaration();
-		} else {
-			typeDecl = new TypeDeclaration();
-		}
-	} else {
-		// Record that the block has a declaration for local types
-		typeDecl = new LocalTypeDeclaration();
-		blockReal();
-	}
-
-	//highlight the name of the type
-	long pos = identifierPositionStack[identifierPtr];
-	typeDecl.sourceEnd = (int) pos;
-	typeDecl.sourceStart = (int) (pos >>> 32);
-	typeDecl.name = identifierStack[identifierPtr--];
-	identifierLengthPtr--;
-
-	//compute the declaration source too
-	// 'class' and 'interface' push an int position
-	typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
-	int declarationSourceStart = intStack[intPtr--];
-	typeDecl.modifiersSourceStart = intStack[intPtr--];
-	typeDecl.modifiers = intStack[intPtr--];
-	if (typeDecl.declarationSourceStart > declarationSourceStart) {
-		typeDecl.declarationSourceStart = declarationSourceStart;
-	}
-	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
-	pushOnAstStack(typeDecl);
-
-	length = 0; // will be updated when reading super-interfaces
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeCompilationUnit() {
-	// CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
-	requestor.exitCompilationUnit(scanner.source.length - 1);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeConstructorDeclaration() {
-	// ConstructorDeclaration ::= ConstructorHeader ConstructorBody
-	super.consumeConstructorDeclaration();
-	if (isLocalDeclaration()) {
-		// we ignore the local variable declarations
-		return;
-	}
-	ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
-	requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeConstructorHeader() {
-	// ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
-	super.consumeConstructorHeader();
-	if (isLocalDeclaration()) {
-		// we ignore the local variable declarations
-		intArrayPtr--;
-		return;
-	}
-	ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
-	Argument[] arguments = cd.arguments;
-	char[][] argumentTypes = null;
-	char[][] argumentNames = null;
-	int[] argumentTypeStarts = null;
-	int[] argumentTypeEnds = null;
-	int[] argumentNameStarts = null;
-	int[] argumentNameEnds = null;
-	if (arguments != null) {
-		int argumentLength = arguments.length;
-		argumentTypes = new char[argumentLength][];
-		argumentNames = new char[argumentLength][];
-		argumentNameStarts = new int[argumentLength];
-		argumentNameEnds = new int[argumentLength];
-		argumentTypeStarts = new int[argumentLength];
-		argumentTypeEnds = new int[argumentLength];
-		for (int i = 0; i < argumentLength; i++) {
-			Argument argument = arguments[i];
-			TypeReference argumentType = argument.type;
-			argumentTypes[i] = returnTypeName(argumentType);
-			argumentNames[i] = argument.name;
-			argumentNameStarts[i] = argument.sourceStart();
-			argumentNameEnds[i] = argument.sourceEnd();
-			argumentTypeStarts[i] = argumentType.sourceStart();
-			argumentTypeEnds[i] = argumentType.sourceEnd();
-		}
-	}
-	TypeReference[] thrownExceptions = cd.thrownExceptions;
-	char[][] exceptionTypes = null;
-	int[] exceptionTypeStarts = null;
-	int[] exceptionTypeEnds = null;
-	if (thrownExceptions != null) {
-		int thrownExceptionLength = thrownExceptions.length;
-		exceptionTypes = new char[thrownExceptionLength][];
-		exceptionTypeStarts = new int[thrownExceptionLength];
-		exceptionTypeEnds = new int[thrownExceptionLength];
-		for (int i = 0; i < thrownExceptionLength; i++) {
-			TypeReference exception = thrownExceptions[i];
-			exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
-			exceptionTypeStarts[i] = exception.sourceStart();
-			exceptionTypeEnds[i] = exception.sourceEnd();
-		}
-	}
-	requestor
-		.enterConstructor(
-			cd.declarationSourceStart, 
-			intArrayStack[intArrayPtr--], 
-			cd.modifiers,
-			cd.modifiersSourceStart, 
-			cd.selector, 
-			cd.sourceStart(), 
-			(int) (selectorSourcePositions & 0xFFFFFFFFL), 
-			// retrieve the source end of the name
-			argumentTypes, 
-			argumentTypeStarts, 
-			argumentTypeEnds, 
-			argumentNames, 
-			argumentNameStarts, 
-			argumentNameEnds, 
-			rParenPos, 
-			// right parenthesis
-			exceptionTypes, 
-			exceptionTypeStarts, 
-			exceptionTypeEnds, 
-			scanner.currentPosition - 1); 
-}
-protected void consumeConstructorHeaderName() {
-	// ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
-	ConstructorDeclaration cd = new ConstructorDeclaration();
-
-	//name -- this is not really revelant but we do .....
-	cd.selector = identifierStack[identifierPtr];
-	selectorSourcePositions = identifierPositionStack[identifierPtr--];
-	identifierLengthPtr--;
-
-	//modifiers
-	cd.declarationSourceStart = intStack[intPtr--];
-	cd.modifiersSourceStart = intStack[intPtr--];
-	cd.modifiers = intStack[intPtr--];
-
-	//highlight starts at the selector starts
-	cd.sourceStart = (int) (selectorSourcePositions >>> 32);
-	pushOnAstStack(cd);
-
-	cd.sourceEnd = lParenPos;
-	cd.bodyStart = lParenPos + 1;
-}
-protected void consumeDefaultModifiers() {
-	checkAnnotation(); // might update modifiers with AccDeprecated
-	pushOnIntStack(modifiers); // modifiers
-	pushOnIntStack(-1);
-	pushOnIntStack(
-		declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
-	resetModifiers();
-}
-protected void consumeDiet() {
-	// Diet ::= $empty
-	super.consumeDiet();
-	/* persisting javadoc positions
-	 * Will be consume in consumeClassBodyDeclaration
-	 */
-	pushOnIntArrayStack(this.getJavaDocPositions());	
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeEnterCompilationUnit() {
-	// EnterCompilationUnit ::= $empty
-	requestor.enterCompilationUnit();
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeEnterVariable() {
-	// EnterVariable ::= $empty
-	boolean isLocalDeclaration = isLocalDeclaration();
-	if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
-		requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
-	}
-	char[] name = identifierStack[identifierPtr];
-	long namePosition = identifierPositionStack[identifierPtr--];
-	int extendedTypeDimension = intStack[intPtr--];
-
-	AbstractVariableDeclaration declaration;
-	if (nestedMethod[nestedType] != 0) {
-		// create the local variable declarations
-		declaration = 
-			new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
-	} else {
-		// create the field declaration
-		declaration = 
-			new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
-	}
-	identifierLengthPtr--;
-	TypeReference type;
-	int variableIndex = variablesCounter[nestedType];
-	int typeDim = 0;
-	if (variableIndex == 0) {
-		// first variable of the declaration (FieldDeclaration or LocalDeclaration)
-		if (nestedMethod[nestedType] != 0) {
-			// local declaration
-			declaration.declarationSourceStart = intStack[intPtr--];
-			declaration.modifiersSourceStart = intStack[intPtr--];
-			declaration.modifiers = intStack[intPtr--];
-			type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
-			pushOnAstStack(type);
-		} else {
-			// field declaration
-			type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
-			pushOnAstStack(type);
-			declaration.declarationSourceStart = intStack[intPtr--];
-			declaration.modifiersSourceStart = intStack[intPtr--];
-			declaration.modifiers = intStack[intPtr--];
-		}
-	} else {
-		type = (TypeReference) astStack[astPtr - variableIndex];
-		typeDim = type.dimensions();
-		AbstractVariableDeclaration previousVariable = 
-			(AbstractVariableDeclaration) astStack[astPtr]; 
-		declaration.declarationSourceStart = previousVariable.declarationSourceStart;
-		declaration.modifiers = previousVariable.modifiers;
-		declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
-	}
-
-	localIntPtr = intPtr;
-
-	if (extendedTypeDimension == 0) {
-		declaration.type = type;
-	} else {
-		int dimension = typeDim + extendedTypeDimension;
-		//on the identifierLengthStack there is the information about the type....
-		int baseType;
-		if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
-			//it was a baseType
-			declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
-		} else {
-			declaration.type = type.copyDims(dimension);
-		}
-	}
-	variablesCounter[nestedType]++;
-	nestedMethod[nestedType]++;
-	pushOnAstStack(declaration);
-
-	int[] javadocPositions = intArrayStack[intArrayPtr];
-	if (!isLocalDeclaration) {
-		requestor
-			.enterField(
-				declaration.declarationSourceStart, 
-				javadocPositions, 
-				declaration.modifiers, 
-				declaration.modifiersSourceStart, 
-				returnTypeName(declaration.type), 
-				type.sourceStart(), 
-				type.sourceEnd(), 
-				typeDims, 
-				name, 
-				(int) (namePosition >>> 32), 
-				(int) namePosition, 
-				extendedTypeDimension, 
-				extendedTypeDimension == 0 ? -1 : endPosition); 
-	}
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeExitVariableWithInitialization() {
-	// ExitVariableWithInitialization ::= $empty
-	// the scanner is located after the comma or the semi-colon.
-	// we want to include the comma or the semi-colon
-	super.consumeExitVariableWithInitialization();
-	nestedMethod[nestedType]--;	
-	lastFieldEndPosition = scanner.currentPosition - 1;
-	lastFieldBodyEndPosition = 	((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd();
-}
-protected void consumeExitVariableWithoutInitialization() {
-	// ExitVariableWithoutInitialization ::= $empty
-	// do nothing by default
-	super.consumeExitVariableWithoutInitialization();
-	nestedMethod[nestedType]--;	
-	lastFieldEndPosition = scanner.currentPosition - 1;
-	lastFieldBodyEndPosition = scanner.startPosition - 1;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeFieldDeclaration() {
-	// See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
-	// FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
-	// the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]	
-	int variableIndex = variablesCounter[nestedType];
-	super.consumeFieldDeclaration();
-	intArrayPtr--;
-	if (isLocalDeclaration())
-		return;
-	if (variableIndex != 0) {
-		requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
-	}
-}
-protected void consumeFormalParameter() {
-	// FormalParameter ::= Type VariableDeclaratorId ==> false
-	// FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
-	/*
-	astStack : 
-	identifierStack : type identifier
-	intStack : dim dim
-	 ==>
-	astStack : Argument
-	identifierStack :  
-	intStack :  
-	*/
-
-	identifierLengthPtr--;
-	char[] name = identifierStack[identifierPtr];
-	long namePositions = identifierPositionStack[identifierPtr--];
-	TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
-	intPtr -= 3;
-	Argument arg = 
-		new Argument(
-			name, 
-			namePositions, 
-			type, 
-			intStack[intPtr + 1]); // modifiers
-	pushOnAstStack(arg);
-	intArrayPtr--;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeInterfaceDeclaration() {
-	super.consumeInterfaceDeclaration();
-	// we know that we have a TypeDeclaration on the top of the astStack
-	if (isLocalDeclaration()) {
-		// we ignore the local variable declarations
-		return;
-	}
-	requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
-	 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeInterfaceHeader() {
-	//InterfaceHeader ::= $empty
-	super.consumeInterfaceHeader();
-	if (isLocalDeclaration()) {
-		// we ignore the local variable declarations
-		intArrayPtr--;
-		return;
-	}
-	TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
-	TypeReference[] superInterfaces = typeDecl.superInterfaces;
-	char[][] interfaceNames = null;
-	int[] interfaceNameStarts = null;
-	int[] interfacenameEnds = null;
-	int superInterfacesLength = 0;
-	if (superInterfaces != null) {
-		superInterfacesLength = superInterfaces.length;
-		interfaceNames = new char[superInterfacesLength][];
-		interfaceNameStarts = new int[superInterfacesLength];
-		interfacenameEnds = new int[superInterfacesLength];
-	}
-	if (superInterfaces != null) {
-		for (int i = 0; i < superInterfacesLength; i++) {
-			TypeReference superInterface = superInterfaces[i];
-			interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.'); 
-			interfaceNameStarts[i] = superInterface.sourceStart();
-			interfacenameEnds[i] = superInterface.sourceEnd();
-		}
-	}
-	// flush the comments related to the interface header
-	scanner.commentPtr = -1;
-	requestor.enterInterface(
-		typeDecl.declarationSourceStart, 
-		intArrayStack[intArrayPtr--], 
-		typeDecl.modifiers, 
-		typeDecl.modifiersSourceStart, 
-		typeStartPosition, 
-		typeDecl.name, 
-		typeDecl.sourceStart(), 
-		typeDecl.sourceEnd(), 
-		interfaceNames, 
-		interfaceNameStarts, 
-		interfacenameEnds, 
-		scanner.currentPosition - 1); 
-}
-protected void consumeInterfaceHeaderName() {
-	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
-	TypeDeclaration typeDecl;
-	int length;
-	if (nestedMethod[nestedType] == 0) {
-		if (nestedType != 0) {
-			typeDecl = new MemberTypeDeclaration();
-		} else {
-			typeDecl = new TypeDeclaration();
-		}
-	} else {
-		// Record that the block has a declaration for local types
-		typeDecl = new LocalTypeDeclaration();
-		blockReal();
-	}
-
-	//highlight the name of the type
-	long pos = identifierPositionStack[identifierPtr];
-	typeDecl.sourceEnd = (int) pos;
-	typeDecl.sourceStart = (int) (pos >>> 32);
-	typeDecl.name = identifierStack[identifierPtr--];
-	identifierLengthPtr--;
-
-	//compute the declaration source too
-	// 'class' and 'interface' push an int position
-	typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
-	int declarationSourceStart = intStack[intPtr--];
-	typeDecl.modifiersSourceStart = intStack[intPtr--];
-	typeDecl.modifiers = intStack[intPtr--];
-	if (typeDecl.declarationSourceStart > declarationSourceStart) {
-		typeDecl.declarationSourceStart = declarationSourceStart;
-	}
-	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
-	pushOnAstStack(typeDecl);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeLocalVariableDeclaration() {
-	// See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
-	// FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
-
-	super.consumeLocalVariableDeclaration();
-	intArrayPtr--;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodDeclaration(boolean isNotAbstract) {
-	// MethodDeclaration ::= MethodHeader MethodBody
-	// AbstractMethodDeclaration ::= MethodHeader ';'
-	super.consumeMethodDeclaration(isNotAbstract);
-	if (isLocalDeclaration()) {
-		// we ignore the local variable declarations
-		return;
-	}
-	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
-	requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodHeader() {
-	// MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
-	super.consumeMethodHeader();
-	if (isLocalDeclaration()) {
-		// we ignore the local variable declarations
-		intArrayPtr--;
-		return;
-	}
-	int length;
-	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
-
-	TypeReference returnType = md.returnType;
-	char[] returnTypeName = returnTypeName(returnType);
-	Argument[] arguments = md.arguments;
-	char[][] argumentTypes = null;
-	char[][] argumentNames = null;
-	int[] argumentTypeStarts = null;
-	int[] argumentTypeEnds = null;
-	int[] argumentNameStarts = null;
-	int[] argumentNameEnds = null;
-	if (arguments != null) {
-		int argumentLength = arguments.length;
-		argumentTypes = new char[argumentLength][];
-		argumentNames = new char[argumentLength][];
-		argumentNameStarts = new int[argumentLength];
-		argumentNameEnds = new int[argumentLength];
-		argumentTypeStarts = new int[argumentLength];
-		argumentTypeEnds = new int[argumentLength];
-		for (int i = 0; i < argumentLength; i++) {
-			Argument argument = arguments[i];
-			TypeReference argumentType = argument.type;
-			argumentTypes[i] = returnTypeName(argumentType);
-			argumentNames[i] = argument.name;
-			argumentNameStarts[i] = argument.sourceStart();
-			argumentNameEnds[i] = argument.sourceEnd();
-			argumentTypeStarts[i] = argumentType.sourceStart();
-			argumentTypeEnds[i] = argumentType.sourceEnd();
-		}
-	}
-	TypeReference[] thrownExceptions = md.thrownExceptions;
-	char[][] exceptionTypes = null;
-	int[] exceptionTypeStarts = null;
-	int[] exceptionTypeEnds = null;
-	if (thrownExceptions != null) {
-		int thrownExceptionLength = thrownExceptions.length;
-		exceptionTypeStarts = new int[thrownExceptionLength];
-		exceptionTypeEnds = new int[thrownExceptionLength];
-		exceptionTypes = new char[thrownExceptionLength][];
-		for (int i = 0; i < thrownExceptionLength; i++) {
-			TypeReference exception = thrownExceptions[i];
-			exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
-			exceptionTypeStarts[i] = exception.sourceStart();
-			exceptionTypeEnds[i] = exception.sourceEnd();
-		}
-	}
-	requestor
-		.enterMethod(
-			md.declarationSourceStart, 
-			intArrayStack[intArrayPtr--], 
-			md.modifiers, 
-			md.modifiersSourceStart, 
-			returnTypeName, 
-			returnType.sourceStart(), 
-			returnType.sourceEnd(), 
-			typeDims, 
-			md.selector, 
-			md.sourceStart(), 
-			(int) (selectorSourcePositions & 0xFFFFFFFFL), 
-			argumentTypes, 
-			argumentTypeStarts, 
-			argumentTypeEnds, 
-			argumentNames, 
-			argumentNameStarts, 
-			argumentNameEnds, 
-			rParenPos, 
-			extendsDim, 
-			extendsDim == 0 ? -1 : endPosition, 
-			exceptionTypes, 
-			exceptionTypeStarts, 
-			exceptionTypeEnds, 
-			scanner.currentPosition - 1); 
-}
-protected void consumeMethodHeaderExtendedDims() {
-	// MethodHeaderExtendedDims ::= Dimsopt
-	// now we update the returnType of the method
-	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
-	int extendedDims = intStack[intPtr--];
-	extendsDim = extendedDims;
-	if (extendedDims != 0) {
-		TypeReference returnType = md.returnType;
-		md.sourceEnd = endPosition;
-		int dims = returnType.dimensions() + extendedDims;
-		int baseType;
-		if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
-			//it was a baseType
-			int sourceStart = returnType.sourceStart();
-			int sourceEnd = returnType.sourceEnd();
-			returnType = TypeReference.baseTypeReference(-baseType, dims);
-			returnType.sourceStart = sourceStart;
-			returnType.sourceEnd = sourceEnd;
-			md.returnType = returnType;
-		} else {
-			md.returnType = md.returnType.copyDims(dims);
-		}
-		if (currentToken == TokenNameLBRACE) {
-			md.bodyStart = endPosition + 1;
-		}
-	}
-}
-protected void consumeMethodHeaderName() {
-	// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
-	int length;
-	MethodDeclaration md = new MethodDeclaration();
-
-	//name
-	md.selector = identifierStack[identifierPtr];
-	selectorSourcePositions = identifierPositionStack[identifierPtr--];
-	identifierLengthPtr--;
-	//type
-	md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
-	//modifiers
-	md.declarationSourceStart = intStack[intPtr--];
-	md.modifiersSourceStart = intStack[intPtr--];
-	md.modifiers = intStack[intPtr--];
-
-	//highlight starts at selector start
-	md.sourceStart = (int) (selectorSourcePositions >>> 32);
-	pushOnAstStack(md);
-	md.bodyStart = scanner.currentPosition-1;
-}
-protected void consumeModifiers() {
-	checkAnnotation(); // might update modifiers with AccDeprecated
-	pushOnIntStack(modifiers); // modifiers
-	pushOnIntStack(modifiersSourceStart);
-	pushOnIntStack(
-		declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
-	resetModifiers();
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumePackageDeclarationName() {
-	/* persisting javadoc positions */
-	pushOnIntArrayStack(this.getJavaDocPositions());
-
-	super.consumePackageDeclarationName();
-	ImportReference importReference = compilationUnit.currentPackage;
-
-	requestor.acceptPackage(
-		importReference.declarationSourceStart, 
-		importReference.declarationSourceEnd, 
-		intArrayStack[intArrayPtr--], 
-		CharOperation.concatWith(importReference.getImportName(), '.'),
-		importReference.sourceStart());
-}
-protected void consumePushModifiers() {
-	checkAnnotation(); // might update modifiers with AccDeprecated
-	pushOnIntStack(modifiers); // modifiers
-	if (modifiersSourceStart < 0) {
-		pushOnIntStack(-1);
-		pushOnIntStack(
-			declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
-	} else {
-		pushOnIntStack(modifiersSourceStart);
-		pushOnIntStack(
-			declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
-	}
-	resetModifiers();
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeSingleTypeImportDeclarationName() {
-	// SingleTypeImportDeclarationName ::= 'import' Name
-
-	/* persisting javadoc positions */
-	pushOnIntArrayStack(this.getJavaDocPositions());
-
-	super.consumeSingleTypeImportDeclarationName();
-	ImportReference importReference = (ImportReference) astStack[astPtr];
-	requestor.acceptImport(
-		importReference.declarationSourceStart, 
-		importReference.declarationSourceEnd,
-		intArrayStack[intArrayPtr--],
-		CharOperation.concatWith(importReference.getImportName(), '.'),
-		importReference.sourceStart(),
-		false);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeStaticInitializer() {
-	// StaticInitializer ::=  StaticOnly Block
-	//push an Initializer
-	//optimize the push/pop
-	super.consumeStaticInitializer();
-	Initializer initializer = (Initializer) astStack[astPtr];
-	requestor.acceptInitializer(
-		initializer.declarationSourceStart,
-		initializer.declarationSourceEnd,
-		intArrayStack[intArrayPtr--],
-		AccStatic, 
-		intStack[intPtr--], 
-		initializer.block.sourceStart,
-		initializer.declarationSourceEnd);
-}
-protected void consumeStaticOnly() {
-	// StaticOnly ::= 'static'
-	checkAnnotation(); // might update declaration source start
-	pushOnIntStack(modifiersSourceStart);
-	pushOnIntStack(
-		declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
-	jumpOverMethodBody();
-	nestedMethod[nestedType]++;
-	resetModifiers();
-}
-protected void consumeToken(int type) {
-	super.consumeToken(type);
-
-	switch (type) {
-		case TokenNamevoid :
-		case TokenNameboolean :
-		case TokenNamebyte :
-		case TokenNamechar :
-		case TokenNamedouble :
-		case TokenNamefloat :
-		case TokenNameint :
-		case TokenNamelong :
-		case TokenNameshort :
-		// we need this position to know where the base type name ends.
-			pushOnIntStack(scanner.currentPosition - 1);
-			break;
-	}
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeTypeImportOnDemandDeclarationName() {
-	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
-
-	/* persisting javadoc positions */
-	pushOnIntArrayStack(this.getJavaDocPositions());
-
-	super.consumeTypeImportOnDemandDeclarationName();
-	ImportReference importReference = (ImportReference) astStack[astPtr];
-	requestor.acceptImport(
-		importReference.declarationSourceStart, 
-		importReference.declarationSourceEnd,
-		intArrayStack[intArrayPtr--],
-		CharOperation.concatWith(importReference.getImportName(), '.'), 
-		importReference.sourceStart(),
-		true);
-}
-public CompilationUnitDeclaration endParse(int act) {
-	if (scanner.recordLineSeparator) {
-		requestor.acceptLineSeparatorPositions(scanner.lineEnds());
-	}
-	return super.endParse(act);
-}
-/*
- * Flush annotations defined prior to a given positions.
- *
- * Note: annotations are stacked in syntactical order
- *
- * Either answer given <position>, or the end position of a comment line 
- * immediately following the <position> (same line)
- *
- * e.g.
- * void foo(){
- * } // end of method foo
- */
- 
-public int flushAnnotationsDefinedPriorTo(int position) {
-
-	return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
-}
-protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
-This variable is a type reference and dim will be its dimensions*/
-
-	int length;
-	TypeReference ref;
-	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
-		// single variable reference
-		if (dim == 0) {
-			ref = 
-				new SingleTypeReference(
-					identifierStack[identifierPtr], 
-					identifierPositionStack[identifierPtr--]); 
-		} else {
-			ref = 
-				new ArrayTypeReference(
-					identifierStack[identifierPtr], 
-					dim, 
-					identifierPositionStack[identifierPtr--]); 
-		}
-	} else {
-		if (length < 0) { //flag for precompiled type reference on base types
-			ref = TypeReference.baseTypeReference(-length, dim);
-			ref.sourceEnd = intStack[intPtr--];
-			ref.sourceStart = intStack[intPtr--];
-		} else { //Qualified variable reference
-			char[][] tokens = new char[length][];
-			identifierPtr -= length;
-			long[] positions = new long[length];
-			System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
-			System.arraycopy(
-				identifierPositionStack, 
-				identifierPtr + 1, 
-				positions, 
-				0, 
-				length); 
-			if (dim == 0)
-				ref = new QualifiedTypeReference(tokens, positions);
-			else
-				ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
-		}
-	};
-	return ref;
-}
-public void initialize() {
-	//positionning the parser for a new compilation unit
-	//avoiding stack reallocation and all that....
-	super.initialize();
-	intArrayPtr = -1;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-private boolean isLocalDeclaration() {
-	int nestedDepth = nestedType;
-	while (nestedDepth >= 0) {
-		if (nestedMethod[nestedDepth] != 0) {
-			return true;
-		}
-		nestedDepth--;
-	}
-	return false;
-}
-/*
- * Investigate one entire unit.
- */
-public void parseCompilationUnit(ICompilationUnit unit) {
-	char[] regionSource = unit.getContents();
-	try {
-		initialize();
-		goForCompilationUnit();
-		referenceContext =
-			compilationUnit = 
-				compilationUnit = 
-					new CompilationUnitDeclaration(
-						problemReporter(), 
-						new CompilationResult(unit, 0, 0), 
-						regionSource.length); 
-		scanner.resetTo(0, regionSource.length);
-		scanner.setSourceBuffer(regionSource);
-		parse();
-	} catch (AbortCompilation ex) {
-	}
-}
-/*
- * Investigate one constructor declaration.
- */
-public void parseConstructor(char[] regionSource) {
-	try {
-		initialize();
-		goForClassBodyDeclarations();
-		referenceContext = 
-			compilationUnit = 
-				compilationUnit = 
-					new CompilationUnitDeclaration(
-						problemReporter(), 
-						new CompilationResult(regionSource, 0, 0), 
-						regionSource.length); 
-		scanner.resetTo(0, regionSource.length);
-		scanner.setSourceBuffer(regionSource);
-		parse();
-	} catch (AbortCompilation ex) {
-	}
-}
-/*
- * Investigate one field declaration statement (might have multiple declarations in it).
- */
-public void parseField(char[] regionSource) {
-	try {
-		initialize();
-		goForFieldDeclaration();
-		referenceContext = 
-			compilationUnit = 
-				compilationUnit = 
-					new CompilationUnitDeclaration(
-						problemReporter(), 
-						new CompilationResult(regionSource, 0, 0), 
-						regionSource.length); 
-		scanner.resetTo(0, regionSource.length);
-		scanner.setSourceBuffer(regionSource);
-		parse();
-	} catch (AbortCompilation ex) {
-	}
-
-}
-/*
- * Investigate one import statement declaration.
- */
-public void parseImport(char[] regionSource) {
-	try {
-		initialize();
-		goForImportDeclaration();
-		referenceContext = 
-			compilationUnit = 
-				compilationUnit = 
-					new CompilationUnitDeclaration(
-						problemReporter(), 
-						new CompilationResult(regionSource, 0, 0), 
-						regionSource.length); 
-		scanner.resetTo(0, regionSource.length);
-		scanner.setSourceBuffer(regionSource);
-		parse();
-	} catch (AbortCompilation ex) {
-	}
-
-}
-/*
- * Investigate one initializer declaration.
- * regionSource need to content exactly an initializer declaration.
- * e.g: static { i = 4; }
- * { name = "test"; }
- */
-public void parseInitializer(char[] regionSource) {
-	try {
-		initialize();
-		goForInitializer();
-		referenceContext = 
-			compilationUnit = 
-				compilationUnit = 
-					new CompilationUnitDeclaration(
-						problemReporter(), 
-						new CompilationResult(regionSource, 0, 0), 
-						regionSource.length); 
-		scanner.resetTo(0, regionSource.length);
-		scanner.setSourceBuffer(regionSource);
-		parse();
-	} catch (AbortCompilation ex) {
-	}
-
-}
-/*
- * Investigate one method declaration.
- */
-public void parseMethod(char[] regionSource) {
-	try {
-		initialize();
-		goForGenericMethodDeclaration();
-		referenceContext = 
-			compilationUnit = 
-				compilationUnit = 
-					new CompilationUnitDeclaration(
-						problemReporter(), 
-						new CompilationResult(regionSource, 0, 0), 
-						regionSource.length); 
-		scanner.resetTo(0, regionSource.length);
-		scanner.setSourceBuffer(regionSource);
-		parse();
-	} catch (AbortCompilation ex) {
-	}
-
-}
-/*
- * Investigate one package statement declaration.
- */
-public void parsePackage(char[] regionSource) {
-	try {
-		initialize();
-		goForPackageDeclaration();
-		referenceContext = 
-			compilationUnit = 
-				compilationUnit = 
-					new CompilationUnitDeclaration(
-						problemReporter(), 
-						new CompilationResult(regionSource, 0, 0), 
-						regionSource.length); 
-		scanner.resetTo(0, regionSource.length);
-		scanner.setSourceBuffer(regionSource);
-		parse();
-	} catch (AbortCompilation ex) {
-	}
-
-}
-/*
- * Investigate one type declaration, its fields, methods and member types.
- */
-public void parseType(char[] regionSource) {
-	try {
-		initialize();
-		goForTypeDeclaration();
-		referenceContext = 
-			compilationUnit = 
-				compilationUnit = 
-					new CompilationUnitDeclaration(
-						problemReporter(), 
-						new CompilationResult(regionSource, 0, 0), 
-						regionSource.length); 
-		scanner.resetTo(0, regionSource.length);
-		scanner.setSourceBuffer(regionSource);
-		parse();
-	} catch (AbortCompilation ex) {
-	}
-
-}
-/**
- * Returns this parser's problem reporter initialized with its reference context.
- * Also it is assumed that a problem is going to be reported, so initializes
- * the compilation result's line positions.
- */
-public ProblemReporter problemReporter() {
-	problemReporter.referenceContext = referenceContext;
-	return problemReporter;
-}
-protected void pushOnIntArrayStack(int[] positions) {
-
-	try {
-		intArrayStack[++intArrayPtr] = positions;
-	} catch (IndexOutOfBoundsException e) {
-		//intPtr is correct 
-		int oldStackLength = intArrayStack.length;
-		int oldStack[][] = intArrayStack;
-		intArrayStack = new int[oldStackLength + StackIncrement][];
-		System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
-		intArrayStack[intArrayPtr] = positions;
-	}
-}
-protected void resetModifiers() {
-	super.resetModifiers();
-	declarationSourceStart = -1;
-}
-/*
- * Syntax error was detected. Will attempt to perform some recovery action in order
- * to resume to the regular parse loop.
- */
-protected boolean resumeOnSyntaxError() {
-	return false;
-}
-/*
- * Answer a char array representation of the type name formatted like:
- * - type name + dimensions
- * Example:
- * "A[][]".toCharArray()
- * "java.lang.String".toCharArray()
- */
-private char[] returnTypeName(TypeReference type) {
-	int dimension = type.dimensions();
-	if (dimension != 0) {
-		char[] dimensionsArray = new char[dimension * 2];
-		for (int i = 0; i < dimension; i++) {
-			dimensionsArray[i*2] = '[';
-			dimensionsArray[(i*2) + 1] = ']';
-		}
-		return CharOperation.concat(
-			CharOperation.concatWith(type.getTypeName(), '.'), 
-			dimensionsArray); 
-	}
-	return CharOperation.concatWith(type.getTypeName(), '.');
-}
-public String toString() {
-	StringBuffer buffer = new StringBuffer();
-	buffer.append("intArrayPtr = "/*nonNLS*/ + intArrayPtr + "\n"/*nonNLS*/);
-	buffer.append(super.toString());
-	return buffer.toString();
-}
-/**
- * INTERNAL USE ONLY
- */
-protected TypeReference typeReference(
-	int dim,
-	int localIdentifierPtr, 
-	int localIdentifierLengthPtr) {
-	/* build a Reference on a variable that may be qualified or not
-	 * This variable is a type reference and dim will be its dimensions.
-	 * We don't have any side effect on the stacks' pointers.
-	 */
-
-	int length;
-	TypeReference ref;
-	if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
-		// single variable reference
-		if (dim == 0) {
-			ref = 
-				new SingleTypeReference(
-					identifierStack[localIdentifierPtr], 
-					identifierPositionStack[localIdentifierPtr--]); 
-		} else {
-			ref = 
-				new ArrayTypeReference(
-					identifierStack[localIdentifierPtr], 
-					dim, 
-					identifierPositionStack[localIdentifierPtr--]); 
-		}
-	} else {
-		if (length < 0) { //flag for precompiled type reference on base types
-			ref = TypeReference.baseTypeReference(-length, dim);
-			ref.sourceEnd = intStack[localIntPtr--];
-			ref.sourceStart = intStack[localIntPtr--];
-		} else { //Qualified variable reference
-			char[][] tokens = new char[length][];
-			localIdentifierPtr -= length;
-			long[] positions = new long[length];
-			System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
-			System.arraycopy(
-				identifierPositionStack, 
-				localIdentifierPtr + 1, 
-				positions, 
-				0, 
-				length); 
-			if (dim == 0)
-				ref = new QualifiedTypeReference(tokens, positions);
-			else
-				ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
-		}
-	};
-	return ref;
-}
-}
+package org.eclipse.jdt.internal.compiler;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/*
+ * A document element parser extracts structural information
+ * from a piece of source, providing detailed source positions info.
+ *
+ * also see @IDocumentElementRequestor
+ *
+ * The structural investigation includes:
+ * - the package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * Any (parsing) problem encountered is also provided.
+ */
+import org.eclipse.jdt.internal.compiler.env.*;
+
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+ 
+public class DocumentElementParser extends Parser {
+	IDocumentElementRequestor requestor;
+	private int localIntPtr;
+	private int lastFieldEndPosition;
+	private int lastFieldBodyEndPosition;	
+	private int typeStartPosition;
+	private long selectorSourcePositions;
+	private int typeDims;
+	private int extendsDim;
+	private int declarationSourceStart;
+
+	/* int[] stack for storing javadoc positions */
+	int[][] intArrayStack;
+	int intArrayPtr;
+public DocumentElementParser(
+	final IDocumentElementRequestor requestor, 
+	IProblemFactory problemFactory) {
+	super(new ProblemReporter(
+		DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
+		new CompilerOptions(), 
+		problemFactory) {
+		public void record(IProblem problem, CompilationResult unitResult) {
+			requestor.acceptProblem(problem);
+		}
+	}, false);
+	this.requestor = requestor;
+	intArrayStack = new int[30][];
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void adjustInterfaceModifiers() {
+	intStack[intPtr - 2] |= AccInterface;
+}
+/*
+ * Will clear the comment stack when looking
+ * for a potential JavaDoc which might contain @deprecated.
+ *
+ * Additionally, before investigating for @deprecated, retrieve the positions
+ * of the JavaDoc comments so as to notify requestor with them.
+ */
+public void checkAnnotation() {
+
+	/* persisting javadoc positions */
+	pushOnIntArrayStack(this.getJavaDocPositions());
+	boolean deprecated = false;
+	int lastAnnotationIndex = -1;
+
+	//since jdk1.2 look only in the last java doc comment...
+	found : {
+		if ((lastAnnotationIndex = scanner.commentPtr) >= 0) { //look for @deprecated
+			scanner.commentPtr = -1;
+			// reset the comment stack, since not necessary after having checked
+			int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
+			// javadoc only (non javadoc comment have negative end positions.)
+			int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1;
+			//stop is one over
+			char[] comment = scanner.source;
+
+			for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
+				if ((comment[i] == '@')
+					&& (comment[i + 1] == 'd')
+					&& (comment[i + 2] == 'e')
+					&& (comment[i + 3] == 'p')
+					&& (comment[i + 4] == 'r')
+					&& (comment[i + 5] == 'e')
+					&& (comment[i + 6] == 'c')
+					&& (comment[i + 7] == 'a')
+					&& (comment[i + 8] == 't')
+					&& (comment[i + 9] == 'e')
+					&& (comment[i + 10] == 'd')) {
+					// ensure the tag is properly ended: either followed by a space, line end or asterisk.
+					int nextPos = i + 11;
+					deprecated = 
+						(comment[nextPos] == ' ')
+							|| (comment[nextPos] == '\n')
+							|| (comment[nextPos] == '\r')
+							|| (comment[nextPos] == '*'); 
+					break found;
+				}
+			}
+		}
+	}
+	if (deprecated) {
+		checkAndSetModifiers(AccDeprecated);
+	}
+	// modify the modifier source start to point at the first comment
+	if (lastAnnotationIndex >= 0) {
+		declarationSourceStart = scanner.commentStarts[0];
+	}
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassBodyDeclaration() {
+	// ClassBodyDeclaration ::= Diet Block
+	//push an Initializer
+	//optimize the push/pop
+
+	super.consumeClassBodyDeclaration();
+	Initializer initializer = (Initializer) astStack[astPtr];
+	requestor.acceptInitializer(
+		initializer.declarationSourceStart,
+		initializer.declarationSourceEnd,
+		intArrayStack[intArrayPtr--], 
+		0,
+		modifiersSourceStart, 
+		initializer.block.sourceStart,
+		initializer.block.sourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassDeclaration() {
+	super.consumeClassDeclaration();
+	// we know that we have a TypeDeclaration on the top of the astStack
+	if (isLocalDeclaration()) {
+		// we ignore the local variable declarations
+		return;
+	}
+	requestor.exitClass(endStatementPosition, // '}' is the end of the body 
+	 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassHeader() {
+	//ClassHeader ::= $empty
+	super.consumeClassHeader();
+	if (isLocalDeclaration()) {
+		// we ignore the local variable declarations
+		intArrayPtr--;
+		return;
+	}
+	TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+	TypeReference[] superInterfaces = typeDecl.superInterfaces;
+	char[][] interfaceNames = null;
+	int[] interfaceNameStarts = null;
+	int[] interfaceNameEnds = null;
+	if (superInterfaces != null) {
+		int superInterfacesLength = superInterfaces.length;
+		interfaceNames = new char[superInterfacesLength][];
+		interfaceNameStarts = new int[superInterfacesLength];
+		interfaceNameEnds = new int[superInterfacesLength];
+		for (int i = 0; i < superInterfacesLength; i++) {
+			TypeReference superInterface = superInterfaces[i];
+			interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.'); 
+			interfaceNameStarts[i] = superInterface.sourceStart();
+			interfaceNameEnds[i] = superInterface.sourceEnd();
+		}
+	}
+	// flush the comments related to the class header
+	scanner.commentPtr = -1;
+	TypeReference superclass = typeDecl.superclass;
+	if (superclass == null) {
+		requestor.enterClass(
+			typeDecl.declarationSourceStart, 
+			intArrayStack[intArrayPtr--], 
+			typeDecl.modifiers, 
+			typeDecl.modifiersSourceStart, 
+			typeStartPosition, 
+			typeDecl.name, 
+			typeDecl.sourceStart(), 
+			typeDecl.sourceEnd(), 
+			null, 
+			-1, 
+			-1, 
+			interfaceNames, 
+			interfaceNameStarts, 
+			interfaceNameEnds, 
+			scanner.currentPosition - 1); 
+	} else {
+		requestor.enterClass(
+			typeDecl.declarationSourceStart, 
+			intArrayStack[intArrayPtr--], 
+			typeDecl.modifiers, 
+			typeDecl.modifiersSourceStart, 
+			typeStartPosition, 
+			typeDecl.name, 
+			typeDecl.sourceStart(), 
+			typeDecl.sourceEnd(), 
+			CharOperation.concatWith(superclass.getTypeName(), '.'), 
+			superclass.sourceStart(), 
+			superclass.sourceEnd(), 
+			interfaceNames, 
+			interfaceNameStarts, 
+			interfaceNameEnds, 
+			scanner.currentPosition - 1); 
+
+	}
+}
+protected void consumeClassHeaderName() {
+	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
+	TypeDeclaration typeDecl;
+	int length;
+	if (nestedMethod[nestedType] == 0) {
+		if (nestedType != 0) {
+			typeDecl = new MemberTypeDeclaration();
+		} else {
+			typeDecl = new TypeDeclaration();
+		}
+	} else {
+		// Record that the block has a declaration for local types
+		typeDecl = new LocalTypeDeclaration();
+		blockReal();
+	}
+
+	//highlight the name of the type
+	long pos = identifierPositionStack[identifierPtr];
+	typeDecl.sourceEnd = (int) pos;
+	typeDecl.sourceStart = (int) (pos >>> 32);
+	typeDecl.name = identifierStack[identifierPtr--];
+	identifierLengthPtr--;
+
+	//compute the declaration source too
+	// 'class' and 'interface' push an int position
+	typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
+	int declarationSourceStart = intStack[intPtr--];
+	typeDecl.modifiersSourceStart = intStack[intPtr--];
+	typeDecl.modifiers = intStack[intPtr--];
+	if (typeDecl.declarationSourceStart > declarationSourceStart) {
+		typeDecl.declarationSourceStart = declarationSourceStart;
+	}
+	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+	pushOnAstStack(typeDecl);
+
+	length = 0; // will be updated when reading super-interfaces
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeCompilationUnit() {
+	// CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
+	requestor.exitCompilationUnit(scanner.source.length - 1);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeConstructorDeclaration() {
+	// ConstructorDeclaration ::= ConstructorHeader ConstructorBody
+	super.consumeConstructorDeclaration();
+	if (isLocalDeclaration()) {
+		// we ignore the local variable declarations
+		return;
+	}
+	ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
+	requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeConstructorHeader() {
+	// ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
+	super.consumeConstructorHeader();
+	if (isLocalDeclaration()) {
+		// we ignore the local variable declarations
+		intArrayPtr--;
+		return;
+	}
+	ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
+	Argument[] arguments = cd.arguments;
+	char[][] argumentTypes = null;
+	char[][] argumentNames = null;
+	int[] argumentTypeStarts = null;
+	int[] argumentTypeEnds = null;
+	int[] argumentNameStarts = null;
+	int[] argumentNameEnds = null;
+	if (arguments != null) {
+		int argumentLength = arguments.length;
+		argumentTypes = new char[argumentLength][];
+		argumentNames = new char[argumentLength][];
+		argumentNameStarts = new int[argumentLength];
+		argumentNameEnds = new int[argumentLength];
+		argumentTypeStarts = new int[argumentLength];
+		argumentTypeEnds = new int[argumentLength];
+		for (int i = 0; i < argumentLength; i++) {
+			Argument argument = arguments[i];
+			TypeReference argumentType = argument.type;
+			argumentTypes[i] = returnTypeName(argumentType);
+			argumentNames[i] = argument.name;
+			argumentNameStarts[i] = argument.sourceStart();
+			argumentNameEnds[i] = argument.sourceEnd();
+			argumentTypeStarts[i] = argumentType.sourceStart();
+			argumentTypeEnds[i] = argumentType.sourceEnd();
+		}
+	}
+	TypeReference[] thrownExceptions = cd.thrownExceptions;
+	char[][] exceptionTypes = null;
+	int[] exceptionTypeStarts = null;
+	int[] exceptionTypeEnds = null;
+	if (thrownExceptions != null) {
+		int thrownExceptionLength = thrownExceptions.length;
+		exceptionTypes = new char[thrownExceptionLength][];
+		exceptionTypeStarts = new int[thrownExceptionLength];
+		exceptionTypeEnds = new int[thrownExceptionLength];
+		for (int i = 0; i < thrownExceptionLength; i++) {
+			TypeReference exception = thrownExceptions[i];
+			exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
+			exceptionTypeStarts[i] = exception.sourceStart();
+			exceptionTypeEnds[i] = exception.sourceEnd();
+		}
+	}
+	requestor
+		.enterConstructor(
+			cd.declarationSourceStart, 
+			intArrayStack[intArrayPtr--], 
+			cd.modifiers,
+			cd.modifiersSourceStart, 
+			cd.selector, 
+			cd.sourceStart(), 
+			(int) (selectorSourcePositions & 0xFFFFFFFFL), 
+			// retrieve the source end of the name
+			argumentTypes, 
+			argumentTypeStarts, 
+			argumentTypeEnds, 
+			argumentNames, 
+			argumentNameStarts, 
+			argumentNameEnds, 
+			rParenPos, 
+			// right parenthesis
+			exceptionTypes, 
+			exceptionTypeStarts, 
+			exceptionTypeEnds, 
+			scanner.currentPosition - 1); 
+}
+protected void consumeConstructorHeaderName() {
+	// ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
+	ConstructorDeclaration cd = new ConstructorDeclaration();
+
+	//name -- this is not really revelant but we do .....
+	cd.selector = identifierStack[identifierPtr];
+	selectorSourcePositions = identifierPositionStack[identifierPtr--];
+	identifierLengthPtr--;
+
+	//modifiers
+	cd.declarationSourceStart = intStack[intPtr--];
+	cd.modifiersSourceStart = intStack[intPtr--];
+	cd.modifiers = intStack[intPtr--];
+
+	//highlight starts at the selector starts
+	cd.sourceStart = (int) (selectorSourcePositions >>> 32);
+	pushOnAstStack(cd);
+
+	cd.sourceEnd = lParenPos;
+	cd.bodyStart = lParenPos + 1;
+}
+protected void consumeDefaultModifiers() {
+	checkAnnotation(); // might update modifiers with AccDeprecated
+	pushOnIntStack(modifiers); // modifiers
+	pushOnIntStack(-1);
+	pushOnIntStack(
+		declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
+	resetModifiers();
+}
+protected void consumeDiet() {
+	// Diet ::= $empty
+	super.consumeDiet();
+	/* persisting javadoc positions
+	 * Will be consume in consumeClassBodyDeclaration
+	 */
+	pushOnIntArrayStack(this.getJavaDocPositions());	
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeEnterCompilationUnit() {
+	// EnterCompilationUnit ::= $empty
+	requestor.enterCompilationUnit();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeEnterVariable() {
+	// EnterVariable ::= $empty
+	boolean isLocalDeclaration = isLocalDeclaration();
+	if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
+		requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
+	}
+	char[] name = identifierStack[identifierPtr];
+	long namePosition = identifierPositionStack[identifierPtr--];
+	int extendedTypeDimension = intStack[intPtr--];
+
+	AbstractVariableDeclaration declaration;
+	if (nestedMethod[nestedType] != 0) {
+		// create the local variable declarations
+		declaration = 
+			new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
+	} else {
+		// create the field declaration
+		declaration = 
+			new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
+	}
+	identifierLengthPtr--;
+	TypeReference type;
+	int variableIndex = variablesCounter[nestedType];
+	int typeDim = 0;
+	if (variableIndex == 0) {
+		// first variable of the declaration (FieldDeclaration or LocalDeclaration)
+		if (nestedMethod[nestedType] != 0) {
+			// local declaration
+			declaration.declarationSourceStart = intStack[intPtr--];
+			declaration.modifiersSourceStart = intStack[intPtr--];
+			declaration.modifiers = intStack[intPtr--];
+			type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
+			pushOnAstStack(type);
+		} else {
+			// field declaration
+			type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
+			pushOnAstStack(type);
+			declaration.declarationSourceStart = intStack[intPtr--];
+			declaration.modifiersSourceStart = intStack[intPtr--];
+			declaration.modifiers = intStack[intPtr--];
+		}
+	} else {
+		type = (TypeReference) astStack[astPtr - variableIndex];
+		typeDim = type.dimensions();
+		AbstractVariableDeclaration previousVariable = 
+			(AbstractVariableDeclaration) astStack[astPtr]; 
+		declaration.declarationSourceStart = previousVariable.declarationSourceStart;
+		declaration.modifiers = previousVariable.modifiers;
+		declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
+	}
+
+	localIntPtr = intPtr;
+
+	if (extendedTypeDimension == 0) {
+		declaration.type = type;
+	} else {
+		int dimension = typeDim + extendedTypeDimension;
+		//on the identifierLengthStack there is the information about the type....
+		int baseType;
+		if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
+			//it was a baseType
+			declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
+		} else {
+			declaration.type = type.copyDims(dimension);
+		}
+	}
+	variablesCounter[nestedType]++;
+	nestedMethod[nestedType]++;
+	pushOnAstStack(declaration);
+
+	int[] javadocPositions = intArrayStack[intArrayPtr];
+	if (!isLocalDeclaration) {
+		requestor
+			.enterField(
+				declaration.declarationSourceStart, 
+				javadocPositions, 
+				declaration.modifiers, 
+				declaration.modifiersSourceStart, 
+				returnTypeName(declaration.type), 
+				type.sourceStart(), 
+				type.sourceEnd(), 
+				typeDims, 
+				name, 
+				(int) (namePosition >>> 32), 
+				(int) namePosition, 
+				extendedTypeDimension, 
+				extendedTypeDimension == 0 ? -1 : endPosition); 
+	}
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeExitVariableWithInitialization() {
+	// ExitVariableWithInitialization ::= $empty
+	// the scanner is located after the comma or the semi-colon.
+	// we want to include the comma or the semi-colon
+	super.consumeExitVariableWithInitialization();
+	nestedMethod[nestedType]--;	
+	lastFieldEndPosition = scanner.currentPosition - 1;
+	lastFieldBodyEndPosition = 	((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd();
+}
+protected void consumeExitVariableWithoutInitialization() {
+	// ExitVariableWithoutInitialization ::= $empty
+	// do nothing by default
+	super.consumeExitVariableWithoutInitialization();
+	nestedMethod[nestedType]--;	
+	lastFieldEndPosition = scanner.currentPosition - 1;
+	lastFieldBodyEndPosition = scanner.startPosition - 1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeFieldDeclaration() {
+	// See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
+	// FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+	// the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]	
+	int variableIndex = variablesCounter[nestedType];
+	super.consumeFieldDeclaration();
+	intArrayPtr--;
+	if (isLocalDeclaration())
+		return;
+	if (variableIndex != 0) {
+		requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
+	}
+}
+protected void consumeFormalParameter() {
+	// FormalParameter ::= Type VariableDeclaratorId ==> false
+	// FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
+	/*
+	astStack : 
+	identifierStack : type identifier
+	intStack : dim dim
+	 ==>
+	astStack : Argument
+	identifierStack :  
+	intStack :  
+	*/
+
+	identifierLengthPtr--;
+	char[] name = identifierStack[identifierPtr];
+	long namePositions = identifierPositionStack[identifierPtr--];
+	TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+	intPtr -= 3;
+	Argument arg = 
+		new Argument(
+			name, 
+			namePositions, 
+			type, 
+			intStack[intPtr + 1]); // modifiers
+	pushOnAstStack(arg);
+	intArrayPtr--;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeInterfaceDeclaration() {
+	super.consumeInterfaceDeclaration();
+	// we know that we have a TypeDeclaration on the top of the astStack
+	if (isLocalDeclaration()) {
+		// we ignore the local variable declarations
+		return;
+	}
+	requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
+	 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeInterfaceHeader() {
+	//InterfaceHeader ::= $empty
+	super.consumeInterfaceHeader();
+	if (isLocalDeclaration()) {
+		// we ignore the local variable declarations
+		intArrayPtr--;
+		return;
+	}
+	TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+	TypeReference[] superInterfaces = typeDecl.superInterfaces;
+	char[][] interfaceNames = null;
+	int[] interfaceNameStarts = null;
+	int[] interfacenameEnds = null;
+	int superInterfacesLength = 0;
+	if (superInterfaces != null) {
+		superInterfacesLength = superInterfaces.length;
+		interfaceNames = new char[superInterfacesLength][];
+		interfaceNameStarts = new int[superInterfacesLength];
+		interfacenameEnds = new int[superInterfacesLength];
+	}
+	if (superInterfaces != null) {
+		for (int i = 0; i < superInterfacesLength; i++) {
+			TypeReference superInterface = superInterfaces[i];
+			interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.'); 
+			interfaceNameStarts[i] = superInterface.sourceStart();
+			interfacenameEnds[i] = superInterface.sourceEnd();
+		}
+	}
+	// flush the comments related to the interface header
+	scanner.commentPtr = -1;
+	requestor.enterInterface(
+		typeDecl.declarationSourceStart, 
+		intArrayStack[intArrayPtr--], 
+		typeDecl.modifiers, 
+		typeDecl.modifiersSourceStart, 
+		typeStartPosition, 
+		typeDecl.name, 
+		typeDecl.sourceStart(), 
+		typeDecl.sourceEnd(), 
+		interfaceNames, 
+		interfaceNameStarts, 
+		interfacenameEnds, 
+		scanner.currentPosition - 1); 
+}
+protected void consumeInterfaceHeaderName() {
+	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
+	TypeDeclaration typeDecl;
+	int length;
+	if (nestedMethod[nestedType] == 0) {
+		if (nestedType != 0) {
+			typeDecl = new MemberTypeDeclaration();
+		} else {
+			typeDecl = new TypeDeclaration();
+		}
+	} else {
+		// Record that the block has a declaration for local types
+		typeDecl = new LocalTypeDeclaration();
+		blockReal();
+	}
+
+	//highlight the name of the type
+	long pos = identifierPositionStack[identifierPtr];
+	typeDecl.sourceEnd = (int) pos;
+	typeDecl.sourceStart = (int) (pos >>> 32);
+	typeDecl.name = identifierStack[identifierPtr--];
+	identifierLengthPtr--;
+
+	//compute the declaration source too
+	// 'class' and 'interface' push an int position
+	typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
+	int declarationSourceStart = intStack[intPtr--];
+	typeDecl.modifiersSourceStart = intStack[intPtr--];
+	typeDecl.modifiers = intStack[intPtr--];
+	if (typeDecl.declarationSourceStart > declarationSourceStart) {
+		typeDecl.declarationSourceStart = declarationSourceStart;
+	}
+	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+	pushOnAstStack(typeDecl);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeLocalVariableDeclaration() {
+	// See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
+	// FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+
+	super.consumeLocalVariableDeclaration();
+	intArrayPtr--;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodDeclaration(boolean isNotAbstract) {
+	// MethodDeclaration ::= MethodHeader MethodBody
+	// AbstractMethodDeclaration ::= MethodHeader ';'
+	super.consumeMethodDeclaration(isNotAbstract);
+	if (isLocalDeclaration()) {
+		// we ignore the local variable declarations
+		return;
+	}
+	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+	requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodHeader() {
+	// MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
+	super.consumeMethodHeader();
+	if (isLocalDeclaration()) {
+		// we ignore the local variable declarations
+		intArrayPtr--;
+		return;
+	}
+	int length;
+	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+
+	TypeReference returnType = md.returnType;
+	char[] returnTypeName = returnTypeName(returnType);
+	Argument[] arguments = md.arguments;
+	char[][] argumentTypes = null;
+	char[][] argumentNames = null;
+	int[] argumentTypeStarts = null;
+	int[] argumentTypeEnds = null;
+	int[] argumentNameStarts = null;
+	int[] argumentNameEnds = null;
+	if (arguments != null) {
+		int argumentLength = arguments.length;
+		argumentTypes = new char[argumentLength][];
+		argumentNames = new char[argumentLength][];
+		argumentNameStarts = new int[argumentLength];
+		argumentNameEnds = new int[argumentLength];
+		argumentTypeStarts = new int[argumentLength];
+		argumentTypeEnds = new int[argumentLength];
+		for (int i = 0; i < argumentLength; i++) {
+			Argument argument = arguments[i];
+			TypeReference argumentType = argument.type;
+			argumentTypes[i] = returnTypeName(argumentType);
+			argumentNames[i] = argument.name;
+			argumentNameStarts[i] = argument.sourceStart();
+			argumentNameEnds[i] = argument.sourceEnd();
+			argumentTypeStarts[i] = argumentType.sourceStart();
+			argumentTypeEnds[i] = argumentType.sourceEnd();
+		}
+	}
+	TypeReference[] thrownExceptions = md.thrownExceptions;
+	char[][] exceptionTypes = null;
+	int[] exceptionTypeStarts = null;
+	int[] exceptionTypeEnds = null;
+	if (thrownExceptions != null) {
+		int thrownExceptionLength = thrownExceptions.length;
+		exceptionTypeStarts = new int[thrownExceptionLength];
+		exceptionTypeEnds = new int[thrownExceptionLength];
+		exceptionTypes = new char[thrownExceptionLength][];
+		for (int i = 0; i < thrownExceptionLength; i++) {
+			TypeReference exception = thrownExceptions[i];
+			exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
+			exceptionTypeStarts[i] = exception.sourceStart();
+			exceptionTypeEnds[i] = exception.sourceEnd();
+		}
+	}
+	requestor
+		.enterMethod(
+			md.declarationSourceStart, 
+			intArrayStack[intArrayPtr--], 
+			md.modifiers, 
+			md.modifiersSourceStart, 
+			returnTypeName, 
+			returnType.sourceStart(), 
+			returnType.sourceEnd(), 
+			typeDims, 
+			md.selector, 
+			md.sourceStart(), 
+			(int) (selectorSourcePositions & 0xFFFFFFFFL), 
+			argumentTypes, 
+			argumentTypeStarts, 
+			argumentTypeEnds, 
+			argumentNames, 
+			argumentNameStarts, 
+			argumentNameEnds, 
+			rParenPos, 
+			extendsDim, 
+			extendsDim == 0 ? -1 : endPosition, 
+			exceptionTypes, 
+			exceptionTypeStarts, 
+			exceptionTypeEnds, 
+			scanner.currentPosition - 1); 
+}
+protected void consumeMethodHeaderExtendedDims() {
+	// MethodHeaderExtendedDims ::= Dimsopt
+	// now we update the returnType of the method
+	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+	int extendedDims = intStack[intPtr--];
+	extendsDim = extendedDims;
+	if (extendedDims != 0) {
+		TypeReference returnType = md.returnType;
+		md.sourceEnd = endPosition;
+		int dims = returnType.dimensions() + extendedDims;
+		int baseType;
+		if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
+			//it was a baseType
+			int sourceStart = returnType.sourceStart();
+			int sourceEnd = returnType.sourceEnd();
+			returnType = TypeReference.baseTypeReference(-baseType, dims);
+			returnType.sourceStart = sourceStart;
+			returnType.sourceEnd = sourceEnd;
+			md.returnType = returnType;
+		} else {
+			md.returnType = md.returnType.copyDims(dims);
+		}
+		if (currentToken == TokenNameLBRACE) {
+			md.bodyStart = endPosition + 1;
+		}
+	}
+}
+protected void consumeMethodHeaderName() {
+	// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+	int length;
+	MethodDeclaration md = new MethodDeclaration();
+
+	//name
+	md.selector = identifierStack[identifierPtr];
+	selectorSourcePositions = identifierPositionStack[identifierPtr--];
+	identifierLengthPtr--;
+	//type
+	md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
+	//modifiers
+	md.declarationSourceStart = intStack[intPtr--];
+	md.modifiersSourceStart = intStack[intPtr--];
+	md.modifiers = intStack[intPtr--];
+
+	//highlight starts at selector start
+	md.sourceStart = (int) (selectorSourcePositions >>> 32);
+	pushOnAstStack(md);
+	md.bodyStart = scanner.currentPosition-1;
+}
+protected void consumeModifiers() {
+	checkAnnotation(); // might update modifiers with AccDeprecated
+	pushOnIntStack(modifiers); // modifiers
+	pushOnIntStack(modifiersSourceStart);
+	pushOnIntStack(
+		declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
+	resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumePackageDeclarationName() {
+	/* persisting javadoc positions */
+	pushOnIntArrayStack(this.getJavaDocPositions());
+
+	super.consumePackageDeclarationName();
+	ImportReference importReference = compilationUnit.currentPackage;
+
+	requestor.acceptPackage(
+		importReference.declarationSourceStart, 
+		importReference.declarationSourceEnd, 
+		intArrayStack[intArrayPtr--], 
+		CharOperation.concatWith(importReference.getImportName(), '.'),
+		importReference.sourceStart());
+}
+protected void consumePushModifiers() {
+	checkAnnotation(); // might update modifiers with AccDeprecated
+	pushOnIntStack(modifiers); // modifiers
+	if (modifiersSourceStart < 0) {
+		pushOnIntStack(-1);
+		pushOnIntStack(
+			declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
+	} else {
+		pushOnIntStack(modifiersSourceStart);
+		pushOnIntStack(
+			declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
+	}
+	resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeSingleTypeImportDeclarationName() {
+	// SingleTypeImportDeclarationName ::= 'import' Name
+
+	/* persisting javadoc positions */
+	pushOnIntArrayStack(this.getJavaDocPositions());
+
+	super.consumeSingleTypeImportDeclarationName();
+	ImportReference importReference = (ImportReference) astStack[astPtr];
+	requestor.acceptImport(
+		importReference.declarationSourceStart, 
+		importReference.declarationSourceEnd,
+		intArrayStack[intArrayPtr--],
+		CharOperation.concatWith(importReference.getImportName(), '.'),
+		importReference.sourceStart(),
+		false);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeStaticInitializer() {
+	// StaticInitializer ::=  StaticOnly Block
+	//push an Initializer
+	//optimize the push/pop
+	super.consumeStaticInitializer();
+	Initializer initializer = (Initializer) astStack[astPtr];
+	requestor.acceptInitializer(
+		initializer.declarationSourceStart,
+		initializer.declarationSourceEnd,
+		intArrayStack[intArrayPtr--],
+		AccStatic, 
+		intStack[intPtr--], 
+		initializer.block.sourceStart,
+		initializer.declarationSourceEnd);
+}
+protected void consumeStaticOnly() {
+	// StaticOnly ::= 'static'
+	checkAnnotation(); // might update declaration source start
+	pushOnIntStack(modifiersSourceStart);
+	pushOnIntStack(
+		declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
+	jumpOverMethodBody();
+	nestedMethod[nestedType]++;
+	resetModifiers();
+}
+protected void consumeToken(int type) {
+	super.consumeToken(type);
+
+	switch (type) {
+		case TokenNamevoid :
+		case TokenNameboolean :
+		case TokenNamebyte :
+		case TokenNamechar :
+		case TokenNamedouble :
+		case TokenNamefloat :
+		case TokenNameint :
+		case TokenNamelong :
+		case TokenNameshort :
+		// we need this position to know where the base type name ends.
+			pushOnIntStack(scanner.currentPosition - 1);
+			break;
+	}
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeTypeImportOnDemandDeclarationName() {
+	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+
+	/* persisting javadoc positions */
+	pushOnIntArrayStack(this.getJavaDocPositions());
+
+	super.consumeTypeImportOnDemandDeclarationName();
+	ImportReference importReference = (ImportReference) astStack[astPtr];
+	requestor.acceptImport(
+		importReference.declarationSourceStart, 
+		importReference.declarationSourceEnd,
+		intArrayStack[intArrayPtr--],
+		CharOperation.concatWith(importReference.getImportName(), '.'), 
+		importReference.sourceStart(),
+		true);
+}
+public CompilationUnitDeclaration endParse(int act) {
+	if (scanner.recordLineSeparator) {
+		requestor.acceptLineSeparatorPositions(scanner.lineEnds());
+	}
+	return super.endParse(act);
+}
+/*
+ * Flush annotations defined prior to a given positions.
+ *
+ * Note: annotations are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line 
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+ 
+public int flushAnnotationsDefinedPriorTo(int position) {
+
+	return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
+}
+protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
+This variable is a type reference and dim will be its dimensions*/
+
+	int length;
+	TypeReference ref;
+	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+		// single variable reference
+		if (dim == 0) {
+			ref = 
+				new SingleTypeReference(
+					identifierStack[identifierPtr], 
+					identifierPositionStack[identifierPtr--]); 
+		} else {
+			ref = 
+				new ArrayTypeReference(
+					identifierStack[identifierPtr], 
+					dim, 
+					identifierPositionStack[identifierPtr--]); 
+		}
+	} else {
+		if (length < 0) { //flag for precompiled type reference on base types
+			ref = TypeReference.baseTypeReference(-length, dim);
+			ref.sourceEnd = intStack[intPtr--];
+			ref.sourceStart = intStack[intPtr--];
+		} else { //Qualified variable reference
+			char[][] tokens = new char[length][];
+			identifierPtr -= length;
+			long[] positions = new long[length];
+			System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+			System.arraycopy(
+				identifierPositionStack, 
+				identifierPtr + 1, 
+				positions, 
+				0, 
+				length); 
+			if (dim == 0)
+				ref = new QualifiedTypeReference(tokens, positions);
+			else
+				ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+		}
+	};
+	return ref;
+}
+public void initialize() {
+	//positionning the parser for a new compilation unit
+	//avoiding stack reallocation and all that....
+	super.initialize();
+	intArrayPtr = -1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+private boolean isLocalDeclaration() {
+	int nestedDepth = nestedType;
+	while (nestedDepth >= 0) {
+		if (nestedMethod[nestedDepth] != 0) {
+			return true;
+		}
+		nestedDepth--;
+	}
+	return false;
+}
+/*
+ * Investigate one entire unit.
+ */
+public void parseCompilationUnit(ICompilationUnit unit) {
+	char[] regionSource = unit.getContents();
+	try {
+		initialize();
+		goForCompilationUnit();
+		referenceContext =
+			compilationUnit = 
+				compilationUnit = 
+					new CompilationUnitDeclaration(
+						problemReporter(), 
+						new CompilationResult(unit, 0, 0), 
+						regionSource.length); 
+		scanner.resetTo(0, regionSource.length);
+		scanner.setSourceBuffer(regionSource);
+		parse();
+	} catch (AbortCompilation ex) {
+	}
+}
+/*
+ * Investigate one constructor declaration.
+ */
+public void parseConstructor(char[] regionSource) {
+	try {
+		initialize();
+		goForClassBodyDeclarations();
+		referenceContext = 
+			compilationUnit = 
+				compilationUnit = 
+					new CompilationUnitDeclaration(
+						problemReporter(), 
+						new CompilationResult(regionSource, 0, 0), 
+						regionSource.length); 
+		scanner.resetTo(0, regionSource.length);
+		scanner.setSourceBuffer(regionSource);
+		parse();
+	} catch (AbortCompilation ex) {
+	}
+}
+/*
+ * Investigate one field declaration statement (might have multiple declarations in it).
+ */
+public void parseField(char[] regionSource) {
+	try {
+		initialize();
+		goForFieldDeclaration();
+		referenceContext = 
+			compilationUnit = 
+				compilationUnit = 
+					new CompilationUnitDeclaration(
+						problemReporter(), 
+						new CompilationResult(regionSource, 0, 0), 
+						regionSource.length); 
+		scanner.resetTo(0, regionSource.length);
+		scanner.setSourceBuffer(regionSource);
+		parse();
+	} catch (AbortCompilation ex) {
+	}
+
+}
+/*
+ * Investigate one import statement declaration.
+ */
+public void parseImport(char[] regionSource) {
+	try {
+		initialize();
+		goForImportDeclaration();
+		referenceContext = 
+			compilationUnit = 
+				compilationUnit = 
+					new CompilationUnitDeclaration(
+						problemReporter(), 
+						new CompilationResult(regionSource, 0, 0), 
+						regionSource.length); 
+		scanner.resetTo(0, regionSource.length);
+		scanner.setSourceBuffer(regionSource);
+		parse();
+	} catch (AbortCompilation ex) {
+	}
+
+}
+/*
+ * Investigate one initializer declaration.
+ * regionSource need to content exactly an initializer declaration.
+ * e.g: static { i = 4; }
+ * { name = "test"; }
+ */
+public void parseInitializer(char[] regionSource) {
+	try {
+		initialize();
+		goForInitializer();
+		referenceContext = 
+			compilationUnit = 
+				compilationUnit = 
+					new CompilationUnitDeclaration(
+						problemReporter(), 
+						new CompilationResult(regionSource, 0, 0), 
+						regionSource.length); 
+		scanner.resetTo(0, regionSource.length);
+		scanner.setSourceBuffer(regionSource);
+		parse();
+	} catch (AbortCompilation ex) {
+	}
+
+}
+/*
+ * Investigate one method declaration.
+ */
+public void parseMethod(char[] regionSource) {
+	try {
+		initialize();
+		goForGenericMethodDeclaration();
+		referenceContext = 
+			compilationUnit = 
+				compilationUnit = 
+					new CompilationUnitDeclaration(
+						problemReporter(), 
+						new CompilationResult(regionSource, 0, 0), 
+						regionSource.length); 
+		scanner.resetTo(0, regionSource.length);
+		scanner.setSourceBuffer(regionSource);
+		parse();
+	} catch (AbortCompilation ex) {
+	}
+
+}
+/*
+ * Investigate one package statement declaration.
+ */
+public void parsePackage(char[] regionSource) {
+	try {
+		initialize();
+		goForPackageDeclaration();
+		referenceContext = 
+			compilationUnit = 
+				compilationUnit = 
+					new CompilationUnitDeclaration(
+						problemReporter(), 
+						new CompilationResult(regionSource, 0, 0), 
+						regionSource.length); 
+		scanner.resetTo(0, regionSource.length);
+		scanner.setSourceBuffer(regionSource);
+		parse();
+	} catch (AbortCompilation ex) {
+	}
+
+}
+/*
+ * Investigate one type declaration, its fields, methods and member types.
+ */
+public void parseType(char[] regionSource) {
+	try {
+		initialize();
+		goForTypeDeclaration();
+		referenceContext = 
+			compilationUnit = 
+				compilationUnit = 
+					new CompilationUnitDeclaration(
+						problemReporter(), 
+						new CompilationResult(regionSource, 0, 0), 
+						regionSource.length); 
+		scanner.resetTo(0, regionSource.length);
+		scanner.setSourceBuffer(regionSource);
+		parse();
+	} catch (AbortCompilation ex) {
+	}
+
+}
+/**
+ * Returns this parser's problem reporter initialized with its reference context.
+ * Also it is assumed that a problem is going to be reported, so initializes
+ * the compilation result's line positions.
+ */
+public ProblemReporter problemReporter() {
+	problemReporter.referenceContext = referenceContext;
+	return problemReporter;
+}
+protected void pushOnIntArrayStack(int[] positions) {
+
+	try {
+		intArrayStack[++intArrayPtr] = positions;
+	} catch (IndexOutOfBoundsException e) {
+		//intPtr is correct 
+		int oldStackLength = intArrayStack.length;
+		int oldStack[][] = intArrayStack;
+		intArrayStack = new int[oldStackLength + StackIncrement][];
+		System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
+		intArrayStack[intArrayPtr] = positions;
+	}
+}
+protected void resetModifiers() {
+	super.resetModifiers();
+	declarationSourceStart = -1;
+}
+/*
+ * Syntax error was detected. Will attempt to perform some recovery action in order
+ * to resume to the regular parse loop.
+ */
+protected boolean resumeOnSyntaxError() {
+	return false;
+}
+/*
+ * Answer a char array representation of the type name formatted like:
+ * - type name + dimensions
+ * Example:
+ * "A[][]".toCharArray()
+ * "java.lang.String".toCharArray()
+ */
+private char[] returnTypeName(TypeReference type) {
+	int dimension = type.dimensions();
+	if (dimension != 0) {
+		char[] dimensionsArray = new char[dimension * 2];
+		for (int i = 0; i < dimension; i++) {
+			dimensionsArray[i*2] = '[';
+			dimensionsArray[(i*2) + 1] = ']';
+		}
+		return CharOperation.concat(
+			CharOperation.concatWith(type.getTypeName(), '.'), 
+			dimensionsArray); 
+	}
+	return CharOperation.concatWith(type.getTypeName(), '.');
+}
+public String toString() {
+	StringBuffer buffer = new StringBuffer();
+	buffer.append("intArrayPtr = "/*nonNLS*/ + intArrayPtr + "\n"/*nonNLS*/);
+	buffer.append(super.toString());
+	return buffer.toString();
+}
+/**
+ * INTERNAL USE ONLY
+ */
+protected TypeReference typeReference(
+	int dim,
+	int localIdentifierPtr, 
+	int localIdentifierLengthPtr) {
+	/* build a Reference on a variable that may be qualified or not
+	 * This variable is a type reference and dim will be its dimensions.
+	 * We don't have any side effect on the stacks' pointers.
+	 */
+
+	int length;
+	TypeReference ref;
+	if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
+		// single variable reference
+		if (dim == 0) {
+			ref = 
+				new SingleTypeReference(
+					identifierStack[localIdentifierPtr], 
+					identifierPositionStack[localIdentifierPtr--]); 
+		} else {
+			ref = 
+				new ArrayTypeReference(
+					identifierStack[localIdentifierPtr], 
+					dim, 
+					identifierPositionStack[localIdentifierPtr--]); 
+		}
+	} else {
+		if (length < 0) { //flag for precompiled type reference on base types
+			ref = TypeReference.baseTypeReference(-length, dim);
+			ref.sourceEnd = intStack[localIntPtr--];
+			ref.sourceStart = intStack[localIntPtr--];
+		} else { //Qualified variable reference
+			char[][] tokens = new char[length][];
+			localIdentifierPtr -= length;
+			long[] positions = new long[length];
+			System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
+			System.arraycopy(
+				identifierPositionStack, 
+				localIdentifierPtr + 1, 
+				positions, 
+				0, 
+				length); 
+			if (dim == 0)
+				ref = new QualifiedTypeReference(tokens, positions);
+			else
+				ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+		}
+	};
+	return ref;
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java b/compiler/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java
index 5790ba3..d1b9988 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java
@@ -1,16 +1,15 @@
-package org.eclipse.jdt.internal.compiler;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.Compiler;
-
-/**
- * A callback interface for receiving compilation results.
- */
-public interface ICompilerRequestor {
-	/**
-	 * Accept a compilation result.
-	 */
-	public void acceptResult(CompilationResult result);
-}
+package org.eclipse.jdt.internal.compiler;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/**
+ * A callback interface for receiving compilation results.
+ */
+public interface ICompilerRequestor {
+	/**
+	 * Accept a compilation result.
+	 */
+	public void acceptResult(CompilationResult result);
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java b/compiler/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java
index 96ed4b9..9e13486 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java
@@ -1,23 +1,22 @@
-package org.eclipse.jdt.internal.compiler;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
-
-/*
- * Handler policy is responsible to answer the 2 following
- * questions:
- * 1. should the handler stop on first problem which appears
- *	to be a real error (i.e. not a warning),
- * 2. should it proceed once it has gathered all problems
- *
- * The intent is that one can supply its own policy to implement 
- * some interactive error handling strategy where some UI would 
- * display problems and ask user if he wants to proceed or not.
- */
-
-public interface IErrorHandlingPolicy {
-	boolean proceedOnErrors();
-	boolean stopOnFirstError();
-}
+package org.eclipse.jdt.internal.compiler;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/*
+ * Handler policy is responsible to answer the 2 following
+ * questions:
+ * 1. should the handler stop on first problem which appears
+ *	to be a real error (i.e. not a warning),
+ * 2. should it proceed once it has gathered all problems
+ *
+ * The intent is that one can supply its own policy to implement 
+ * some interactive error handling strategy where some UI would 
+ * display problems and ask user if he wants to proceed or not.
+ */
+
+public interface IErrorHandlingPolicy {
+	boolean proceedOnErrors();
+	boolean stopOnFirstError();
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/IProblem.java b/compiler/org/eclipse/jdt/internal/compiler/IProblem.java
index b67f0fe..8871384 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/IProblem.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/IProblem.java
@@ -1,79 +1,78 @@
-package org.eclipse.jdt.internal.compiler;
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
-
-/*
- * Handler policy is responsible to answer the 2 following
- * questions:
- * 1. should the handler stop on first problem which appears
- *	to be a real error (i.e. not a warning),
- * 2. should it proceed once it has gathered all problems
- *
- * The intent is that one can supply its own policy to implement 
- * some interactive error handling strategy where some UI would 
- * display problems and ask user if he wants to proceed or not.
- */
-
-public interface IProblem {
-	final int Error = 1; // when bit is set: problem is error, if not it is a warning
-/**
- * Answer back the original arguments recorded into the problem.
- */
-String[] getArguments();
-/**
- * 
- * @return int
- */
-int getID();
-/**
- * Answer a localized, human-readable message string which describes the problem.
- */
-String getMessage();
-/**
- * Answer the file name in which the problem was found.
- */
-char[] getOriginatingFileName();
-/**
- * Answer the severity of the problem.
- */
-int getSeverity();
-/**
- * Answer the end position of the problem (inclusive), or -1 if unknown.
- */
-int getSourceEnd();
-/**
- * Answer the line number in source where the problem begins.
- */
-int getSourceLineNumber();
-/**
- * Answer the start position of the problem (inclusive), or -1 if unknown.
- */
-int getSourceStart();
-/*
- * Helper method: checks the severity to see if the Error bit is set.
- */
-boolean isError();
-/*
- * Helper method: checks the severity to see if the Error bit is not set.
- */
-boolean isWarning();
-/**
- * Set the end position of the problem (inclusive), or -1 if unknown.
- *
- * Used for shifting problem positions.
- */
-void setSourceEnd(int sourceEnd);
-/**
- * Set the line number in source where the problem begins.
- */
-void setSourceLineNumber(int lineNumber);
-/**
- * Set the start position of the problem (inclusive), or -1 if unknown.
- *
- * Used for shifting problem positions.
- */
-void setSourceStart(int sourceStart);
-}
+package org.eclipse.jdt.internal.compiler;
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+/*
+ * Handler policy is responsible to answer the 2 following
+ * questions:
+ * 1. should the handler stop on first problem which appears
+ *	to be a real error (i.e. not a warning),
+ * 2. should it proceed once it has gathered all problems
+ *
+ * The intent is that one can supply its own policy to implement 
+ * some interactive error handling strategy where some UI would 
+ * display problems and ask user if he wants to proceed or not.
+ */
+
+public interface IProblem {
+	final int Error = 1; // when bit is set: problem is error, if not it is a warning
+/**
+ * Answer back the original arguments recorded into the problem.
+ */
+String[] getArguments();
+/**
+ * 
+ * @return int
+ */
+int getID();
+/**
+ * Answer a localized, human-readable message string which describes the problem.
+ */
+String getMessage();
+/**
+ * Answer the file name in which the problem was found.
+ */
+char[] getOriginatingFileName();
+/**
+ * Answer the severity of the problem.
+ */
+int getSeverity();
+/**
+ * Answer the end position of the problem (inclusive), or -1 if unknown.
+ */
+int getSourceEnd();
+/**
+ * Answer the line number in source where the problem begins.
+ */
+int getSourceLineNumber();
+/**
+ * Answer the start position of the problem (inclusive), or -1 if unknown.
+ */
+int getSourceStart();
+/*
+ * Helper method: checks the severity to see if the Error bit is set.
+ */
+boolean isError();
+/*
+ * Helper method: checks the severity to see if the Error bit is not set.
+ */
+boolean isWarning();
+/**
+ * Set the end position of the problem (inclusive), or -1 if unknown.
+ *
+ * Used for shifting problem positions.
+ */
+void setSourceEnd(int sourceEnd);
+/**
+ * Set the line number in source where the problem begins.
+ */
+void setSourceLineNumber(int lineNumber);
+/**
+ * Set the start position of the problem (inclusive), or -1 if unknown.
+ *
+ * Used for shifting problem positions.
+ */
+void setSourceStart(int sourceStart);
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java
index 4529056..ca700ef 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java
@@ -1,936 +1,884 @@
-package org.eclipse.jdt.internal.compiler;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-/**
- * A source element parser extracts structural and reference information
- * from a piece of source.
- *
- * also see @ISourceElementRequestor
- *
- * The structural investigation includes:
- * - the package statement
- * - import statements
- * - top-level types: package member, member types (member types of member types...)
- * - fields
- * - methods
- *
- * If reference information is requested, then all source constructs are
- * investigated and type, field & method references are provided as well.
- *
- * Any (parsing) problem encountered is also provided.
- */
-import java.lang.reflect.Constructor;
-
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
-
-public class SourceElementParser extends Parser {
-	ISourceElementRequestor requestor;
-	private int fieldCount;
-	private int localIntPtr;
-	private int lastFieldEndPosition;
-	private ISourceType sourceType;
-	private boolean reportReferenceInfo;
-	private char[][] typeNames;
-	private char[][] superTypeNames;
-	private int nestedTypeIndex;
-	private static final char[] JAVA_LANG_OBJECT = "java.lang.Object"/*nonNLS*/.toCharArray();
-public SourceElementParser(
-	final ISourceElementRequestor requestor, 
-	IProblemFactory problemFactory) {
-	// we want to notify all syntax error with the acceptProblem API
-	// To do so, we define the record method of the ProblemReporter
-	super(new ProblemReporter(
-		DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
-		new CompilerOptions(), 
-		problemFactory) {
-		public void record(IProblem problem, CompilationResult unitResult) {
-			unitResult.record(problem);
-			requestor.acceptProblem(problem);
-		}
-	}, false);
-	this.requestor = requestor;
-	typeNames = new char[4][];
-	superTypeNames = new char[4][];
-	nestedTypeIndex = 0;
-}
-protected void classInstanceCreation(boolean alwaysQualified) {
-
-	boolean previousFlag = reportReferenceInfo;
-	reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
-	super.classInstanceCreation(alwaysQualified);
-	reportReferenceInfo = previousFlag;
-	if (reportReferenceInfo){
-		AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
-		TypeReference typeRef = alloc.type;
-		requestor.acceptConstructorReference(
-			typeRef instanceof SingleTypeReference 
-				? ((SingleTypeReference) typeRef).token
-				: CharOperation.concatWith(alloc.type.getTypeName(), '.'),
-			alloc.arguments == null ? 0 : alloc.arguments.length, 
-			alloc.sourceStart);
-	}
-}
-protected void consumeConstructorHeaderName() {
-	// ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
-
-	/* recovering - might be an empty message send */
-	if (currentElement != null){
-		if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
-			lastCheckPoint = scanner.startPosition; // force to restart at this exact position				
-			restartRecovery = true;
-			return;
-		}
-	}
-	SourceConstructorDeclaration cd = new SourceConstructorDeclaration();
-
-	//name -- this is not really revelant but we do .....
-	cd.selector = identifierStack[identifierPtr];
-	long selectorSourcePositions = identifierPositionStack[identifierPtr--];
-	identifierLengthPtr--;
-
-	//modifiers
-	cd.declarationSourceStart = intStack[intPtr--];
-	cd.modifiers = intStack[intPtr--];
-
-	//highlight starts at the selector starts
-	cd.sourceStart = (int) (selectorSourcePositions >>> 32);
-	cd.selectorSourceEnd = (int) selectorSourcePositions;
-	pushOnAstStack(cd);
-
-	cd.sourceEnd = lParenPos;
-	cd.bodyStart = lParenPos+1;
-	listLength = 0; // initialize listLength before reading parameters/throws
-
-	// recovery
-	if (currentElement != null){
-		lastCheckPoint = cd.bodyStart;
-		if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
-			|| cd.modifiers != 0){
-			currentElement = currentElement.add(cd, 0);
-			lastIgnoredToken = -1;
-		}
-	}	
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeExitVariableWithInitialization() {
-	// ExitVariableWithInitialization ::= $empty
-	// the scanner is located after the comma or the semi-colon.
-	// we want to include the comma or the semi-colon
-	super.consumeExitVariableWithInitialization();
-	if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
-		return;
-	((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
-}
-protected void consumeExitVariableWithoutInitialization() {
-	// ExitVariableWithoutInitialization ::= $empty
-	// do nothing by default
-	if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
-		return;
-	((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeFieldAccess(boolean isSuperAccess) {
-	// FieldAccess ::= Primary '.' 'Identifier'
-	// FieldAccess ::= 'super' '.' 'Identifier'
-	super.consumeFieldAccess(isSuperAccess);
-	FieldReference fr = (FieldReference) expressionStack[expressionPtr];
-	if (reportReferenceInfo) {
-		requestor.acceptFieldReference(fr.token, fr.sourceStart);
-	}
-}
-protected void consumeMethodHeaderName() {
-	// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
-	int length;
-	SourceMethodDeclaration md = new SourceMethodDeclaration();
-
-	//name
-	md.selector = identifierStack[identifierPtr];
-	long selectorSourcePositions = identifierPositionStack[identifierPtr--];
-	identifierLengthPtr--;
-	//type
-	md.returnType = getTypeReference(intStack[intPtr--]);
-	//modifiers
-	md.declarationSourceStart = intStack[intPtr--];
-	md.modifiers = intStack[intPtr--];
-
-	//highlight starts at selector start
-	md.sourceStart = (int) (selectorSourcePositions >>> 32);
-	md.selectorSourceEnd = (int) selectorSourcePositions;
-	pushOnAstStack(md);
-	md.sourceEnd = lParenPos;
-	md.bodyStart = lParenPos+1;
-	listLength = 0; // initialize listLength before reading parameters/throws
-	
-	// recovery
-	if (currentElement != null){
-		if (currentElement instanceof RecoveredType 
-			//|| md.modifiers != 0
-			|| (scanner.searchLineNumber(md.returnType.sourceStart)
-					== scanner.searchLineNumber(md.sourceStart))){
-			lastCheckPoint = md.bodyStart;
-			currentElement = currentElement.add(md, 0);
-			lastIgnoredToken = -1;			
-		} else {
-			lastCheckPoint = md.sourceStart;
-			restartRecovery = true;
-		}
-	}		
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodInvocationName() {
-	// MethodInvocation ::= Name '(' ArgumentListopt ')'
-
-	// when the name is only an identifier...we have a message send to "this" (implicit)
-	super.consumeMethodInvocationName();
-	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
-	Expression[] args = messageSend.arguments;
-	if (reportReferenceInfo) {
-		requestor.acceptMethodReference(
-			messageSend.selector, 
-			args == null ? 0 : args.length, 
-			(int)(messageSend.nameSourcePosition >>> 32));
-	}
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodInvocationPrimary() {
-	super.consumeMethodInvocationPrimary();
-	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
-	Expression[] args = messageSend.arguments;
-	if (reportReferenceInfo) {
-		requestor.acceptMethodReference(
-			messageSend.selector, 
-			args == null ? 0 : args.length, 
-			(int)(messageSend.nameSourcePosition >>> 32));
-	}
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void consumeMethodInvocationSuper() {
-	// MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
-	super.consumeMethodInvocationSuper();
-	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
-	Expression[] args = messageSend.arguments;
-	if (reportReferenceInfo) {
-		requestor.acceptMethodReference(
-			messageSend.selector, 
-			args == null ? 0 : args.length, 
-			(int)(messageSend.nameSourcePosition >>> 32));
-	}
-}
-protected void consumeSingleTypeImportDeclarationName() {
-	// SingleTypeImportDeclarationName ::= 'import' Name
-	/* push an ImportRef build from the last name 
-	stored in the identifier stack. */
-
-	super.consumeSingleTypeImportDeclarationName();
-	ImportReference impt = (ImportReference)astStack[astPtr];
-	if (reportReferenceInfo) {
-		requestor.acceptTypeReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
-	}
-}
-protected void consumeTypeImportOnDemandDeclarationName() {
-	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
-	/* push an ImportRef build from the last name 
-	stored in the identifier stack. */
-
-	super.consumeTypeImportOnDemandDeclarationName();
-	ImportReference impt = (ImportReference)astStack[astPtr];
-	if (reportReferenceInfo) {
-		requestor.acceptUnknownReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
-	}
-}
-protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
-	return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
-}
-protected CompilationUnitDeclaration endParse(int act) {
-
-	if (sourceType != null) {
-		if (sourceType.isInterface()) {
-			consumeInterfaceDeclaration();
-		} else {
-			consumeClassDeclaration();
-		}
-	}
-	CompilationUnitDeclaration result = super.endParse(act);
-	notifySourceElementRequestor();
-	return result;
-}
-/*
- * Flush annotations defined prior to a given positions.
- *
- * Note: annotations are stacked in syntactical order
- *
- * Either answer given <position>, or the end position of a comment line 
- * immediately following the <position> (same line)
- *
- * e.g.
- * void foo(){
- * } // end of method foo
- */
- 
-public int flushAnnotationsDefinedPriorTo(int position) {
-
-	return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
-}
-public TypeReference getTypeReference(int dim) {
-	/* build a Reference on a variable that may be qualified or not
-	 * This variable is a type reference and dim will be its dimensions
-	 */
-	int length;
-	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
-		// single variable reference
-		if (dim == 0) {
-			SingleTypeReference ref = 
-				new SingleTypeReference(
-					identifierStack[identifierPtr], 
-					identifierPositionStack[identifierPtr--]);
-			if (reportReferenceInfo) {
-				requestor.acceptTypeReference(ref.token, ref.sourceStart);
-			}
-			return ref;
-		} else {
-			ArrayTypeReference ref = 
-				new ArrayTypeReference(
-					identifierStack[identifierPtr], 
-					dim, 
-					identifierPositionStack[identifierPtr--]); 
-			if (reportReferenceInfo) {
-				requestor.acceptTypeReference(ref.token, ref.sourceStart);
-			}
-			return ref;
-		}
-	} else {
-		if (length < 0) { //flag for precompiled type reference on base types
-			TypeReference ref = TypeReference.baseTypeReference(-length, dim);
-			ref.sourceStart = intStack[intPtr--];
-			return ref;
-		} else { //Qualified variable reference
-			char[][] tokens = new char[length][];
-			identifierPtr -= length;
-			long[] positions = new long[length];
-			System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
-			System.arraycopy(
-				identifierPositionStack, 
-				identifierPtr + 1, 
-				positions, 
-				0, 
-				length); 
-			if (dim == 0) {
-				QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
-				if (reportReferenceInfo) {
-					requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
-				}
-				return ref;
-			} else {
-				ArrayQualifiedTypeReference ref = 
-					new ArrayQualifiedTypeReference(tokens, dim, positions); 
-				if (reportReferenceInfo) {
-					requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
-				}
-				return ref;
-			}
-		}
-	}
-}
-public NameReference getUnspecifiedReference() {
-	/* build a (unspecified) NameReference which may be qualified*/
-
-	int length;
-	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
-		// single variable reference
-		SingleNameReference ref = 
-			new SingleNameReference(
-				identifierStack[identifierPtr], 
-				identifierPositionStack[identifierPtr--]); 
-		if (reportReferenceInfo) {
-			requestor.acceptUnknownReference(ref.token, ref.sourceStart());
-		}
-		return ref;
-	} else {
-		//Qualified variable reference
-		char[][] tokens = new char[length][];
-		identifierPtr -= length;
-		System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
-		QualifiedNameReference ref = 
-			new QualifiedNameReference(
-				tokens, 
-				(int) (identifierPositionStack[identifierPtr + 1] >> 32), 
-		// sourceStart
-		 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
-		if (reportReferenceInfo) {
-			requestor.acceptUnknownReference(
-				ref.tokens, 
-				ref.sourceStart(), 
-				ref.sourceEnd()); 
-		}
-		return ref;
-	}
-}
-public NameReference getUnspecifiedReferenceOptimized() {
-	/* build a (unspecified) NameReference which may be qualified
-	The optimization occurs for qualified reference while we are
-	certain in this case the last item of the qualified name is
-	a field access. This optimization is IMPORTANT while it results
-	that when a NameReference is build, the type checker should always
-	look for that it is not a type reference */
-
-	int length;
-	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
-		// single variable reference
-		SingleNameReference ref = 
-			new SingleNameReference(
-				identifierStack[identifierPtr], 
-				identifierPositionStack[identifierPtr--]); 
-		ref.bits &= ~NameReference.RestrictiveFlagMASK;
-		ref.bits |= LOCAL | FIELD;
-		if (reportReferenceInfo) {
-			requestor.acceptUnknownReference(ref.token, ref.sourceStart());
-		}
-		return ref;
-	}
-
-	//Qualified-variable-reference
-	//In fact it is variable-reference DOT field-ref , but it would result in a type
-	//conflict tha can be only reduce by making a superclass (or inetrface ) between
-	//nameReference and FiledReference or putting FieldReference under NameReference
-	//or else..........This optimisation is not really relevant so just leave as it is
-
-	char[][] tokens = new char[length][];
-	identifierPtr -= length;
-	System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
-	QualifiedNameReference ref = 
-		new QualifiedNameReference(
-			tokens, 
-			(int) (identifierPositionStack[identifierPtr + 1] >> 32), 
-	// sourceStart
-	 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
-	ref.bits &= ~NameReference.RestrictiveFlagMASK;
-	ref.bits |= LOCAL | FIELD;
-	if (reportReferenceInfo) {
-		requestor.acceptUnknownReference(
-			ref.tokens, 
-			ref.sourceStart(), 
-			ref.sourceEnd());
-	}
-	return ref;
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-private boolean isLocalDeclaration() {
-	int nestedDepth = nestedType;
-	while (nestedDepth >= 0) {
-		if (nestedMethod[nestedDepth] != 0) {
-			return true;
-		}
-		nestedDepth--;
-	}
-	return false;
-}
-/*
- * Update the bodyStart of the corresponding parse node
- */
-public void notifySourceElementRequestor() {
-
-	if (sourceType == null){
-		if (scanner.initialPosition == 0) {
-			requestor.enterCompilationUnit();
-		}
-		// first we notify the package declaration
-		ImportReference currentPackage = compilationUnit.currentPackage;
-		if (currentPackage != null) {
-			notifySourceElementRequestor(currentPackage, true);
-		}
-		// then the imports
-		ImportReference[] imports = compilationUnit.imports;
-		if (imports != null) {
-			for (int i = 0, max = imports.length; i < max; i++) {
-				notifySourceElementRequestor(imports[i], false);
-			}
-		}
-	}
-	// then the types contained by this compilation unit
-	TypeDeclaration[] types = compilationUnit.types;
-	if (types != null) {
-		for (int i = 0, max = types.length; i < max; i++) {
-			notifySourceElementRequestor(types[i], sourceType == null);
-		}
-	}
-	if (sourceType == null){
-		if (scanner.eofPosition >= compilationUnit.sourceEnd) {
-			requestor.exitCompilationUnit(compilationUnit.sourceEnd);
-		}
-	}
-}
-/*
- * Update the bodyStart of the corresponding parse node
- */
-public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
-	if (methodDeclaration.isClinit())
-		return;
-
-	if (methodDeclaration.isDefaultConstructor()) {
-		if (reportReferenceInfo) {
-			ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
-			ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
-			if (constructorCall != null) {
-				switch(constructorCall.accessMode) {
-					case ExplicitConstructorCall.This :
-						requestor.acceptConstructorReference(
-							typeNames[nestedTypeIndex-1],
-							constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
-							constructorCall.sourceStart);
-						break;
-					case ExplicitConstructorCall.Super :
-					case ExplicitConstructorCall.ImplicitSuper :					
-						requestor.acceptConstructorReference(
-							superTypeNames[nestedTypeIndex-1],
-							constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
-							constructorCall.sourceStart);
-						break;
-				}
-			}
-		}	
-		return;	
-	}	
-	char[][] argumentTypes = null;
-	char[][] argumentNames = null;
-	Argument[] arguments = methodDeclaration.arguments;
-	if (arguments != null) {
-		int argumentLength = arguments.length;
-		argumentTypes = new char[argumentLength][];
-		argumentNames = new char[argumentLength][];
-		for (int i = 0; i < argumentLength; i++) {
-			argumentTypes[i] = returnTypeName(arguments[i].type);
-			argumentNames[i] = arguments[i].name;
-		}
-	}
-	char[][] thrownExceptionTypes = null;
-	TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
-	if (thrownExceptions != null) {
-		int thrownExceptionLength = thrownExceptions.length;
-		thrownExceptionTypes = new char[thrownExceptionLength][];
-		for (int i = 0; i < thrownExceptionLength; i++) {
-			thrownExceptionTypes[i] = 
-				CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.'); 
-		}
-	}
-	// by default no selector end position
-	int selectorSourceEnd = -1;
-	if (methodDeclaration.isConstructor()) {
-		if (methodDeclaration instanceof SourceConstructorDeclaration) {
-			selectorSourceEnd = 
-				((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd; 
-		}
-		if (scanner.initialPosition <= methodDeclaration.declarationSourceStart) {
-			requestor.enterConstructor(
-				methodDeclaration.declarationSourceStart, 
-				methodDeclaration.modifiers, 
-				methodDeclaration.selector, 
-				methodDeclaration.sourceStart, 
-				selectorSourceEnd, 
-				argumentTypes, 
-				argumentNames, 
-				thrownExceptionTypes);
-			if (reportReferenceInfo) {
-				ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
-				ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
-				if (constructorCall != null) {
-					switch(constructorCall.accessMode) {
-						case ExplicitConstructorCall.This :
-							requestor.acceptConstructorReference(
-								typeNames[nestedTypeIndex-1],
-								constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
-								constructorCall.sourceStart);
-							break;
-						case ExplicitConstructorCall.Super :
-						case ExplicitConstructorCall.ImplicitSuper :
-							requestor.acceptConstructorReference(
-								superTypeNames[nestedTypeIndex-1],
-								constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
-								constructorCall.sourceStart);
-							break;
-					}
-				}
-			}
-		}
-		if (scanner.eofPosition >= methodDeclaration.declarationSourceEnd) {
-			requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
-		}
-		return;
-	}
-	if (methodDeclaration instanceof SourceMethodDeclaration) {
-		selectorSourceEnd = 
-			((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd; 
-	}
-	requestor.enterMethod(
-		methodDeclaration.declarationSourceStart, 
-		methodDeclaration.modifiers, 
-		returnTypeName(((MethodDeclaration) methodDeclaration).returnType), 
-		methodDeclaration.selector, 
-		methodDeclaration.sourceStart, 
-		selectorSourceEnd, 
-		argumentTypes, 
-		argumentNames, 
-		thrownExceptionTypes); 
-	requestor.exitMethod(methodDeclaration.declarationSourceEnd);
-}
-/*
-* Update the bodyStart of the corresponding parse node
-*/
-public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
-	if (fieldDeclaration.isField()) {
-		int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
-		if (fieldDeclaration instanceof SourceFieldDeclaration) {
-			fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
-			if (fieldEndPosition == 0) {
-				// use the declaration source end by default
-				fieldEndPosition = fieldDeclaration.declarationSourceEnd;
-			}
-		}
-		requestor.enterField(
-			fieldDeclaration.declarationSourceStart, 
-			fieldDeclaration.modifiers, 
-			returnTypeName(fieldDeclaration.type), 
-			fieldDeclaration.name, 
-			fieldDeclaration.sourceStart, 
-			fieldDeclaration.sourceEnd); 
-		requestor.exitField(fieldEndPosition);
-
-	} else {
-		requestor.acceptInitializer(
-			fieldDeclaration.modifiers, 
-			fieldDeclaration.declarationSourceStart, 
-			fieldDeclaration.declarationSourceEnd); 
-	}
-}
-public void notifySourceElementRequestor(
-	ImportReference importReference, 
-	boolean isPackage) {
-	if (isPackage) {
-		requestor.acceptPackage(
-			importReference.declarationSourceStart, 
-			importReference.declarationSourceEnd, 
-			CharOperation.concatWith(importReference.getImportName(), '.')); 
-	} else {
-		requestor.acceptImport(
-			importReference.declarationSourceStart, 
-			importReference.declarationSourceEnd, 
-			CharOperation.concatWith(importReference.getImportName(), '.'), 
-			importReference.onDemand); 
-	}
-}
-public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
-	FieldDeclaration[] fields = typeDeclaration.fields;
-	AbstractMethodDeclaration[] methods = typeDeclaration.methods;
-	MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
-	int fieldCount = fields == null ? 0 : fields.length;
-	int methodCount = methods == null ? 0 : methods.length;
-	int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
-	int fieldIndex = 0;
-	int methodIndex = 0;
-	int memberTypeIndex = 0;
-	boolean isInterface = typeDeclaration.isInterface();
-
-	if (notifyTypePresence){
-		char[][] interfaceNames = null;
-		int superInterfacesLength = 0;
-		TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
-		if (superInterfaces != null) {
-			superInterfacesLength = superInterfaces.length;
-			interfaceNames = new char[superInterfacesLength][];
-		}
-		if (superInterfaces != null) {
-			for (int i = 0; i < superInterfacesLength; i++) {
-				interfaceNames[i] = 
-					CharOperation.concatWith(superInterfaces[i].getTypeName(), '.'); 
-			}
-		}
-		if (isInterface) {
-			requestor.enterInterface(
-				typeDeclaration.declarationSourceStart, 
-				typeDeclaration.modifiers, 
-				typeDeclaration.name, 
-				typeDeclaration.sourceStart, 
-				typeDeclaration.sourceEnd, 
-				interfaceNames);
-			if (nestedTypeIndex == typeNames.length) {
-				// need a resize
-				System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
-				System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
-			}
-			typeNames[nestedTypeIndex] = typeDeclaration.name;
-			superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
-		} else {
-			TypeReference superclass = typeDeclaration.superclass;
-			if (superclass == null) {
-				requestor.enterClass(
-					typeDeclaration.declarationSourceStart, 
-					typeDeclaration.modifiers, 
-					typeDeclaration.name, 
-					typeDeclaration.sourceStart, 
-					typeDeclaration.sourceEnd, 
-					null, 
-					interfaceNames); 
-			} else {
-				requestor.enterClass(
-					typeDeclaration.declarationSourceStart, 
-					typeDeclaration.modifiers, 
-					typeDeclaration.name, 
-					typeDeclaration.sourceStart, 
-					typeDeclaration.sourceEnd, 
-					CharOperation.concatWith(superclass.getTypeName(), '.'), 
-					interfaceNames); 
-			}
-			if (nestedTypeIndex == typeNames.length) {
-				// need a resize
-				System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
-				System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
-			}
-			typeNames[nestedTypeIndex] = typeDeclaration.name;
-			superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
-		}
-	}
-	while ((fieldIndex < fieldCount)
-		|| (memberTypeIndex < memberTypeCount)
-		|| (methodIndex < methodCount)) {
-		FieldDeclaration nextFieldDeclaration = null;
-		AbstractMethodDeclaration nextMethodDeclaration = null;
-		TypeDeclaration nextMemberDeclaration = null;
-
-		int position = Integer.MAX_VALUE;
-		int nextDeclarationType = -1;
-		if (fieldIndex < fieldCount) {
-			nextFieldDeclaration = fields[fieldIndex];
-			if (nextFieldDeclaration.declarationSourceStart < position) {
-				position = nextFieldDeclaration.declarationSourceStart;
-				nextDeclarationType = 0; // FIELD
-			}
-		}
-		if (methodIndex < methodCount) {
-			nextMethodDeclaration = methods[methodIndex];
-			if (nextMethodDeclaration.declarationSourceStart < position) {
-				position = nextMethodDeclaration.declarationSourceStart;
-				nextDeclarationType = 1; // METHOD
-			}
-		}
-		if (memberTypeIndex < memberTypeCount) {
-			nextMemberDeclaration = memberTypes[memberTypeIndex];
-			if (nextMemberDeclaration.declarationSourceStart < position) {
-				position = nextMemberDeclaration.declarationSourceStart;
-				nextDeclarationType = 2; // MEMBER
-			}
-		}
-		switch (nextDeclarationType) {
-			case 0 :
-				fieldIndex++;
-				notifySourceElementRequestor(nextFieldDeclaration);
-				break;
-			case 1 :
-				methodIndex++;
-				notifySourceElementRequestor(nextMethodDeclaration);
-				break;
-			case 2 :
-				memberTypeIndex++;
-				notifySourceElementRequestor(nextMemberDeclaration, true);
-		}
-	}
-	if (notifyTypePresence){
-		if (isInterface) {
-			requestor.exitInterface(typeDeclaration.declarationSourceEnd);
-		} else {
-			requestor.exitClass(typeDeclaration.declarationSourceEnd);
-		}
-		nestedTypeIndex--;
-	}
-}
-public void parseCompilationUnit(
-	ICompilationUnit unit, 
-	int start, 
-	int end, 
-	boolean needReferenceInfo) {
-
-	CompilationUnitDeclaration result;
-	reportReferenceInfo = needReferenceInfo;
-	boolean old = diet;
-	try {
-		diet = !needReferenceInfo;
-		CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
-		result = parse(unit, compilationUnitResult, start, end);
-	} catch (AbortCompilation e) {
-	} finally {
-		if (scanner.recordLineSeparator) {
-			requestor.acceptLineSeparatorPositions(scanner.lineEnds());
-		}
-		diet = old;
-	}
-}
-public void parseCompilationUnit(
-	ICompilationUnit unit, 
-	boolean needReferenceInfo) {
-
-	CompilationUnitDeclaration result;
-	boolean old = diet;
-	try {
-		diet = !needReferenceInfo;
-		reportReferenceInfo = needReferenceInfo;
-		CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
-		result = parse(unit, compilationUnitResult);
-	} catch (AbortCompilation e) {
-	} finally {
-		if (scanner.recordLineSeparator) {
-			requestor.acceptLineSeparatorPositions(scanner.lineEnds());
-		}
-		diet = old;
-	}
-}
-public void parseTypeMemberDeclarations(
-	ISourceType sourceType, 
-	ICompilationUnit sourceUnit, 
-	int start, 
-	int end, 
-	boolean needReferenceInfo) {
-
-	boolean old = diet;
-	try {
-		diet = !needReferenceInfo;
-		reportReferenceInfo = needReferenceInfo;
-		CompilationResult compilationUnitResult = 
-			new CompilationResult(sourceUnit, 0, 0); 
-
-		CompilationUnitDeclaration unit = 
-			SourceTypeConverter.buildCompilationUnit(
-				sourceType, 
-				false,
-				false, 
-				problemReporter(), 
-				compilationUnitResult); 
-		if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
-			return;
-
-		this.sourceType = sourceType;
-
-		try {
-			/* automaton initialization */
-			initialize();
-			goForClassBodyDeclarations();
-			/* scanner initialization */
-			scanner.setSourceBuffer(sourceUnit.getContents());
-			int sourceLength = scanner.source.length;
-			scanner.resetTo(start, end);
-			/* unit creation */
-			referenceContext = compilationUnit = unit;
-
-			/* initialize the astStacl */
-			// the compilationUnitDeclaration should contain exactly one type
-			pushOnAstStack(unit.types[0]);
-			/* run automaton */
-			parse();
-		} finally {
-			unit = compilationUnit;
-			compilationUnit = null; // reset parser
-		}
-	} catch (AbortCompilation e) {
-	} finally {
-		if (scanner.recordLineSeparator) {
-			requestor.acceptLineSeparatorPositions(scanner.lineEnds());
-		}
-		diet = old;
-	}
-}
-/*
- * Answer a char array representation of the type name formatted like:
- * - type name + dimensions
- * Example:
- * "A[][]".toCharArray()
- * "java.lang.String".toCharArray()
- */
-private char[] returnTypeName(TypeReference type) {
-	if (type == null)
-		return null;
-	int dimension = type.dimensions();
-	if (dimension != 0) {
-		char[] dimensionsArray = new char[dimension * 2];
-		for (int i = 0; i < dimension; i++) {
-			dimensionsArray[i * 2] = '[';
-			dimensionsArray[(i * 2) + 1] = ']';
-		}
-		return CharOperation.concat(
-			CharOperation.concatWith(type.getTypeName(), '.'), 
-			dimensionsArray); 
-	}
-	return CharOperation.concatWith(type.getTypeName(), '.');
-}
-private TypeReference typeReference(
-	int dim, 
-	int localIdentifierPtr, 
-	int localIdentifierLengthPtr) {
-	/* build a Reference on a variable that may be qualified or not
-	 * This variable is a type reference and dim will be its dimensions.
-	 * We don't have any side effect on the stacks' pointers.
-	 */
-
-	int length;
-	TypeReference ref;
-	if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
-		// single variable reference
-		if (dim == 0) {
-			ref = 
-				new SingleTypeReference(
-					identifierStack[localIdentifierPtr], 
-					identifierPositionStack[localIdentifierPtr--]); 
-		} else {
-			ref = 
-				new ArrayTypeReference(
-					identifierStack[localIdentifierPtr], 
-					dim, 
-					identifierPositionStack[localIdentifierPtr--]); 
-		}
-	} else {
-		if (length < 0) { //flag for precompiled type reference on base types
-			ref = TypeReference.baseTypeReference(-length, dim);
-			ref.sourceStart = intStack[localIntPtr--];
-		} else { //Qualified variable reference
-			char[][] tokens = new char[length][];
-			localIdentifierPtr -= length;
-			long[] positions = new long[length];
-			System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
-			System.arraycopy(
-				identifierPositionStack, 
-				localIdentifierPtr + 1, 
-				positions, 
-				0, 
-				length); 
-			if (dim == 0)
-				ref = new QualifiedTypeReference(tokens, positions);
-			else
-				ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
-		}
-	};
-	return ref;
-}
-}
+package org.eclipse.jdt.internal.compiler;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+/**
+ * A source element parser extracts structural and reference information
+ * from a piece of source.
+ *
+ * also see @ISourceElementRequestor
+ *
+ * The structural investigation includes:
+ * - the package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * If reference information is requested, then all source constructs are
+ * investigated and type, field & method references are provided as well.
+ *
+ * Any (parsing) problem encountered is also provided.
+ */
+
+import org.eclipse.jdt.internal.compiler.env.*;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+
+public class SourceElementParser extends Parser {
+	ISourceElementRequestor requestor;
+	private int lastFieldEndPosition;
+	private ISourceType sourceType;
+	private boolean reportReferenceInfo;
+	private char[][] typeNames;
+	private char[][] superTypeNames;
+	private int nestedTypeIndex;
+	private static final char[] JAVA_LANG_OBJECT = "java.lang.Object"/*nonNLS*/.toCharArray();
+public SourceElementParser(
+	final ISourceElementRequestor requestor, 
+	IProblemFactory problemFactory) {
+	// we want to notify all syntax error with the acceptProblem API
+	// To do so, we define the record method of the ProblemReporter
+	super(new ProblemReporter(
+		DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
+		new CompilerOptions(), 
+		problemFactory) {
+		public void record(IProblem problem, CompilationResult unitResult) {
+			unitResult.record(problem);
+			requestor.acceptProblem(problem);
+		}
+	}, false);
+	this.requestor = requestor;
+	typeNames = new char[4][];
+	superTypeNames = new char[4][];
+	nestedTypeIndex = 0;
+}
+protected void classInstanceCreation(boolean alwaysQualified) {
+
+	boolean previousFlag = reportReferenceInfo;
+	reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
+	super.classInstanceCreation(alwaysQualified);
+	reportReferenceInfo = previousFlag;
+	if (reportReferenceInfo){
+		AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
+		TypeReference typeRef = alloc.type;
+		requestor.acceptConstructorReference(
+			typeRef instanceof SingleTypeReference 
+				? ((SingleTypeReference) typeRef).token
+				: CharOperation.concatWith(alloc.type.getTypeName(), '.'),
+			alloc.arguments == null ? 0 : alloc.arguments.length, 
+			alloc.sourceStart);
+	}
+}
+protected void consumeConstructorHeaderName() {
+	// ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
+
+	/* recovering - might be an empty message send */
+	if (currentElement != null){
+		if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
+			lastCheckPoint = scanner.startPosition; // force to restart at this exact position				
+			restartRecovery = true;
+			return;
+		}
+	}
+	SourceConstructorDeclaration cd = new SourceConstructorDeclaration();
+
+	//name -- this is not really revelant but we do .....
+	cd.selector = identifierStack[identifierPtr];
+	long selectorSourcePositions = identifierPositionStack[identifierPtr--];
+	identifierLengthPtr--;
+
+	//modifiers
+	cd.declarationSourceStart = intStack[intPtr--];
+	cd.modifiers = intStack[intPtr--];
+
+	//highlight starts at the selector starts
+	cd.sourceStart = (int) (selectorSourcePositions >>> 32);
+	cd.selectorSourceEnd = (int) selectorSourcePositions;
+	pushOnAstStack(cd);
+
+	cd.sourceEnd = lParenPos;
+	cd.bodyStart = lParenPos+1;
+	listLength = 0; // initialize listLength before reading parameters/throws
+
+	// recovery
+	if (currentElement != null){
+		lastCheckPoint = cd.bodyStart;
+		if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
+			|| cd.modifiers != 0){
+			currentElement = currentElement.add(cd, 0);
+			lastIgnoredToken = -1;
+		}
+	}	
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeExitVariableWithInitialization() {
+	// ExitVariableWithInitialization ::= $empty
+	// the scanner is located after the comma or the semi-colon.
+	// we want to include the comma or the semi-colon
+	super.consumeExitVariableWithInitialization();
+	if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
+		return;
+	((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+}
+protected void consumeExitVariableWithoutInitialization() {
+	// ExitVariableWithoutInitialization ::= $empty
+	// do nothing by default
+	if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
+		return;
+	((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeFieldAccess(boolean isSuperAccess) {
+	// FieldAccess ::= Primary '.' 'Identifier'
+	// FieldAccess ::= 'super' '.' 'Identifier'
+	super.consumeFieldAccess(isSuperAccess);
+	FieldReference fr = (FieldReference) expressionStack[expressionPtr];
+	if (reportReferenceInfo) {
+		requestor.acceptFieldReference(fr.token, fr.sourceStart);
+	}
+}
+protected void consumeMethodHeaderName() {
+	// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+	int length;
+	SourceMethodDeclaration md = new SourceMethodDeclaration();
+
+	//name
+	md.selector = identifierStack[identifierPtr];
+	long selectorSourcePositions = identifierPositionStack[identifierPtr--];
+	identifierLengthPtr--;
+	//type
+	md.returnType = getTypeReference(intStack[intPtr--]);
+	//modifiers
+	md.declarationSourceStart = intStack[intPtr--];
+	md.modifiers = intStack[intPtr--];
+
+	//highlight starts at selector start
+	md.sourceStart = (int) (selectorSourcePositions >>> 32);
+	md.selectorSourceEnd = (int) selectorSourcePositions;
+	pushOnAstStack(md);
+	md.sourceEnd = lParenPos;
+	md.bodyStart = lParenPos+1;
+	listLength = 0; // initialize listLength before reading parameters/throws
+	
+	// recovery
+	if (currentElement != null){
+		if (currentElement instanceof RecoveredType 
+			//|| md.modifiers != 0
+			|| (scanner.searchLineNumber(md.returnType.sourceStart)
+					== scanner.searchLineNumber(md.sourceStart))){
+			lastCheckPoint = md.bodyStart;
+			currentElement = currentElement.add(md, 0);
+			lastIgnoredToken = -1;			
+		} else {
+			lastCheckPoint = md.sourceStart;
+			restartRecovery = true;
+		}
+	}		
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodInvocationName() {
+	// MethodInvocation ::= Name '(' ArgumentListopt ')'
+
+	// when the name is only an identifier...we have a message send to "this" (implicit)
+	super.consumeMethodInvocationName();
+	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+	Expression[] args = messageSend.arguments;
+	if (reportReferenceInfo) {
+		requestor.acceptMethodReference(
+			messageSend.selector, 
+			args == null ? 0 : args.length, 
+			(int)(messageSend.nameSourcePosition >>> 32));
+	}
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodInvocationPrimary() {
+	super.consumeMethodInvocationPrimary();
+	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+	Expression[] args = messageSend.arguments;
+	if (reportReferenceInfo) {
+		requestor.acceptMethodReference(
+			messageSend.selector, 
+			args == null ? 0 : args.length, 
+			(int)(messageSend.nameSourcePosition >>> 32));
+	}
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodInvocationSuper() {
+	// MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
+	super.consumeMethodInvocationSuper();
+	MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+	Expression[] args = messageSend.arguments;
+	if (reportReferenceInfo) {
+		requestor.acceptMethodReference(
+			messageSend.selector, 
+			args == null ? 0 : args.length, 
+			(int)(messageSend.nameSourcePosition >>> 32));
+	}
+}
+protected void consumeSingleTypeImportDeclarationName() {
+	// SingleTypeImportDeclarationName ::= 'import' Name
+	/* push an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	super.consumeSingleTypeImportDeclarationName();
+	ImportReference impt = (ImportReference)astStack[astPtr];
+	if (reportReferenceInfo) {
+		requestor.acceptTypeReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
+	}
+}
+protected void consumeTypeImportOnDemandDeclarationName() {
+	// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+	/* push an ImportRef build from the last name 
+	stored in the identifier stack. */
+
+	super.consumeTypeImportOnDemandDeclarationName();
+	ImportReference impt = (ImportReference)astStack[astPtr];
+	if (reportReferenceInfo) {
+		requestor.acceptUnknownReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
+	}
+}
+protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+	return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
+}
+protected CompilationUnitDeclaration endParse(int act) {
+
+	if (sourceType != null) {
+		if (sourceType.isInterface()) {
+			consumeInterfaceDeclaration();
+		} else {
+			consumeClassDeclaration();
+		}
+	}
+	CompilationUnitDeclaration result = super.endParse(act);
+	notifySourceElementRequestor();
+	return result;
+}
+/*
+ * Flush annotations defined prior to a given positions.
+ *
+ * Note: annotations are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line 
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+ 
+public int flushAnnotationsDefinedPriorTo(int position) {
+
+	return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
+}
+public TypeReference getTypeReference(int dim) {
+	/* build a Reference on a variable that may be qualified or not
+	 * This variable is a type reference and dim will be its dimensions
+	 */
+	int length;
+	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+		// single variable reference
+		if (dim == 0) {
+			SingleTypeReference ref = 
+				new SingleTypeReference(
+					identifierStack[identifierPtr], 
+					identifierPositionStack[identifierPtr--]);
+			if (reportReferenceInfo) {
+				requestor.acceptTypeReference(ref.token, ref.sourceStart);
+			}
+			return ref;
+		} else {
+			ArrayTypeReference ref = 
+				new ArrayTypeReference(
+					identifierStack[identifierPtr], 
+					dim, 
+					identifierPositionStack[identifierPtr--]); 
+			if (reportReferenceInfo) {
+				requestor.acceptTypeReference(ref.token, ref.sourceStart);
+			}
+			return ref;
+		}
+	} else {
+		if (length < 0) { //flag for precompiled type reference on base types
+			TypeReference ref = TypeReference.baseTypeReference(-length, dim);
+			ref.sourceStart = intStack[intPtr--];
+			return ref;
+		} else { //Qualified variable reference
+			char[][] tokens = new char[length][];
+			identifierPtr -= length;
+			long[] positions = new long[length];
+			System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+			System.arraycopy(
+				identifierPositionStack, 
+				identifierPtr + 1, 
+				positions, 
+				0, 
+				length); 
+			if (dim == 0) {
+				QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
+				if (reportReferenceInfo) {
+					requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
+				}
+				return ref;
+			} else {
+				ArrayQualifiedTypeReference ref = 
+					new ArrayQualifiedTypeReference(tokens, dim, positions); 
+				if (reportReferenceInfo) {
+					requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
+				}
+				return ref;
+			}
+		}
+	}
+}
+public NameReference getUnspecifiedReference() {
+	/* build a (unspecified) NameReference which may be qualified*/
+
+	int length;
+	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+		// single variable reference
+		SingleNameReference ref = 
+			new SingleNameReference(
+				identifierStack[identifierPtr], 
+				identifierPositionStack[identifierPtr--]); 
+		if (reportReferenceInfo) {
+			requestor.acceptUnknownReference(ref.token, ref.sourceStart());
+		}
+		return ref;
+	} else {
+		//Qualified variable reference
+		char[][] tokens = new char[length][];
+		identifierPtr -= length;
+		System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+		QualifiedNameReference ref = 
+			new QualifiedNameReference(
+				tokens, 
+				(int) (identifierPositionStack[identifierPtr + 1] >> 32), 
+		// sourceStart
+		 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+		if (reportReferenceInfo) {
+			requestor.acceptUnknownReference(
+				ref.tokens, 
+				ref.sourceStart(), 
+				ref.sourceEnd()); 
+		}
+		return ref;
+	}
+}
+public NameReference getUnspecifiedReferenceOptimized() {
+	/* build a (unspecified) NameReference which may be qualified
+	The optimization occurs for qualified reference while we are
+	certain in this case the last item of the qualified name is
+	a field access. This optimization is IMPORTANT while it results
+	that when a NameReference is build, the type checker should always
+	look for that it is not a type reference */
+
+	int length;
+	if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+		// single variable reference
+		SingleNameReference ref = 
+			new SingleNameReference(
+				identifierStack[identifierPtr], 
+				identifierPositionStack[identifierPtr--]); 
+		ref.bits &= ~NameReference.RestrictiveFlagMASK;
+		ref.bits |= LOCAL | FIELD;
+		if (reportReferenceInfo) {
+			requestor.acceptUnknownReference(ref.token, ref.sourceStart());
+		}
+		return ref;
+	}
+
+	//Qualified-variable-reference
+	//In fact it is variable-reference DOT field-ref , but it would result in a type
+	//conflict tha can be only reduce by making a superclass (or inetrface ) between
+	//nameReference and FiledReference or putting FieldReference under NameReference
+	//or else..........This optimisation is not really relevant so just leave as it is
+
+	char[][] tokens = new char[length][];
+	identifierPtr -= length;
+	System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+	QualifiedNameReference ref = 
+		new QualifiedNameReference(
+			tokens, 
+			(int) (identifierPositionStack[identifierPtr + 1] >> 32), 
+	// sourceStart
+	 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+	ref.bits &= ~NameReference.RestrictiveFlagMASK;
+	ref.bits |= LOCAL | FIELD;
+	if (reportReferenceInfo) {
+		requestor.acceptUnknownReference(
+			ref.tokens, 
+			ref.sourceStart(), 
+			ref.sourceEnd());
+	}
+	return ref;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+private boolean isLocalDeclaration() {
+	int nestedDepth = nestedType;
+	while (nestedDepth >= 0) {
+		if (nestedMethod[nestedDepth] != 0) {
+			return true;
+		}
+		nestedDepth--;
+	}
+	return false;
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void notifySourceElementRequestor() {
+
+	if (sourceType == null){
+		if (scanner.initialPosition == 0) {
+			requestor.enterCompilationUnit();
+		}
+		// first we notify the package declaration
+		ImportReference currentPackage = compilationUnit.currentPackage;
+		if (currentPackage != null) {
+			notifySourceElementRequestor(currentPackage, true);
+		}
+		// then the imports
+		ImportReference[] imports = compilationUnit.imports;
+		if (imports != null) {
+			for (int i = 0, max = imports.length; i < max; i++) {
+				notifySourceElementRequestor(imports[i], false);
+			}
+		}
+	}
+	// then the types contained by this compilation unit
+	TypeDeclaration[] types = compilationUnit.types;
+	if (types != null) {
+		for (int i = 0, max = types.length; i < max; i++) {
+			notifySourceElementRequestor(types[i], sourceType == null);
+		}
+	}
+	if (sourceType == null){
+		if (scanner.eofPosition >= compilationUnit.sourceEnd) {
+			requestor.exitCompilationUnit(compilationUnit.sourceEnd);
+		}
+	}
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
+	if (methodDeclaration.isClinit())
+		return;
+
+	if (methodDeclaration.isDefaultConstructor()) {
+		if (reportReferenceInfo) {
+			ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+			ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+			if (constructorCall != null) {
+				switch(constructorCall.accessMode) {
+					case ExplicitConstructorCall.This :
+						requestor.acceptConstructorReference(
+							typeNames[nestedTypeIndex-1],
+							constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
+							constructorCall.sourceStart);
+						break;
+					case ExplicitConstructorCall.Super :
+					case ExplicitConstructorCall.ImplicitSuper :					
+						requestor.acceptConstructorReference(
+							superTypeNames[nestedTypeIndex-1],
+							constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
+							constructorCall.sourceStart);
+						break;
+				}
+			}
+		}	
+		return;	
+	}	
+	char[][] argumentTypes = null;
+	char[][] argumentNames = null;
+	Argument[] arguments = methodDeclaration.arguments;
+	if (arguments != null) {
+		int argumentLength = arguments.length;
+		argumentTypes = new char[argumentLength][];
+		argumentNames = new char[argumentLength][];
+		for (int i = 0; i < argumentLength; i++) {
+			argumentTypes[i] = returnTypeName(arguments[i].type);
+			argumentNames[i] = arguments[i].name;
+		}
+	}
+	char[][] thrownExceptionTypes = null;
+	TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
+	if (thrownExceptions != null) {
+		int thrownExceptionLength = thrownExceptions.length;
+		thrownExceptionTypes = new char[thrownExceptionLength][];
+		for (int i = 0; i < thrownExceptionLength; i++) {
+			thrownExceptionTypes[i] = 
+				CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.'); 
+		}
+	}
+	// by default no selector end position
+	int selectorSourceEnd = -1;
+	if (methodDeclaration.isConstructor()) {
+		if (methodDeclaration instanceof SourceConstructorDeclaration) {
+			selectorSourceEnd = 
+				((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd; 
+		}
+		if (scanner.initialPosition <= methodDeclaration.declarationSourceStart) {
+			requestor.enterConstructor(
+				methodDeclaration.declarationSourceStart, 
+				methodDeclaration.modifiers, 
+				methodDeclaration.selector, 
+				methodDeclaration.sourceStart, 
+				selectorSourceEnd, 
+				argumentTypes, 
+				argumentNames, 
+				thrownExceptionTypes);
+			if (reportReferenceInfo) {
+				ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+				ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+				if (constructorCall != null) {
+					switch(constructorCall.accessMode) {
+						case ExplicitConstructorCall.This :
+							requestor.acceptConstructorReference(
+								typeNames[nestedTypeIndex-1],
+								constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
+								constructorCall.sourceStart);
+							break;
+						case ExplicitConstructorCall.Super :
+						case ExplicitConstructorCall.ImplicitSuper :
+							requestor.acceptConstructorReference(
+								superTypeNames[nestedTypeIndex-1],
+								constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
+								constructorCall.sourceStart);
+							break;
+					}
+				}
+			}
+		}
+		if (scanner.eofPosition >= methodDeclaration.declarationSourceEnd) {
+			requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
+		}
+		return;
+	}
+	if (methodDeclaration instanceof SourceMethodDeclaration) {
+		selectorSourceEnd = 
+			((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd; 
+	}
+	requestor.enterMethod(
+		methodDeclaration.declarationSourceStart, 
+		methodDeclaration.modifiers, 
+		returnTypeName(((MethodDeclaration) methodDeclaration).returnType), 
+		methodDeclaration.selector, 
+		methodDeclaration.sourceStart, 
+		selectorSourceEnd, 
+		argumentTypes, 
+		argumentNames, 
+		thrownExceptionTypes); 
+	requestor.exitMethod(methodDeclaration.declarationSourceEnd);
+}
+/*
+* Update the bodyStart of the corresponding parse node
+*/
+public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
+	if (fieldDeclaration.isField()) {
+		int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
+		if (fieldDeclaration instanceof SourceFieldDeclaration) {
+			fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
+			if (fieldEndPosition == 0) {
+				// use the declaration source end by default
+				fieldEndPosition = fieldDeclaration.declarationSourceEnd;
+			}
+		}
+		requestor.enterField(
+			fieldDeclaration.declarationSourceStart, 
+			fieldDeclaration.modifiers, 
+			returnTypeName(fieldDeclaration.type), 
+			fieldDeclaration.name, 
+			fieldDeclaration.sourceStart, 
+			fieldDeclaration.sourceEnd); 
+		requestor.exitField(fieldEndPosition);
+
+	} else {
+		requestor.acceptInitializer(
+			fieldDeclaration.modifiers, 
+			fieldDeclaration.declarationSourceStart, 
+			fieldDeclaration.declarationSourceEnd); 
+	}
+}
+public void notifySourceElementRequestor(
+	ImportReference importReference, 
+	boolean isPackage) {
+	if (isPackage) {
+		requestor.acceptPackage(
+			importReference.declarationSourceStart, 
+			importReference.declarationSourceEnd, 
+			CharOperation.concatWith(importReference.getImportName(), '.')); 
+	} else {
+		requestor.acceptImport(
+			importReference.declarationSourceStart, 
+			importReference.declarationSourceEnd, 
+			CharOperation.concatWith(importReference.getImportName(), '.'), 
+			importReference.onDemand); 
+	}
+}
+public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
+	FieldDeclaration[] fields = typeDeclaration.fields;
+	AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+	MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
+	int fieldCount = fields == null ? 0 : fields.length;
+	int methodCount = methods == null ? 0 : methods.length;
+	int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
+	int fieldIndex = 0;
+	int methodIndex = 0;
+	int memberTypeIndex = 0;
+	boolean isInterface = typeDeclaration.isInterface();
+
+	if (notifyTypePresence){
+		char[][] interfaceNames = null;
+		int superInterfacesLength = 0;
+		TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+		if (superInterfaces != null) {
+			superInterfacesLength = superInterfaces.length;
+			interfaceNames = new char[superInterfacesLength][];
+		}
+		if (superInterfaces != null) {
+			for (int i = 0; i < superInterfacesLength; i++) {
+				interfaceNames[i] = 
+					CharOperation.concatWith(superInterfaces[i].getTypeName(), '.'); 
+			}
+		}
+		if (isInterface) {
+			requestor.enterInterface(
+				typeDeclaration.declarationSourceStart, 
+				typeDeclaration.modifiers, 
+				typeDeclaration.name, 
+				typeDeclaration.sourceStart, 
+				typeDeclaration.sourceEnd, 
+				interfaceNames);
+			if (nestedTypeIndex == typeNames.length) {
+				// need a resize
+				System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+				System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+			}
+			typeNames[nestedTypeIndex] = typeDeclaration.name;
+			superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
+		} else {
+			TypeReference superclass = typeDeclaration.superclass;
+			if (superclass == null) {
+				requestor.enterClass(
+					typeDeclaration.declarationSourceStart, 
+					typeDeclaration.modifiers, 
+					typeDeclaration.name, 
+					typeDeclaration.sourceStart, 
+					typeDeclaration.sourceEnd, 
+					null, 
+					interfaceNames); 
+			} else {
+				requestor.enterClass(
+					typeDeclaration.declarationSourceStart, 
+					typeDeclaration.modifiers, 
+					typeDeclaration.name, 
+					typeDeclaration.sourceStart, 
+					typeDeclaration.sourceEnd, 
+					CharOperation.concatWith(superclass.getTypeName(), '.'), 
+					interfaceNames); 
+			}
+			if (nestedTypeIndex == typeNames.length) {
+				// need a resize
+				System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+				System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+			}
+			typeNames[nestedTypeIndex] = typeDeclaration.name;
+			superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
+		}
+	}
+	while ((fieldIndex < fieldCount)
+		|| (memberTypeIndex < memberTypeCount)
+		|| (methodIndex < methodCount)) {
+		FieldDeclaration nextFieldDeclaration = null;
+		AbstractMethodDeclaration nextMethodDeclaration = null;
+		TypeDeclaration nextMemberDeclaration = null;
+
+		int position = Integer.MAX_VALUE;
+		int nextDeclarationType = -1;
+		if (fieldIndex < fieldCount) {
+			nextFieldDeclaration = fields[fieldIndex];
+			if (nextFieldDeclaration.declarationSourceStart < position) {
+				position = nextFieldDeclaration.declarationSourceStart;
+				nextDeclarationType = 0; // FIELD
+			}
+		}
+		if (methodIndex < methodCount) {
+			nextMethodDeclaration = methods[methodIndex];
+			if (nextMethodDeclaration.declarationSourceStart < position) {
+				position = nextMethodDeclaration.declarationSourceStart;
+				nextDeclarationType = 1; // METHOD
+			}
+		}
+		if (memberTypeIndex < memberTypeCount) {
+			nextMemberDeclaration = memberTypes[memberTypeIndex];
+			if (nextMemberDeclaration.declarationSourceStart < position) {
+				position = nextMemberDeclaration.declarationSourceStart;
+				nextDeclarationType = 2; // MEMBER
+			}
+		}
+		switch (nextDeclarationType) {
+			case 0 :
+				fieldIndex++;
+				notifySourceElementRequestor(nextFieldDeclaration);
+				break;
+			case 1 :
+				methodIndex++;
+				notifySourceElementRequestor(nextMethodDeclaration);
+				break;
+			case 2 :
+				memberTypeIndex++;
+				notifySourceElementRequestor(nextMemberDeclaration, true);
+		}
+	}
+	if (notifyTypePresence){
+		if (isInterface) {
+			requestor.exitInterface(typeDeclaration.declarationSourceEnd);
+		} else {
+			requestor.exitClass(typeDeclaration.declarationSourceEnd);
+		}
+		nestedTypeIndex--;
+	}
+}
+public void parseCompilationUnit(
+	ICompilationUnit unit, 
+	int start, 
+	int end, 
+	boolean needReferenceInfo) {
+
+	CompilationUnitDeclaration result;
+	reportReferenceInfo = needReferenceInfo;
+	boolean old = diet;
+	try {
+		diet = !needReferenceInfo;
+		CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
+		result = parse(unit, compilationUnitResult, start, end);
+	} catch (AbortCompilation e) {
+	} finally {
+		if (scanner.recordLineSeparator) {
+			requestor.acceptLineSeparatorPositions(scanner.lineEnds());
+		}
+		diet = old;
+	}
+}
+public void parseCompilationUnit(
+	ICompilationUnit unit, 
+	boolean needReferenceInfo) {
+
+	CompilationUnitDeclaration result;
+	boolean old = diet;
+	try {
+		diet = !needReferenceInfo;
+		reportReferenceInfo = needReferenceInfo;
+		CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
+		result = parse(unit, compilationUnitResult);
+	} catch (AbortCompilation e) {
+	} finally {
+		if (scanner.recordLineSeparator) {
+			requestor.acceptLineSeparatorPositions(scanner.lineEnds());
+		}
+		diet = old;
+	}
+}
+public void parseTypeMemberDeclarations(
+	ISourceType sourceType, 
+	ICompilationUnit sourceUnit, 
+	int start, 
+	int end, 
+	boolean needReferenceInfo) {
+
+	boolean old = diet;
+	try {
+		diet = !needReferenceInfo;
+		reportReferenceInfo = needReferenceInfo;
+		CompilationResult compilationUnitResult = 
+			new CompilationResult(sourceUnit, 0, 0); 
+
+		CompilationUnitDeclaration unit = 
+			SourceTypeConverter.buildCompilationUnit(
+				sourceType, 
+				false,
+				false, 
+				problemReporter(), 
+				compilationUnitResult); 
+		if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
+			return;
+
+		this.sourceType = sourceType;
+
+		try {
+			/* automaton initialization */
+			initialize();
+			goForClassBodyDeclarations();
+			/* scanner initialization */
+			scanner.setSourceBuffer(sourceUnit.getContents());
+			int sourceLength = scanner.source.length;
+			scanner.resetTo(start, end);
+			/* unit creation */
+			referenceContext = compilationUnit = unit;
+
+			/* initialize the astStacl */
+			// the compilationUnitDeclaration should contain exactly one type
+			pushOnAstStack(unit.types[0]);
+			/* run automaton */
+			parse();
+		} finally {
+			unit = compilationUnit;
+			compilationUnit = null; // reset parser
+		}
+	} catch (AbortCompilation e) {
+	} finally {
+		if (scanner.recordLineSeparator) {
+			requestor.acceptLineSeparatorPositions(scanner.lineEnds());
+		}
+		diet = old;
+	}
+}
+/*
+ * Answer a char array representation of the type name formatted like:
+ * - type name + dimensions
+ * Example:
+ * "A[][]".toCharArray()
+ * "java.lang.String".toCharArray()
+ */
+private char[] returnTypeName(TypeReference type) {
+	if (type == null)
+		return null;
+	int dimension = type.dimensions();
+	if (dimension != 0) {
+		char[] dimensionsArray = new char[dimension * 2];
+		for (int i = 0; i < dimension; i++) {
+			dimensionsArray[i * 2] = '[';
+			dimensionsArray[(i * 2) + 1] = ']';
+		}
+		return CharOperation.concat(
+			CharOperation.concatWith(type.getTypeName(), '.'), 
+			dimensionsArray); 
+	}
+	return CharOperation.concatWith(type.getTypeName(), '.');
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
index 8539431..0a7caff 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
@@ -1,37 +1,35 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public abstract class AbstractVariableDeclaration extends Statement {
-	public int modifiers;
-	
-	public TypeReference type;
-	public Expression initialization;
-
-	public char[] name;
-
-	public int declarationSourceStart;
-	public int declarationSourceEnd;
-	public int modifiersSourceStart;
-public AbstractVariableDeclaration(){}
-public String name(){
-
-	return "anonymous storage box"/*nonNLS*/; }
-public String toString(int tab) {
-	/*slow code*/
-
-	String s = tabString(tab);
-	if (modifiers != AccDefault) {
-		s += modifiersString(modifiers);
-	}
-	s += type.toString(0) + " "/*nonNLS*/ + new String(name());
-	if (initialization != null)
-		s += " = "/*nonNLS*/ + initialization.toStringExpression(tab);
-	return s;
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+public abstract class AbstractVariableDeclaration extends Statement {
+	public int modifiers;
+	
+	public TypeReference type;
+	public Expression initialization;
+
+	public char[] name;
+
+	public int declarationSourceStart;
+	public int declarationSourceEnd;
+	public int modifiersSourceStart;
+public AbstractVariableDeclaration(){}
+public String name(){
+
+	return "anonymous storage box"/*nonNLS*/; }
+public String toString(int tab) {
+	/*slow code*/
+
+	String s = tabString(tab);
+	if (modifiers != AccDefault) {
+		s += modifiersString(modifiers);
+	}
+	s += type.toString(0) + " "/*nonNLS*/ + new String(name());
+	if (initialization != null)
+		s += " = "/*nonNLS*/ + initialization.toStringExpression(tab);
+	return s;
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 4ae4b54..216ffe3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -1,199 +1,198 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class AllocationExpression extends Expression implements InvocationSite {
-	public TypeReference type;
-	public Expression[] arguments;
-	public MethodBinding binding;
-
-	MethodBinding syntheticAccessor;
-
-public AllocationExpression() {
-	super();
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
-	// must verify that exceptions potentially thrown by this expression are caught in the method
-
-	// process arguments
-	if (arguments != null) {
-		for (int i = 0, count = arguments.length; i < count; i++) {
-			flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
-		}
-	}
-	// record some dependency information for exception types
-	int count;
-	ReferenceBinding[] thrownExceptions;
-	if ((count = (thrownExceptions = binding.thrownExceptions).length) != 0) {
-		// check exception handling
-		flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo, currentScope);
-	}
-	manageEnclosingInstanceAccessIfNecessary(currentScope);
-	manageSyntheticAccessIfNecessary(currentScope);
-	return flowInfo;
-}
-public Expression enclosingInstance() {
-	return null;
-}
-public void generateCode(
-	BlockScope currentScope, 
-	CodeStream codeStream, 
-	boolean valueRequired) {
-
-	int pc = codeStream.position;
-	ReferenceBinding allocatedType = binding.declaringClass;
-
-	codeStream.new_(allocatedType);
-	if (valueRequired) {
-		codeStream.dup();
-	}
-	// better highlight for allocation: display the type individually
-	codeStream.recordPositionsFrom(pc, type);
-
-	// handling innerclass instance allocation
-	if (allocatedType.isNestedType()) {
-		codeStream.generateSyntheticArgumentValues(
-			currentScope, 
-			allocatedType, 
-			enclosingInstance(), 
-			this); 
-	}
-	// generate the arguments for constructor
-	if (arguments != null) {
-		for (int i = 0, count = arguments.length; i < count; i++) {
-			arguments[i].generateCode(currentScope, codeStream, true);
-		}
-	}
-	// invoke constructor
-	if (syntheticAccessor == null) {
-		codeStream.invokespecial(binding);
-	} else {
-		// synthetic accessor got some extra arguments appended to its signature, which need values
-		for (int i = 0, max = syntheticAccessor.parameters.length - binding.parameters.length; i < max; i++) {
-			codeStream.aconst_null();
-		}
-		codeStream.invokespecial(syntheticAccessor);
-	}
-	codeStream.recordPositionsFrom(pc, this);
-}
-public boolean isSuperAccess() {
-	return false;
-}
-public boolean isTypeAccess(){
-	return true;
-}
-/* Inner emulation consists in either recording a dependency 
- * link only, or performing one level of propagation.
- *
- * Dependency mechanism is used whenever dealing with source target
- * types, since by the time we reach them, we might not yet know their
- * exact need.
- */
-public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
-	ReferenceBinding invocationType, allocatedType;
-
-	// perform some emulation work in case there is some and we are inside a local type only
-	if ((allocatedType = binding.declaringClass).isNestedType() 
-		&& currentScope.enclosingSourceType().isLocalType()) {
-
-		if (allocatedType.isLocalType()){
-			((LocalTypeBinding)allocatedType).addInnerEmulationDependent(currentScope, false, false); // request cascade of accesses
-		} else {
-			// locally propagate, since we already now the desired shape for sure
-			currentScope.propagateInnerEmulation(allocatedType, false, false); // request cascade of accesses
-		}
-	}
-}
-public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
-	if (binding.isPrivate() && (currentScope.enclosingSourceType() != binding.declaringClass)) {
-
-		if (currentScope.environment().options.isPrivateConstructorAccessChangingVisibility){
-			binding.tagForClearingPrivateModifier(); // constructor will not be dumped as private, no emulation required thus
-		} else {
-			syntheticAccessor = ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding);
-			currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
-		}
-	}
-}
-public TypeBinding resolveType(BlockScope scope) {
-	// Propagate the type checking to the arguments, and check if the constructor is defined.
-	constant = NotAConstant;
-	TypeBinding typeBinding = type.resolveType(scope); // will check for null after args are resolved
-
-	// buffering the arguments' types
-	TypeBinding[] argumentTypes = NoParameters;
-	if (arguments != null) {
-		boolean argHasError = false;
-		int length = arguments.length;
-		argumentTypes = new TypeBinding[length];
-		for (int i = 0; i < length; i++)
-			if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
-				argHasError = true;
-		if (argHasError)
-			return null;
-	}
-	if (typeBinding == null)
-		return null;
-
-	if (!typeBinding.canBeInstantiated()) {
-		scope.problemReporter().cannotInstantiate(type, typeBinding);
-		return null;
-	}
-	ReferenceBinding allocatedType = (ReferenceBinding) typeBinding;
-	if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this)).isValidBinding()) {
-		if (binding.declaringClass == null)
-			binding.declaringClass = allocatedType;
-		scope.problemReporter().invalidConstructor(this, binding);
-		return null;
-	}
-	if (isMethodUseDeprecated(binding, scope))
-		scope.problemReporter().deprecatedMethod(binding, this);
-
-	if (arguments != null)
-		for (int i = 0; i < arguments.length; i++)
-			arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
-	return allocatedType;
-}
-public void setDepth(int i) {
-	// ignored
-}
-public void setFieldIndex(int i) {
-	// ignored
-}
-public String toStringExpression() {
-	/* slow code */
-
-	String s = "new "/*nonNLS*/ + type.toString(0);
-	if (arguments == null)
-		s = s + "()"/*nonNLS*/ ;
-	else
-	{	s = s + "("/*nonNLS*/;
-		for (int i = 0 ; i < arguments.length ; i++)
-		{	s = s + arguments[i].toStringExpression();
-			if (i == (arguments.length-1))
-				s = s + ")"/*nonNLS*/ ;
-			else
-				s = s + ", "/*nonNLS*/; };};
-	return s ;}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	if (visitor.visit(this, scope)) {
-		int argumentsLength;
-		type.traverse(visitor, scope);
-		if (arguments != null) {
-			argumentsLength = arguments.length;
-			for (int i = 0; i < argumentsLength; i++)
-				arguments[i].traverse(visitor, scope);
-		}
-	}
-	visitor.endVisit(this, scope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class AllocationExpression extends Expression implements InvocationSite {
+	public TypeReference type;
+	public Expression[] arguments;
+	public MethodBinding binding;
+
+	MethodBinding syntheticAccessor;
+
+public AllocationExpression() {
+	super();
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+	// must verify that exceptions potentially thrown by this expression are caught in the method
+
+	// process arguments
+	if (arguments != null) {
+		for (int i = 0, count = arguments.length; i < count; i++) {
+			flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+		}
+	}
+	// record some dependency information for exception types
+	int count;
+	ReferenceBinding[] thrownExceptions;
+	if ((count = (thrownExceptions = binding.thrownExceptions).length) != 0) {
+		// check exception handling
+		flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo, currentScope);
+	}
+	manageEnclosingInstanceAccessIfNecessary(currentScope);
+	manageSyntheticAccessIfNecessary(currentScope);
+	return flowInfo;
+}
+public Expression enclosingInstance() {
+	return null;
+}
+public void generateCode(
+	BlockScope currentScope, 
+	CodeStream codeStream, 
+	boolean valueRequired) {
+
+	int pc = codeStream.position;
+	ReferenceBinding allocatedType = binding.declaringClass;
+
+	codeStream.new_(allocatedType);
+	if (valueRequired) {
+		codeStream.dup();
+	}
+	// better highlight for allocation: display the type individually
+	codeStream.recordPositionsFrom(pc, type);
+
+	// handling innerclass instance allocation
+	if (allocatedType.isNestedType()) {
+		codeStream.generateSyntheticArgumentValues(
+			currentScope, 
+			allocatedType, 
+			enclosingInstance(), 
+			this); 
+	}
+	// generate the arguments for constructor
+	if (arguments != null) {
+		for (int i = 0, count = arguments.length; i < count; i++) {
+			arguments[i].generateCode(currentScope, codeStream, true);
+		}
+	}
+	// invoke constructor
+	if (syntheticAccessor == null) {
+		codeStream.invokespecial(binding);
+	} else {
+		// synthetic accessor got some extra arguments appended to its signature, which need values
+		for (int i = 0, max = syntheticAccessor.parameters.length - binding.parameters.length; i < max; i++) {
+			codeStream.aconst_null();
+		}
+		codeStream.invokespecial(syntheticAccessor);
+	}
+	codeStream.recordPositionsFrom(pc, this);
+}
+public boolean isSuperAccess() {
+	return false;
+}
+public boolean isTypeAccess(){
+	return true;
+}
+/* Inner emulation consists in either recording a dependency 
+ * link only, or performing one level of propagation.
+ *
+ * Dependency mechanism is used whenever dealing with source target
+ * types, since by the time we reach them, we might not yet know their
+ * exact need.
+ */
+public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+	ReferenceBinding invocationType, allocatedType;
+
+	// perform some emulation work in case there is some and we are inside a local type only
+	if ((allocatedType = binding.declaringClass).isNestedType() 
+		&& currentScope.enclosingSourceType().isLocalType()) {
+
+		if (allocatedType.isLocalType()){
+			((LocalTypeBinding)allocatedType).addInnerEmulationDependent(currentScope, false, false); // request cascade of accesses
+		} else {
+			// locally propagate, since we already now the desired shape for sure
+			currentScope.propagateInnerEmulation(allocatedType, false, false); // request cascade of accesses
+		}
+	}
+}
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
+	if (binding.isPrivate() && (currentScope.enclosingSourceType() != binding.declaringClass)) {
+
+		if (currentScope.environment().options.isPrivateConstructorAccessChangingVisibility){
+			binding.tagForClearingPrivateModifier(); // constructor will not be dumped as private, no emulation required thus
+		} else {
+			syntheticAccessor = ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding);
+			currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+		}
+	}
+}
+public TypeBinding resolveType(BlockScope scope) {
+	// Propagate the type checking to the arguments, and check if the constructor is defined.
+	constant = NotAConstant;
+	TypeBinding typeBinding = type.resolveType(scope); // will check for null after args are resolved
+
+	// buffering the arguments' types
+	TypeBinding[] argumentTypes = NoParameters;
+	if (arguments != null) {
+		boolean argHasError = false;
+		int length = arguments.length;
+		argumentTypes = new TypeBinding[length];
+		for (int i = 0; i < length; i++)
+			if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
+				argHasError = true;
+		if (argHasError)
+			return null;
+	}
+	if (typeBinding == null)
+		return null;
+
+	if (!typeBinding.canBeInstantiated()) {
+		scope.problemReporter().cannotInstantiate(type, typeBinding);
+		return null;
+	}
+	ReferenceBinding allocatedType = (ReferenceBinding) typeBinding;
+	if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this)).isValidBinding()) {
+		if (binding.declaringClass == null)
+			binding.declaringClass = allocatedType;
+		scope.problemReporter().invalidConstructor(this, binding);
+		return null;
+	}
+	if (isMethodUseDeprecated(binding, scope))
+		scope.problemReporter().deprecatedMethod(binding, this);
+
+	if (arguments != null)
+		for (int i = 0; i < arguments.length; i++)
+			arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
+	return allocatedType;
+}
+public void setDepth(int i) {
+	// ignored
+}
+public void setFieldIndex(int i) {
+	// ignored
+}
+public String toStringExpression() {
+	/* slow code */
+
+	String s = "new "/*nonNLS*/ + type.toString(0);
+	if (arguments == null)
+		s = s + "()"/*nonNLS*/ ;
+	else
+	{	s = s + "("/*nonNLS*/;
+		for (int i = 0 ; i < arguments.length ; i++)
+		{	s = s + arguments[i].toStringExpression();
+			if (i == (arguments.length-1))
+				s = s + ")"/*nonNLS*/ ;
+			else
+				s = s + ", "/*nonNLS*/; };};
+	return s ;}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	if (visitor.visit(this, scope)) {
+		int argumentsLength;
+		type.traverse(visitor, scope);
+		if (arguments != null) {
+			argumentsLength = arguments.length;
+			for (int i = 0; i < argumentsLength; i++)
+				arguments[i].traverse(visitor, scope);
+		}
+	}
+	visitor.endVisit(this, scope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java
index aaa8ee6..1e84888 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java
@@ -1,159 +1,158 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-
-public class AnonymousLocalTypeDeclaration extends LocalTypeDeclaration {
-	//a temporal default name
-	public static final char[] ANONYMOUS_EMPTY_NAME = new char[]{} ;
-	public QualifiedAllocationExpression allocation;
-public AnonymousLocalTypeDeclaration(){
-	super();
-	modifiers = AccDefault ;
-	name = ANONYMOUS_EMPTY_NAME; } // use a default name in order to th name lookup 
-									// to operate juat like a regular type (which has a name)
-									//without checking systematically if the naem is null .... 
-public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
-	//Add to method'set, the default constuctor that just recall the
-	//super constructor with the same arguments
-
-	String baseName = "$anonymous"/*nonNLS*/;
-	TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
-	int argumentsLength = argumentTypes.length;
-	//the constructor
-	ConstructorDeclaration cd = new ConstructorDeclaration();
-	cd.selector = new char[] {'x'}; //no maining
-	cd.sourceStart = sourceStart;
-	cd.sourceEnd = sourceEnd;
-	cd.modifiers = modifiers & AccVisibilityMASK;
-
-	if (argumentsLength > 0) {
-		Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
-		for (int i = argumentsLength; --i >= 0;) {
-			arguments[i] = 
-				new Argument(
-					(baseName + i).toCharArray(), 
-					0L, 
-			//toCharArray() could be optimized ....
-			null, //no meaning (a TypeReference)
-			AccDefault);
-		}
-	}
-
-	//the super call inside the constructor
-	cd.constructorCall = 
-		new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); 
-	cd.constructorCall.sourceStart = sourceStart;
-	cd.constructorCall.sourceEnd = sourceEnd;
-
-	if (argumentsLength > 0) {
-		Expression[] args;
-		args = cd.constructorCall.arguments = new Expression[argumentsLength];
-		for (int i = argumentsLength; --i >= 0;) {
-			args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
-		}
-	}
-
-	//adding the constructor in the methods list
-	if (methods == null) {
-		methods = new AbstractMethodDeclaration[] {cd};
-	} else {
-		AbstractMethodDeclaration[] newMethods;
-		System.arraycopy(
-			methods, 
-			0, 
-			newMethods = new AbstractMethodDeclaration[methods.length + 1], 
-			1, 
-			methods.length); 
-		newMethods[0] = cd;
-		methods = newMethods;
-	}
-
-	//============BINDING UPDATE==========================
-	cd.binding = new MethodBinding(
-		cd.modifiers, //methodDeclaration
-		argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
-		inheritedConstructorBinding.thrownExceptions, //exceptions
-		binding); //declaringClass
-	cd.scope = new MethodScope(scope, this, true);
-	cd.bindArguments();
-	cd.constructorCall.resolve(cd.scope);
-	if (binding.methods == null) {
-		binding.methods = new MethodBinding[] {cd.binding};
-	} else {
-		MethodBinding[] newMethods;
-		System.arraycopy(
-			binding.methods, 
-			0, 
-			newMethods = new MethodBinding[binding.methods.length + 1], 
-			1, 
-			binding.methods.length); 
-		newMethods[0] = cd.binding;
-		binding.methods = newMethods;
-	}
-	//===================================================
-
-	return cd.binding;
-
-}
-public void resolve(BlockScope scope) {
-	// scope and binding are provided in updateBindingSuperclass 
-
-	resolve();
-	updateMaxFieldCount();
-}
-public String toString(int tab ){
-	/*slow code */
-
-	return toStringBody(tab);
-	}
-/**
- *	Iteration for a local anonymous innertype
- *
- */
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
-	if (ignoreFurtherInvestigation)
-		return;
-	try {
-		if (visitor.visit(this, blockScope)) {
-
-			int fieldsLength;
-			int methodsLength;
-			int memberTypesLength;
-
-			// <superclass> is bound to the actual type from the allocation expression
-			// therefore it has already been iterated at this point.
-
-			if (memberTypes != null) {
-				memberTypesLength = memberTypes.length;
-				for (int i = 0; i < memberTypesLength; i++)
-					memberTypes[i].traverse(visitor, scope);
-			}
-			if (fields != null) {
-				fieldsLength = fields.length;
-				for (int i = 0; i < fieldsLength; i++) {
-					FieldDeclaration field;
-					if ((field = fields[i]).isStatic()) {
-						// local type cannot have static fields
-					} else {
-						field.traverse(visitor, initializerScope);
-					}
-				}
-			}
-			if (methods != null) {
-				methodsLength = methods.length;
-				for (int i = 0; i < methodsLength; i++)
-					methods[i].traverse(visitor, scope);
-			}
-		}
-		visitor.endVisit(this, blockScope);
-	} catch (AbortType e) {
-	}
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+
+public class AnonymousLocalTypeDeclaration extends LocalTypeDeclaration {
+	//a temporal default name
+	public static final char[] ANONYMOUS_EMPTY_NAME = new char[]{} ;
+	public QualifiedAllocationExpression allocation;
+public AnonymousLocalTypeDeclaration(){
+	super();
+	modifiers = AccDefault ;
+	name = ANONYMOUS_EMPTY_NAME; } // use a default name in order to th name lookup 
+									// to operate juat like a regular type (which has a name)
+									//without checking systematically if the naem is null .... 
+public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
+	//Add to method'set, the default constuctor that just recall the
+	//super constructor with the same arguments
+
+	String baseName = "$anonymous"/*nonNLS*/;
+	TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
+	int argumentsLength = argumentTypes.length;
+	//the constructor
+	ConstructorDeclaration cd = new ConstructorDeclaration();
+	cd.selector = new char[] {'x'}; //no maining
+	cd.sourceStart = sourceStart;
+	cd.sourceEnd = sourceEnd;
+	cd.modifiers = modifiers & AccVisibilityMASK;
+
+	if (argumentsLength > 0) {
+		Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
+		for (int i = argumentsLength; --i >= 0;) {
+			arguments[i] = 
+				new Argument(
+					(baseName + i).toCharArray(), 
+					0L, 
+			//toCharArray() could be optimized ....
+			null, //no meaning (a TypeReference)
+			AccDefault);
+		}
+	}
+
+	//the super call inside the constructor
+	cd.constructorCall = 
+		new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); 
+	cd.constructorCall.sourceStart = sourceStart;
+	cd.constructorCall.sourceEnd = sourceEnd;
+
+	if (argumentsLength > 0) {
+		Expression[] args;
+		args = cd.constructorCall.arguments = new Expression[argumentsLength];
+		for (int i = argumentsLength; --i >= 0;) {
+			args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
+		}
+	}
+
+	//adding the constructor in the methods list
+	if (methods == null) {
+		methods = new AbstractMethodDeclaration[] {cd};
+	} else {
+		AbstractMethodDeclaration[] newMethods;
+		System.arraycopy(
+			methods, 
+			0, 
+			newMethods = new AbstractMethodDeclaration[methods.length + 1], 
+			1, 
+			methods.length); 
+		newMethods[0] = cd;
+		methods = newMethods;
+	}
+
+	//============BINDING UPDATE==========================
+	cd.binding = new MethodBinding(
+		cd.modifiers, //methodDeclaration
+		argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
+		inheritedConstructorBinding.thrownExceptions, //exceptions
+		binding); //declaringClass
+	cd.scope = new MethodScope(scope, this, true);
+	cd.bindArguments();
+	cd.constructorCall.resolve(cd.scope);
+	if (binding.methods == null) {
+		binding.methods = new MethodBinding[] {cd.binding};
+	} else {
+		MethodBinding[] newMethods;
+		System.arraycopy(
+			binding.methods, 
+			0, 
+			newMethods = new MethodBinding[binding.methods.length + 1], 
+			1, 
+			binding.methods.length); 
+		newMethods[0] = cd.binding;
+		binding.methods = newMethods;
+	}
+	//===================================================
+
+	return cd.binding;
+
+}
+public void resolve(BlockScope scope) {
+	// scope and binding are provided in updateBindingSuperclass 
+
+	resolve();
+	updateMaxFieldCount();
+}
+public String toString(int tab ){
+	/*slow code */
+
+	return toStringBody(tab);
+	}
+/**
+ *	Iteration for a local anonymous innertype
+ *
+ */
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+	if (ignoreFurtherInvestigation)
+		return;
+	try {
+		if (visitor.visit(this, blockScope)) {
+
+			int fieldsLength;
+			int methodsLength;
+			int memberTypesLength;
+
+			// <superclass> is bound to the actual type from the allocation expression
+			// therefore it has already been iterated at this point.
+
+			if (memberTypes != null) {
+				memberTypesLength = memberTypes.length;
+				for (int i = 0; i < memberTypesLength; i++)
+					memberTypes[i].traverse(visitor, scope);
+			}
+			if (fields != null) {
+				fieldsLength = fields.length;
+				for (int i = 0; i < fieldsLength; i++) {
+					FieldDeclaration field;
+					if ((field = fields[i]).isStatic()) {
+						// local type cannot have static fields
+					} else {
+						field.traverse(visitor, initializerScope);
+					}
+				}
+			}
+			if (methods != null) {
+				methodsLength = methods.length;
+				for (int i = 0; i < methodsLength; i++)
+					methods[i].traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, blockScope);
+	} catch (AbortType e) {
+	}
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
index d28f16d..1ab99e0 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -5,7 +5,6 @@
  * All Rights Reserved.
  */
 import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class Argument extends LocalDeclaration {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
index 7553690..cccdbe3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
@@ -1,46 +1,45 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
-	int dimensions;
-public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss) {
-	super( sources , poss);
-	dimensions = dim ;
-}
-public ArrayQualifiedTypeReference(char[][] sources , TypeBinding tb, int dim, long[] poss) {
-	super( sources , tb, poss);
-	dimensions = dim ;
-}
-public int dimensions() {
-	return dimensions;
-}
-public TypeBinding getTypeBinding(Scope scope) {
-	if (binding != null)
-		return binding;
-	return scope.createArray(scope.getType(tokens), dimensions);
-}
-public String toStringExpression(int tab){
-	/* slow speed */
-
-	String s = super.toStringExpression(tab)  ;
-	if (dimensions == 1 ) return s + "[]"/*nonNLS*/ ;
-	for (int i=1 ; i <= dimensions ; i++)
-		s = s + "[]"/*nonNLS*/ ;
-	return s ;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
+	int dimensions;
+public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss) {
+	super( sources , poss);
+	dimensions = dim ;
+}
+public ArrayQualifiedTypeReference(char[][] sources , TypeBinding tb, int dim, long[] poss) {
+	super( sources , tb, poss);
+	dimensions = dim ;
+}
+public int dimensions() {
+	return dimensions;
+}
+public TypeBinding getTypeBinding(Scope scope) {
+	if (binding != null)
+		return binding;
+	return scope.createArray(scope.getType(tokens), dimensions);
+}
+public String toStringExpression(int tab){
+	/* slow speed */
+
+	String s = super.toStringExpression(tab)  ;
+	if (dimensions == 1 ) return s + "[]"/*nonNLS*/ ;
+	for (int i=1 ; i <= dimensions ; i++)
+		s = s + "[]"/*nonNLS*/ ;
+	return s ;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	visitor.visit(this, scope);
+	visitor.endVisit(this, scope);
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
+	visitor.visit(this, scope);
+	visitor.endVisit(this, scope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
index 6776245..c1acd4d 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
@@ -1,47 +1,46 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class ArrayTypeReference extends SingleTypeReference {
-	public int dimensions;
-/**
- * ArrayTypeReference constructor comment.
- * @param source char[]
- * @param dim int
- * @param pos int
- */
-public ArrayTypeReference(char[] source, int dim, long pos) {
-	super(source, pos);
-	dimensions = dim ;
-}
-public ArrayTypeReference(char[] source, TypeBinding tb, int dim, long pos) {
-	super(source, tb, pos);
-	dimensions = dim ;}
-public int dimensions() {
-	return dimensions;
-}
-public TypeBinding getTypeBinding(Scope scope) {
-	if (binding != null)
-		return binding;
-	return scope.createArray(scope.getType(token), dimensions);
-}
-public String toStringExpression(int tab){
-	/* slow speed */
-
-	String s = super.toStringExpression(tab)  ;
-	if (dimensions == 1 ) return s + "[]"/*nonNLS*/ ;
-	for (int i=1 ; i <= dimensions ; i++)
-		s = s + "[]"/*nonNLS*/ ;
-	return s ;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ArrayTypeReference extends SingleTypeReference {
+	public int dimensions;
+/**
+ * ArrayTypeReference constructor comment.
+ * @param source char[]
+ * @param dim int
+ * @param pos int
+ */
+public ArrayTypeReference(char[] source, int dim, long pos) {
+	super(source, pos);
+	dimensions = dim ;
+}
+public ArrayTypeReference(char[] source, TypeBinding tb, int dim, long pos) {
+	super(source, tb, pos);
+	dimensions = dim ;}
+public int dimensions() {
+	return dimensions;
+}
+public TypeBinding getTypeBinding(Scope scope) {
+	if (binding != null)
+		return binding;
+	return scope.createArray(scope.getType(token), dimensions);
+}
+public String toStringExpression(int tab){
+	/* slow speed */
+
+	String s = super.toStringExpression(tab)  ;
+	if (dimensions == 1 ) return s + "[]"/*nonNLS*/ ;
+	for (int i=1 ; i <= dimensions ; i++)
+		s = s + "[]"/*nonNLS*/ ;
+	return s ;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	visitor.visit(this, scope);
+	visitor.endVisit(this, scope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index 1d142c9..4453657 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -1,122 +1,121 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class Assignment extends Expression {
-	public Reference lhs ;
-	public Expression expression ;
-public Assignment(Expression lhs, Expression expression) {
-	//lhs is always a reference by construction ,
-	//but is build as an expression ==> the checkcast cannot fail
-
-	this.lhs = (Reference) lhs;
-	this.expression = expression ;
-
-	sourceStart = lhs.sourceStart;
-	sourceEnd = expression.sourceEnd;
-
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-	// record setting a variable: various scenarii are possible, setting an array reference, 
-	// a field reference, a blank final field reference, a field of an enclosing instance or 
-	// just a local variable.
-
-	return lhs.analyseAssignment(currentScope, flowContext, flowInfo, this, false).unconditionalInits();
-}
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
-
-	// various scenarii are possible, setting an array reference, 
-	// a field reference, a blank final field reference, a field of an enclosing instance or 
-	// just a local variable.
-
-	int pc = codeStream.position;
-	lhs.generateAssignment(currentScope, codeStream, this, valueRequired); // variable may have been optimized out
-	// the lhs is responsible to perform the implicitConversion generation for the assignment since optimized for unused local assignment.
-	codeStream.recordPositionsFrom(pc, this);
-}
-public TypeBinding resolveType(BlockScope scope) {
-	// due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
-
-	constant = NotAConstant;
-	TypeBinding lhsTb = lhs.resolveType(scope);
-	TypeBinding expressionTb = expression.resolveType(scope);
-	if (lhsTb == null || expressionTb == null)
-		return null;
-
-	// Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
-	// may require to widen the rhs expression at runtime
-	if ((expression.isConstantValueOfTypeAssignableToType(expressionTb, lhsTb) ||
-		(lhsTb.isBaseType() && BaseTypeBinding.isWidening(lhsTb.id, expressionTb.id))) ||
-		(scope.areTypesCompatible(expressionTb, lhsTb))) {
-			expression.implicitWidening(lhsTb, expressionTb);
-			return lhsTb;
-		}
-	scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, lhsTb);
-	return null;
-
-
-	/*------------code deported to the flow analysis-------------------
-	if (lhs.isFieldReference()) {
-		// cover also the case of a nameReference that refers to a field...(of course !...)
-		if (lhsTb.isFinal()) {
-			// if the field is final, then the assignment may be done only in constructors/initializers
-			// (this does not insure that the assignment is valid....the flow analysis will tell so)
-			if (scope.enclosingType() == lhs.fieldBinding().declaringClass) {
-				scope.problemReporter().cannotAssignToFinalField(this, lhs.fieldBinding());
-				return null;
-			}
-			if (!scope.enclosingMethod().isConstructorOrInintilizer()) {
-				scope.problemReporter().cannotAssignToFinalField(this, lhs.fieldBinding());
-				return null;
-			}
-		}
-	}
-	-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
-
-	/*----------------------------------------------------------------
-	the code that test if the local is an outer local (it is by definition final)
-	and thus cannot be assigned , has been moved to flow analysis		
-	------------------------------------------------------------------*/
-
-	/*-----------------------------------------------------------------
-	The code that detect the a.b = a.b + 1 ; is done by the flow analysis too
-	-------------------------------------------------------------------*/
-}
-public String toString(int tab){
-	/* slow code*/
-
-	//no () when used as a statement 
-	
-	return	tabString(tab) + toStringExpressionNoParenthesis() ; }
-public String toStringExpression(){
-	/* slow code*/
-
-	//subclass redefine toStringExpressionNoParenthesis()
-	
-	return	"("/*nonNLS*/ + toStringExpressionNoParenthesis() + ")"/*nonNLS*/; }
-public String toStringExpressionNoParenthesis() {
-
-	return 	lhs.toStringExpression() + " "/*nonNLS*/ +
-			"="/*nonNLS*/ + 
-			
-			( (expression.constant != null ) && (expression.constant != NotAConstant) ?
-			 	" /*cst:"/*nonNLS*/+expression.constant.toString()+"*/ "/*nonNLS*/ :
-			 	" "/*nonNLS*/ ) +
-				
-			expression.toStringExpression() ; }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	if (visitor.visit(this, scope)) {
-		lhs.traverse(visitor, scope);
-		expression.traverse(visitor, scope);
-	}
-	visitor.endVisit(this, scope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class Assignment extends Expression {
+	public Reference lhs ;
+	public Expression expression ;
+public Assignment(Expression lhs, Expression expression) {
+	//lhs is always a reference by construction ,
+	//but is build as an expression ==> the checkcast cannot fail
+
+	this.lhs = (Reference) lhs;
+	this.expression = expression ;
+
+	sourceStart = lhs.sourceStart;
+	sourceEnd = expression.sourceEnd;
+
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+	// record setting a variable: various scenarii are possible, setting an array reference, 
+	// a field reference, a blank final field reference, a field of an enclosing instance or 
+	// just a local variable.
+
+	return lhs.analyseAssignment(currentScope, flowContext, flowInfo, this, false).unconditionalInits();
+}
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+	// various scenarii are possible, setting an array reference, 
+	// a field reference, a blank final field reference, a field of an enclosing instance or 
+	// just a local variable.
+
+	int pc = codeStream.position;
+	lhs.generateAssignment(currentScope, codeStream, this, valueRequired); // variable may have been optimized out
+	// the lhs is responsible to perform the implicitConversion generation for the assignment since optimized for unused local assignment.
+	codeStream.recordPositionsFrom(pc, this);
+}
+public TypeBinding resolveType(BlockScope scope) {
+	// due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
+
+	constant = NotAConstant;
+	TypeBinding lhsTb = lhs.resolveType(scope);
+	TypeBinding expressionTb = expression.resolveType(scope);
+	if (lhsTb == null || expressionTb == null)
+		return null;
+
+	// Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
+	// may require to widen the rhs expression at runtime
+	if ((expression.isConstantValueOfTypeAssignableToType(expressionTb, lhsTb) ||
+		(lhsTb.isBaseType() && BaseTypeBinding.isWidening(lhsTb.id, expressionTb.id))) ||
+		(scope.areTypesCompatible(expressionTb, lhsTb))) {
+			expression.implicitWidening(lhsTb, expressionTb);
+			return lhsTb;
+		}
+	scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, lhsTb);
+	return null;
+
+
+	/*------------code deported to the flow analysis-------------------
+	if (lhs.isFieldReference()) {
+		// cover also the case of a nameReference that refers to a field...(of course !...)
+		if (lhsTb.isFinal()) {
+			// if the field is final, then the assignment may be done only in constructors/initializers
+			// (this does not insure that the assignment is valid....the flow analysis will tell so)
+			if (scope.enclosingType() == lhs.fieldBinding().declaringClass) {
+				scope.problemReporter().cannotAssignToFinalField(this, lhs.fieldBinding());
+				return null;
+			}
+			if (!scope.enclosingMethod().isConstructorOrInintilizer()) {
+				scope.problemReporter().cannotAssignToFinalField(this, lhs.fieldBinding());
+				return null;
+			}
+		}
+	}
+	-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
+
+	/*----------------------------------------------------------------
+	the code that test if the local is an outer local (it is by definition final)
+	and thus cannot be assigned , has been moved to flow analysis		
+	------------------------------------------------------------------*/
+
+	/*-----------------------------------------------------------------
+	The code that detect the a.b = a.b + 1 ; is done by the flow analysis too
+	-------------------------------------------------------------------*/
+}
+public String toString(int tab){
+	/* slow code*/
+
+	//no () when used as a statement 
+	
+	return	tabString(tab) + toStringExpressionNoParenthesis() ; }
+public String toStringExpression(){
+	/* slow code*/
+
+	//subclass redefine toStringExpressionNoParenthesis()
+	
+	return	"("/*nonNLS*/ + toStringExpressionNoParenthesis() + ")"/*nonNLS*/; }
+public String toStringExpressionNoParenthesis() {
+
+	return 	lhs.toStringExpression() + " "/*nonNLS*/ +
+			"="/*nonNLS*/ + 
+			
+			( (expression.constant != null ) && (expression.constant != NotAConstant) ?
+			 	" /*cst:"/*nonNLS*/+expression.constant.toString()+"*/ "/*nonNLS*/ :
+			 	" "/*nonNLS*/ ) +
+				
+			expression.toStringExpression() ; }
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	if (visitor.visit(this, scope)) {
+		lhs.traverse(visitor, scope);
+		expression.traverse(visitor, scope);
+	}
+	visitor.endVisit(this, scope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java
index a233a1f..06b8a39 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java
@@ -5,9 +5,7 @@
  * All Rights Reserved.
  */
 import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
 import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
 
 public abstract class AstNode  implements BaseTypes, CompilerModifiers, TypeConstants, TypeIds {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index 2443f2b..0033cd5 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -1,129 +1,128 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class Block extends Statement {
-	public Statement[] statements;
-	public int explicitDeclarations; // the number of explicit declaration , used to create scope
-	public BlockScope scope;
-	public static final Block None = new Block(0);
-public Block(int explicitDeclarations) {
-	this.explicitDeclarations = explicitDeclarations;
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
-	// iterate on statements
-
-	// empty block
-	if (statements == null)
-		return flowInfo;
-	for (int i = 0, max = statements.length; i < max; i++) {
-		Statement stat;
-		if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) {
-			flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
-		}
-	}
-	return flowInfo;
-}
-public static final Block EmptyWith(int sourceStart, int sourceEnd) {
-	//return an empty block which position is s and e
-
-	Block bk = new Block(0);
-	bk.sourceStart = sourceStart;
-	bk.sourceEnd = sourceEnd;
-	return bk;
-}
-/**
- * Code generation for a block
- *	i.e. propagate to statements
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-	if ((bits & IsReachableMASK) == 0) {
-		return;
-	}
-	int pc = codeStream.position;
-	if (statements != null) {
-		for (int i = 0, max = statements.length; i < max; i++) {
-			statements[i].generateCode(scope, codeStream);
-		}
-	} // for local variable debug attributes
-	if (scope != currentScope){ // was really associated with its own scope
-		codeStream.exitUserScope(scope);
-	}
-	codeStream.recordPositionsFrom(pc, this);
-}
-public boolean isEmptyBlock(){
-	return statements == null;
-}
-public void resolve(BlockScope upperScope) {
-	if (statements != null) {
-		scope = explicitDeclarations == 0 ? upperScope : new BlockScope(upperScope, explicitDeclarations);
-		int i = 0, length = statements.length;
-		while (i < length)
-			statements[i++].resolve(scope);
-	}
-}
-public void resolveUsing(BlockScope givenScope) {
-	// this optimized resolve(...) is sent only on none empty blocks
-
-	scope = givenScope;
-	if (statements != null) {
-		int i = 0, length = statements.length;
-		while (i < length)
-			statements[i++].resolve(scope);
-	}
-}
-public String toString(int tab) {
-	/* slow code */
-
-	String s = tabString(tab);
-	if (this.statements == null) {
-		s += "{\n"/*nonNLS*/;
-		s += tabString(tab);
-		s += "}"/*nonNLS*/;
-		return s;
-	}
-
-	//	s = s + (explicitDeclarations != 0
-	//				? " { // ---scope needed for "+String.valueOf(explicitDeclarations) +" locals------------ \n"
-	//				: "{// ---NO scope needed------ \n") ;
-
-	s += "{\n"/*nonNLS*/;
-	s += this.toStringStatements(tab);
-	s += tabString(tab);
-	s += "}"/*nonNLS*/;
-	return s;
-}
-public String toStringStatements(int tab) {
-	/* slow code */
- 	if (this.statements == null) return ""/*nonNLS*/;
-	StringBuffer buffer = new StringBuffer();
-	for (int i = 0; i < statements.length; i++) {
-		buffer.append(statements[i].toString(tab + 1));
-		if (statements[i] instanceof Block){
-			buffer.append("\n"/*nonNLS*/);
-		} else {
-			buffer.append(";\n"/*nonNLS*/);
-		}
-	};
-	return buffer.toString();
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
-	if (visitor.visit(this, blockScope)) {
-		if (statements != null) {
-			int statementLength = statements.length;
-			for (int i = 0; i < statementLength; i++)
-				statements[i].traverse(visitor, scope);
-		}
-	}
-	visitor.endVisit(this, blockScope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class Block extends Statement {
+	public Statement[] statements;
+	public int explicitDeclarations; // the number of explicit declaration , used to create scope
+	public BlockScope scope;
+	public static final Block None = new Block(0);
+public Block(int explicitDeclarations) {
+	this.explicitDeclarations = explicitDeclarations;
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+	// iterate on statements
+
+	// empty block
+	if (statements == null)
+		return flowInfo;
+	for (int i = 0, max = statements.length; i < max; i++) {
+		Statement stat;
+		if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) {
+			flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
+		}
+	}
+	return flowInfo;
+}
+public static final Block EmptyWith(int sourceStart, int sourceEnd) {
+	//return an empty block which position is s and e
+
+	Block bk = new Block(0);
+	bk.sourceStart = sourceStart;
+	bk.sourceEnd = sourceEnd;
+	return bk;
+}
+/**
+ * Code generation for a block
+ *	i.e. propagate to statements
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+	if ((bits & IsReachableMASK) == 0) {
+		return;
+	}
+	int pc = codeStream.position;
+	if (statements != null) {
+		for (int i = 0, max = statements.length; i < max; i++) {
+			statements[i].generateCode(scope, codeStream);
+		}
+	} // for local variable debug attributes
+	if (scope != currentScope){ // was really associated with its own scope
+		codeStream.exitUserScope(scope);
+	}
+	codeStream.recordPositionsFrom(pc, this);
+}
+public boolean isEmptyBlock(){
+	return statements == null;
+}
+public void resolve(BlockScope upperScope) {
+	if (statements != null) {
+		scope = explicitDeclarations == 0 ? upperScope : new BlockScope(upperScope, explicitDeclarations);
+		int i = 0, length = statements.length;
+		while (i < length)
+			statements[i++].resolve(scope);
+	}
+}
+public void resolveUsing(BlockScope givenScope) {
+	// this optimized resolve(...) is sent only on none empty blocks
+
+	scope = givenScope;
+	if (statements != null) {
+		int i = 0, length = statements.length;
+		while (i < length)
+			statements[i++].resolve(scope);
+	}
+}
+public String toString(int tab) {
+	/* slow code */
+
+	String s = tabString(tab);
+	if (this.statements == null) {
+		s += "{\n"/*nonNLS*/;
+		s += tabString(tab);
+		s += "}"/*nonNLS*/;
+		return s;
+	}
+
+	//	s = s + (explicitDeclarations != 0
+	//				? " { // ---scope needed for "+String.valueOf(explicitDeclarations) +" locals------------ \n"
+	//				: "{// ---NO scope needed------ \n") ;
+
+	s += "{\n"/*nonNLS*/;
+	s += this.toStringStatements(tab);
+	s += tabString(tab);
+	s += "}"/*nonNLS*/;
+	return s;
+}
+public String toStringStatements(int tab) {
+	/* slow code */
+ 	if (this.statements == null) return ""/*nonNLS*/;
+	StringBuffer buffer = new StringBuffer();
+	for (int i = 0; i < statements.length; i++) {
+		buffer.append(statements[i].toString(tab + 1));
+		if (statements[i] instanceof Block){
+			buffer.append("\n"/*nonNLS*/);
+		} else {
+			buffer.append(";\n"/*nonNLS*/);
+		}
+	};
+	return buffer.toString();
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+	if (visitor.visit(this, blockScope)) {
+		if (statements != null) {
+			int statementLength = statements.length;
+			for (int i = 0; i < statementLength; i++)
+				statements[i].traverse(visitor, scope);
+		}
+	}
+	visitor.endVisit(this, blockScope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
index ee3f29f..f339cab 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
@@ -1,58 +1,57 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public abstract class BranchStatement extends Statement {
-	public char[] label;
-	public Label targetLabel;
-	public AstNode[] subroutines;
-/**
- * BranchStatement constructor comment.
- */
-public BranchStatement(char[] l, int s,int e) {
-	label = l ;
-	sourceStart = s;
-	sourceEnd = e;
-}
-/**
- * Branch code generation
- *
- *   generate the finallyInvocationSequence.
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
-	if ((bits & IsReachableMASK) == 0) {
-		return;
-	}
-	int pc = codeStream.position;
-
-	// generation of code responsible for invoking the finally 
-	// blocks in sequence
-	if (subroutines != null){
-		for (int i = 0, max = subroutines.length; i < max; i++){
-			AstNode sub;
-			if ((sub = subroutines[i]) instanceof SynchronizedStatement){
-				codeStream.load(((SynchronizedStatement)sub).synchroVariable);
-				codeStream.monitorexit(); 
-			} else {
-				TryStatement trySub = (TryStatement) sub;
-				if (trySub.subRoutineCannotReturn)	{
-					codeStream.goto_(trySub.subRoutineStartLabel);
-					codeStream.recordPositionsFrom(pc, this);
-					return;
-				} else {
-					codeStream.jsr(trySub.subRoutineStartLabel);
-				}
-			}
-		}
-	}
-	codeStream.goto_(targetLabel);
-	codeStream.recordPositionsFrom(pc, this);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public abstract class BranchStatement extends Statement {
+	public char[] label;
+	public Label targetLabel;
+	public AstNode[] subroutines;
+/**
+ * BranchStatement constructor comment.
+ */
+public BranchStatement(char[] l, int s,int e) {
+	label = l ;
+	sourceStart = s;
+	sourceEnd = e;
+}
+/**
+ * Branch code generation
+ *
+ *   generate the finallyInvocationSequence.
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+	if ((bits & IsReachableMASK) == 0) {
+		return;
+	}
+	int pc = codeStream.position;
+
+	// generation of code responsible for invoking the finally 
+	// blocks in sequence
+	if (subroutines != null){
+		for (int i = 0, max = subroutines.length; i < max; i++){
+			AstNode sub;
+			if ((sub = subroutines[i]) instanceof SynchronizedStatement){
+				codeStream.load(((SynchronizedStatement)sub).synchroVariable);
+				codeStream.monitorexit(); 
+			} else {
+				TryStatement trySub = (TryStatement) sub;
+				if (trySub.subRoutineCannotReturn)	{
+					codeStream.goto_(trySub.subRoutineStartLabel);
+					codeStream.recordPositionsFrom(pc, this);
+					return;
+				} else {
+					codeStream.jsr(trySub.subRoutineStartLabel);
+				}
+			}
+		}
+	}
+	codeStream.goto_(targetLabel);
+	codeStream.recordPositionsFrom(pc, this);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java
index 1a1786e..885b33b 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java
@@ -1,77 +1,76 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class Break extends BranchStatement {
-public Break(char[] label, int sourceStart, int e) {
-	super(label, sourceStart,e);
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
-	// here requires to generate a sequence of finally blocks invocations depending corresponding
-	// to each of the traversed try statements, so that execution will terminate properly.
-
-	// lookup the label, this should answer the returnContext
-	FlowContext targetContext;
-	if (label == null) {
-		targetContext = flowContext.getTargetContextForDefaultBreak();
-	} else {
-		targetContext = flowContext.getTargetContextForBreakLabel(label);
-	}
-	if (targetContext == null) {
-		if (label == null) {
-			currentScope.problemReporter().invalidBreak(this);
-		} else {
-			currentScope.problemReporter().undefinedLabel(this); // need to improve
-		}
-	} else {
-		targetLabel = targetContext.breakLabel();
-		targetContext.recordBreakFrom(flowInfo);
-		FlowContext traversedContext = flowContext;
-		int subIndex = 0, maxSub = 5;
-		subroutines = new AstNode[maxSub];
-		while (true) {
-			AstNode sub;
-			if ((sub = traversedContext.subRoutine()) != null) {
-				if (subIndex == maxSub) {
-					System.arraycopy(subroutines, 0, (subroutines = new AstNode[maxSub *= 2]), 0, subIndex); // grow
-				}
-				subroutines[subIndex++] = sub;
-				if (sub.cannotReturn()) {
-					break;
-				}
-			}
-			if (traversedContext == targetContext) {
-				break;
-			} else {
-				traversedContext = traversedContext.parent;
-			}
-		}
-		// resize subroutines
-		if (subIndex != maxSub) {
-			System.arraycopy(subroutines, 0, (subroutines = new AstNode[subIndex]), 0, subIndex);
-		}
-	}
-	return FlowInfo.DeadEnd;
-}
-public String toString(int tab){
-	/* slow code */
-
-	String s = tabString(tab) ;
-	s = s + "break "/*nonNLS*/;
-	if (label != null )
-		s = s + new String(label) ;
-	return s;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockscope) {
-	visitor.visit(this, blockscope);
-	visitor.endVisit(this, blockscope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class Break extends BranchStatement {
+public Break(char[] label, int sourceStart, int e) {
+	super(label, sourceStart,e);
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+	// here requires to generate a sequence of finally blocks invocations depending corresponding
+	// to each of the traversed try statements, so that execution will terminate properly.
+
+	// lookup the label, this should answer the returnContext
+	FlowContext targetContext;
+	if (label == null) {
+		targetContext = flowContext.getTargetContextForDefaultBreak();
+	} else {
+		targetContext = flowContext.getTargetContextForBreakLabel(label);
+	}
+	if (targetContext == null) {
+		if (label == null) {
+			currentScope.problemReporter().invalidBreak(this);
+		} else {
+			currentScope.problemReporter().undefinedLabel(this); // need to improve
+		}
+	} else {
+		targetLabel = targetContext.breakLabel();
+		targetContext.recordBreakFrom(flowInfo);
+		FlowContext traversedContext = flowContext;
+		int subIndex = 0, maxSub = 5;
+		subroutines = new AstNode[maxSub];
+		while (true) {
+			AstNode sub;
+			if ((sub = traversedContext.subRoutine()) != null) {
+				if (subIndex == maxSub) {
+					System.arraycopy(subroutines, 0, (subroutines = new AstNode[maxSub *= 2]), 0, subIndex); // grow
+				}
+				subroutines[subIndex++] = sub;
+				if (sub.cannotReturn()) {
+					break;
+				}
+			}
+			if (traversedContext == targetContext) {
+				break;
+			} else {
+				traversedContext = traversedContext.parent;
+			}
+		}
+		// resize subroutines
+		if (subIndex != maxSub) {
+			System.arraycopy(subroutines, 0, (subroutines = new AstNode[subIndex]), 0, subIndex);
+		}
+	}
+	return FlowInfo.DeadEnd;
+}
+public String toString(int tab){
+	/* slow code */
+
+	String s = tabString(tab) ;
+	s = s + "break "/*nonNLS*/;
+	if (label != null )
+		s = s + new String(label) ;
+	return s;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockscope) {
+	visitor.visit(this, blockscope);
+	visitor.endVisit(this, blockscope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index 6ceaa8d..df4149e 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -1,246 +1,244 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.*;
-
-public class CastExpression extends Expression {
-	public Expression expression;
-	public Expression type;
-	public boolean needRuntimeCheckcast ;
-	public TypeBinding castTb ;
-	
-	//expression.implicitConversion holds the cast for baseType casting 
-	
-	
-
-public CastExpression(Expression e , Expression t) {
-	expression = e ;
-	type = t ;
-
-	//due to the fact an expression may start with ( and that a cast also start with (
-	//the field is an expression....it can be a TypeReference OR a NameReference Or
-	//an expression <--this last one is invalid.......
-
-	// :-( .............
-	
-	//if (type instanceof TypeReference )
-	//	flag = IsTypeReference ;
-	//else
-	//	if (type instanceof NameReference)
-	//		flag = IsNameReference ;
-	//	else
-	//		flag = IsExpression ;
-		
-		
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
-	/* EXTRA REFERENCE RECORDING
-	if (!needsRuntimeCheck && (implicitConversion == NoConversion)) {
-		// need to manually remember the castType as part of the reference information"
-		currentScope.currentMethodDeclaration().recordReferenceTo(type.getTypeBinding());
-	}
-	*/
-
-	return expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
-}
-public final void areTypesCastCompatible(BlockScope scope, TypeBinding castTb, TypeBinding expressionTb) {
-	// see specifications p.68
-	// handle errors and process constant when needed
-
-	// if either one of the type is null ==>
-	// some error has been already reported some where ==>
-	// we then do not report an obvious-cascade-error.
-
-	needRuntimeCheckcast = false;
-	if (castTb == null || expressionTb == null)
-		return;
-	if (castTb.isBaseType()) {
-		if (expressionTb.isBaseType()) {
-			if (expressionTb == castTb) {
-				constant = expression.constant; //use the same constant
-				return;
-			}
-			if (scope.areTypesCompatible(expressionTb, castTb)
-				|| BaseTypeBinding.isNarrowing(castTb.id, expressionTb.id)) {
-				expression.implicitConversion = (castTb.id << 4) + expressionTb.id;
-				if (expression.constant != Constant.NotAConstant)
-					constant = expression.constant.castTo(expression.implicitConversion);
-				return;
-			}
-		}
-		scope.problemReporter().typeCastError(this, castTb, expressionTb);
-		return;
-	}
-
-	//-----------cast to something which is NOT a base type--------------------------	
-	if (expressionTb == NullBinding)
-		return; //null is compatible with every thing
-
-	if (expressionTb.isBaseType()) {
-		scope.problemReporter().typeCastError(this, castTb, expressionTb);
-		return;
-	}
-
-	if (expressionTb.isArrayType()) {
-		if (castTb.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray -----------
-			TypeBinding expressionEltTb = ((ArrayBinding) expressionTb).elementsType(scope);
-			if (expressionEltTb.isBaseType()) {
-				// <---stop the recursion------- 
-				if (((ArrayBinding) castTb).elementsType(scope) == expressionEltTb)
-					needRuntimeCheckcast = true;
-				else
-					scope.problemReporter().typeCastError(this, castTb, expressionTb);
-				return;
-			}
-			// recursively on the elements...
-			areTypesCastCompatible(scope, ((ArrayBinding) castTb).elementsType(scope), expressionEltTb);
-			return;
-		} else if (castTb.isClass()) { //------(castTb.isClass) expressionTb.isArray ---------------	
-			if (scope.isJavaLangObject(castTb))
-				return;
-		} else { //------- (castTb.isInterface) expressionTb.isArray -----------
-			if (scope.isJavaLangCloneable(castTb) || scope.isJavaIoSerializable(castTb)) {
-				needRuntimeCheckcast = true;
-				return;
-			}
-		}
-		scope.problemReporter().typeCastError(this, castTb, expressionTb);
-		return;
-	}
-
-	if (expressionTb.isClass()) {
-		if (castTb.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass -------
-			if (scope.isJavaLangObject(expressionTb)) { // potential runtime error
-				needRuntimeCheckcast = true;
-				return;
-			}
-		} else if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------
-			if (scope.areTypesCompatible(expressionTb, castTb)) // no runtime error
-				return;
-			if (scope.areTypesCompatible(castTb, expressionTb)) { // potential runtime  error
-				needRuntimeCheckcast = true;
-				return;
-			}
-		} else { // ----- (castTb.isInterface) expressionTb.isClass -------  
-			if (((ReferenceBinding) expressionTb).isFinal()) { // no subclass for expressionTb, thus compile-time check is valid
-				if (scope.areTypesCompatible(expressionTb, castTb))
-					return;
-			} else { // a subclass may implement the interface ==> no check at compile time
-				needRuntimeCheckcast = true;
-				return;
-			}
-		}
-		scope.problemReporter().typeCastError(this, castTb, expressionTb);
-		return;
-	}
-
-//	if (expressionTb.isInterface()) { cannot be anything else
-	if (castTb.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------
-		if (scope.isJavaLangCloneable(expressionTb) || scope.isJavaIoSerializable(expressionTb)) // potential runtime error
-			needRuntimeCheckcast = true;
-		else
-			scope.problemReporter().typeCastError(this, castTb, expressionTb);
-		return;
-	} else if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface --------
-		if (scope.isJavaLangObject(castTb)) // no runtime error
-			return;
-		if (((ReferenceBinding) castTb).isFinal()) { // no subclass for castTb, thus compile-time check is valid
-			if (!scope.areTypesCompatible(castTb, expressionTb)) { // potential runtime error
-				scope.problemReporter().typeCastError(this, castTb, expressionTb);
-				return;
-			}
-		}
-	} else { // ----- (castTb.isInterface) expressionTb.isInterface -------
-		if (castTb != expressionTb && (scope.compareTypes(castTb, expressionTb) == NotRelated)) {
-			MethodBinding[] castTbMethods = ((ReferenceBinding) castTb).methods();
-			MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionTb).methods();
-			int exprMethodsLength = expressionTbMethods.length;
-			for (int i = 0, castMethodsLength  = castTbMethods.length; i < castMethodsLength; i++)
-				for (int j = 0; j < exprMethodsLength; j++)
-					if (castTbMethods[i].returnType != expressionTbMethods[j].returnType)
-						if (castTbMethods[i].selector == expressionTbMethods[j].selector)
-							if (castTbMethods[i].areParametersEqual(expressionTbMethods[j]))
-								scope.problemReporter().typeCastError(this, castTb, expressionTb);
-		}
-	}
-	needRuntimeCheckcast = true;
-	return;
-}
-/**
- * Cast expression code generation
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
-	int pc = codeStream.position;
-	if (constant != NotAConstant) {
-		if (valueRequired || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
-			codeStream.generateConstant(constant, implicitConversion);
-			if (needRuntimeCheckcast) {
-				codeStream.checkcast(castTb);
-				if (!valueRequired)
-					codeStream.pop();
-			}
-		}
-		codeStream.recordPositionsFrom(pc, this);
-		return;
-	}
-	expression.generateCode(currentScope, codeStream, valueRequired || needRuntimeCheckcast);
-	if (needRuntimeCheckcast) {
-		codeStream.checkcast(castTb);
-		if (!valueRequired)
-			codeStream.pop();
-	} else {
-		if (valueRequired)
-			codeStream.generateImplicitConversion(implicitConversion);
-	}
-	codeStream.recordPositionsFrom(pc, this);
-}
-public TypeBinding resolveType(BlockScope scope) {
-	// compute a new constant if the cast is effective
-
-	// due to the fact an expression may start with ( and that a cast can also start with (
-	// the field is an expression....it can be a TypeReference OR a NameReference Or
-	// any kind of Expression <-- this last one is invalid.......
-
-	constant = Constant.NotAConstant;
-	implicitConversion = T_undefined;
-	TypeBinding expressionTb = expression.resolveType(scope);
-	if (expressionTb == null)
-		return null;
-
-	if ((type instanceof TypeReference) || (type instanceof NameReference)) {
-		if ((castTb = type.resolveType(scope)) == null)
-			return null;
-		areTypesCastCompatible(scope, castTb, expressionTb);
-		return castTb;
-	} else { // expression as a cast !!!!!!!!
-		scope.problemReporter().invalidTypeReference(type);
-		return null;
-	}
-}
-public String toStringExpression(){
-	/*slow code*/
-	
-	return "("/*nonNLS*/ + type.toString(0)+ ") "/*nonNLS*/ +
-			expression.toStringExpression() ; }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
-	if (visitor.visit(this, blockScope)) {
-		type.traverse(visitor, blockScope);
-		expression.traverse(visitor, blockScope);
-	}
-	visitor.endVisit(this, blockScope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class CastExpression extends Expression {
+	public Expression expression;
+	public Expression type;
+	public boolean needRuntimeCheckcast ;
+	public TypeBinding castTb ;
+	
+	//expression.implicitConversion holds the cast for baseType casting 
+	
+	
+
+public CastExpression(Expression e , Expression t) {
+	expression = e ;
+	type = t ;
+
+	//due to the fact an expression may start with ( and that a cast also start with (
+	//the field is an expression....it can be a TypeReference OR a NameReference Or
+	//an expression <--this last one is invalid.......
+
+	// :-( .............
+	
+	//if (type instanceof TypeReference )
+	//	flag = IsTypeReference ;
+	//else
+	//	if (type instanceof NameReference)
+	//		flag = IsNameReference ;
+	//	else
+	//		flag = IsExpression ;
+		
+		
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+	/* EXTRA REFERENCE RECORDING
+	if (!needsRuntimeCheck && (implicitConversion == NoConversion)) {
+		// need to manually remember the castType as part of the reference information"
+		currentScope.currentMethodDeclaration().recordReferenceTo(type.getTypeBinding());
+	}
+	*/
+
+	return expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+}
+public final void areTypesCastCompatible(BlockScope scope, TypeBinding castTb, TypeBinding expressionTb) {
+	// see specifications p.68
+	// handle errors and process constant when needed
+
+	// if either one of the type is null ==>
+	// some error has been already reported some where ==>
+	// we then do not report an obvious-cascade-error.
+
+	needRuntimeCheckcast = false;
+	if (castTb == null || expressionTb == null)
+		return;
+	if (castTb.isBaseType()) {
+		if (expressionTb.isBaseType()) {
+			if (expressionTb == castTb) {
+				constant = expression.constant; //use the same constant
+				return;
+			}
+			if (scope.areTypesCompatible(expressionTb, castTb)
+				|| BaseTypeBinding.isNarrowing(castTb.id, expressionTb.id)) {
+				expression.implicitConversion = (castTb.id << 4) + expressionTb.id;
+				if (expression.constant != Constant.NotAConstant)
+					constant = expression.constant.castTo(expression.implicitConversion);
+				return;
+			}
+		}
+		scope.problemReporter().typeCastError(this, castTb, expressionTb);
+		return;
+	}
+
+	//-----------cast to something which is NOT a base type--------------------------	
+	if (expressionTb == NullBinding)
+		return; //null is compatible with every thing
+
+	if (expressionTb.isBaseType()) {
+		scope.problemReporter().typeCastError(this, castTb, expressionTb);
+		return;
+	}
+
+	if (expressionTb.isArrayType()) {
+		if (castTb.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray -----------
+			TypeBinding expressionEltTb = ((ArrayBinding) expressionTb).elementsType(scope);
+			if (expressionEltTb.isBaseType()) {
+				// <---stop the recursion------- 
+				if (((ArrayBinding) castTb).elementsType(scope) == expressionEltTb)
+					needRuntimeCheckcast = true;
+				else
+					scope.problemReporter().typeCastError(this, castTb, expressionTb);
+				return;
+			}
+			// recursively on the elements...
+			areTypesCastCompatible(scope, ((ArrayBinding) castTb).elementsType(scope), expressionEltTb);
+			return;
+		} else if (castTb.isClass()) { //------(castTb.isClass) expressionTb.isArray ---------------	
+			if (scope.isJavaLangObject(castTb))
+				return;
+		} else { //------- (castTb.isInterface) expressionTb.isArray -----------
+			if (scope.isJavaLangCloneable(castTb) || scope.isJavaIoSerializable(castTb)) {
+				needRuntimeCheckcast = true;
+				return;
+			}
+		}
+		scope.problemReporter().typeCastError(this, castTb, expressionTb);
+		return;
+	}
+
+	if (expressionTb.isClass()) {
+		if (castTb.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass -------
+			if (scope.isJavaLangObject(expressionTb)) { // potential runtime error
+				needRuntimeCheckcast = true;
+				return;
+			}
+		} else if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------
+			if (scope.areTypesCompatible(expressionTb, castTb)) // no runtime error
+				return;
+			if (scope.areTypesCompatible(castTb, expressionTb)) { // potential runtime  error
+				needRuntimeCheckcast = true;
+				return;
+			}
+		} else { // ----- (castTb.isInterface) expressionTb.isClass -------  
+			if (((ReferenceBinding) expressionTb).isFinal()) { // no subclass for expressionTb, thus compile-time check is valid
+				if (scope.areTypesCompatible(expressionTb, castTb))
+					return;
+			} else { // a subclass may implement the interface ==> no check at compile time
+				needRuntimeCheckcast = true;
+				return;
+			}
+		}
+		scope.problemReporter().typeCastError(this, castTb, expressionTb);
+		return;
+	}
+
+//	if (expressionTb.isInterface()) { cannot be anything else
+	if (castTb.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------
+		if (scope.isJavaLangCloneable(expressionTb) || scope.isJavaIoSerializable(expressionTb)) // potential runtime error
+			needRuntimeCheckcast = true;
+		else
+			scope.problemReporter().typeCastError(this, castTb, expressionTb);
+		return;
+	} else if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface --------
+		if (scope.isJavaLangObject(castTb)) // no runtime error
+			return;
+		if (((ReferenceBinding) castTb).isFinal()) { // no subclass for castTb, thus compile-time check is valid
+			if (!scope.areTypesCompatible(castTb, expressionTb)) { // potential runtime error
+				scope.problemReporter().typeCastError(this, castTb, expressionTb);
+				return;
+			}
+		}
+	} else { // ----- (castTb.isInterface) expressionTb.isInterface -------
+		if (castTb != expressionTb && (scope.compareTypes(castTb, expressionTb) == NotRelated)) {
+			MethodBinding[] castTbMethods = ((ReferenceBinding) castTb).methods();
+			MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionTb).methods();
+			int exprMethodsLength = expressionTbMethods.length;
+			for (int i = 0, castMethodsLength  = castTbMethods.length; i < castMethodsLength; i++)
+				for (int j = 0; j < exprMethodsLength; j++)
+					if (castTbMethods[i].returnType != expressionTbMethods[j].returnType)
+						if (castTbMethods[i].selector == expressionTbMethods[j].selector)
+							if (castTbMethods[i].areParametersEqual(expressionTbMethods[j]))
+								scope.problemReporter().typeCastError(this, castTb, expressionTb);
+		}
+	}
+	needRuntimeCheckcast = true;
+	return;
+}
+/**
+ * Cast expression code generation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+	int pc = codeStream.position;
+	if (constant != NotAConstant) {
+		if (valueRequired || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
+			codeStream.generateConstant(constant, implicitConversion);
+			if (needRuntimeCheckcast) {
+				codeStream.checkcast(castTb);
+				if (!valueRequired)
+					codeStream.pop();
+			}
+		}
+		codeStream.recordPositionsFrom(pc, this);
+		return;
+	}
+	expression.generateCode(currentScope, codeStream, valueRequired || needRuntimeCheckcast);
+	if (needRuntimeCheckcast) {
+		codeStream.checkcast(castTb);
+		if (!valueRequired)
+			codeStream.pop();
+	} else {
+		if (valueRequired)
+			codeStream.generateImplicitConversion(implicitConversion);
+	}
+	codeStream.recordPositionsFrom(pc, this);
+}
+public TypeBinding resolveType(BlockScope scope) {
+	// compute a new constant if the cast is effective
+
+	// due to the fact an expression may start with ( and that a cast can also start with (
+	// the field is an expression....it can be a TypeReference OR a NameReference Or
+	// any kind of Expression <-- this last one is invalid.......
+
+	constant = Constant.NotAConstant;
+	implicitConversion = T_undefined;
+	TypeBinding expressionTb = expression.resolveType(scope);
+	if (expressionTb == null)
+		return null;
+
+	if ((type instanceof TypeReference) || (type instanceof NameReference)) {
+		if ((castTb = type.resolveType(scope)) == null)
+			return null;
+		areTypesCastCompatible(scope, castTb, expressionTb);
+		return castTb;
+	} else { // expression as a cast !!!!!!!!
+		scope.problemReporter().invalidTypeReference(type);
+		return null;
+	}
+}
+public String toStringExpression(){
+	/*slow code*/
+	
+	return "("/*nonNLS*/ + type.toString(0)+ ") "/*nonNLS*/ +
+			expression.toStringExpression() ; }
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+	if (visitor.visit(this, blockScope)) {
+		type.traverse(visitor, blockScope);
+		expression.traverse(visitor, blockScope);
+	}
+	visitor.endVisit(this, blockScope);
+}
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
index 4521446..8d26653 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
@@ -1,71 +1,70 @@
-package org.eclipse.jdt.internal.compiler.ast;
-
-/*
- * (c) Copyright IBM Corp. 2000, 2001.
- * All Rights Reserved.
- */
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class ClassLiteralAccess extends Expression {
-	public TypeReference type;
-	public TypeBinding targetType;
-	FieldBinding syntheticField;
-
-public ClassLiteralAccess(int pos, TypeReference t) {
-	type = t;
-	sourceEnd = (sourceStart = pos)+4 ; // "class" length - 1
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-	
-	// if reachable, request the addition of a synthetic field for caching the class descriptor
-	SourceTypeBinding sourceType = currentScope.outerMostMethodScope().enclosingSourceType();
-	if (!(sourceType.isInterface() // no field generated in interface case (would'nt verify) see 1FHHEZL
-			|| sourceType.isBaseType())){ 
-		syntheticField = sourceType.addSyntheticField(targetType, currentScope);
-	}
-	return flowInfo;
-}
-/**
- * MessageSendDotClass code generation
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
-	int pc = codeStream.position;
-
-	// in interface case, no caching occurs, since cannot make a cache field for interface
-	if (valueRequired)
-		codeStream.generateClassLiteralAccessForType(type.binding, syntheticField);
-	codeStream.recordPositionsFrom(pc, this);
-}
-public TypeBinding resolveType(BlockScope scope) {
-	constant = NotAConstant;
-	if ((targetType = type.resolveType(scope)) == null)
-		return null;
-
-	if (targetType.isArrayType() && ((ArrayBinding) targetType).leafComponentType == VoidBinding) {
-		scope.problemReporter().cannotAllocateVoidArray(this);
-		return null;
-	}
-
-	return scope.getJavaLangClass();
-}
-public String toStringExpression(){
-	/*slow code*/
-	
-	String s = ""/*nonNLS*/;
-	s = s + type.toString(0) + ".class"/*nonNLS*/ ;
-	return s;}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
-	if (visitor.visit(this, blockScope)) {
-		type.traverse(visitor, blockScope);
-	}
-	visitor.endVisit(this, blockScope);
-}
-}
+package org.eclipse.jdt.internal.compiler.ast;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ClassLiteralAccess extends Expression {
+	public TypeReference type;
+	public TypeBinding targetType;
+	FieldBinding syntheticField;
+
+public ClassLiteralAccess(int pos, TypeReference t) {
+	type = t;
+	sourceEnd = (sourceStart = pos)+4 ; // "class" length - 1
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+	
+	// if reachable, request the addition of a synthetic field for caching the class descriptor
+	SourceTypeBinding sourceType = currentScope.outerMostMethodScope().enclosingSourceType();
+	if (!(sourceType.isInterface() // no field generated in interface case (would'nt verify) see 1FHHEZL
+			|| sourceType.isBaseType())){ 
+		syntheticField = sourceType.addSyntheticField(targetType, currentScope);
+	}
+	return flowInfo;
+}
+/**
+ * MessageSendDotClass code generation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+	int pc = codeStream.position;
+
+	// in interface case, no caching occurs, since cannot make a cache field for interface
+	if (valueRequired)
+		codeStream.generateClassLiteralAccessForType(type.binding, syntheticField);
+	codeStream.recordPositionsFrom(pc, this);
+}
+public TypeBinding resolveType(BlockScope scope) {
+	constant = NotAConstant;
+	if ((targetType = type.resolveType(scope)) == null)
+		return null;
+
+	if (targetType.isArrayType() && ((ArrayBinding) targetType).leafComponentType == VoidBinding) {
+		scope.problemReporter().cannotAllocateVoidArray(this);
+		return null;
+	}
+
+	return scope.getJavaLangClass();
+}
+public String toStringExpression(){
+	/*slow code*/
+	
+	String s = ""/*nonNLS*/;
+	s = s + type.toString(0) + ".class"/*nonNLS*/ ;
+	return s;}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+	if (visitor.visit(this, blockScope)) {
+		type.traverse(visitor, blockScope);
+	}
+	visitor.endVisit(this, blockScope);
+}
+}
