/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.codeassist.impl;

/*
 * Parser extension for code assist task
 *
 */

import java.util.HashSet;

import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock;
import org.eclipse.jdt.internal.compiler.parser.RecoveredElement;
import org.eclipse.jdt.internal.compiler.parser.RecoveredField;
import org.eclipse.jdt.internal.compiler.parser.RecoveredInitializer;
import org.eclipse.jdt.internal.compiler.parser.RecoveredLocalVariable;
import org.eclipse.jdt.internal.compiler.parser.RecoveredMethod;
import org.eclipse.jdt.internal.compiler.parser.RecoveredStatement;
import org.eclipse.jdt.internal.compiler.parser.RecoveredType;
import org.eclipse.jdt.internal.compiler.parser.RecoveredUnit;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
public abstract class AssistParser extends Parser {
	public ASTNode assistNode;
	public boolean isOrphanCompletionNode;
	private boolean resumedAfterRepair = false;
	// last modifiers info
	protected int lastModifiers = ClassFileConstants.AccDefault;
	protected int lastModifiersStart = -1;
	/* recovery */
	int[] blockStarts = new int[30];

	// the previous token read by the scanner
	protected int previousToken;

	// the index in the identifier stack of the previous identifier
	protected int previousIdentifierPtr;
	
	// depth of '(', '{' and '[]'
	protected int bracketDepth;

	// element stack
	protected static final int ElementStackIncrement = 100;
	protected int elementPtr;
	protected int[] elementKindStack = new int[ElementStackIncrement];
	protected int[] elementInfoStack = new int[ElementStackIncrement];
	protected Object[] elementObjectInfoStack = new Object[ElementStackIncrement];
	protected int previousKind;
	protected int previousInfo;
	protected Object previousObjectInfo;

	// OWNER
	protected static final int ASSIST_PARSER = 512;

	// KIND : all values known by AssistParser are between 513 and 1023
	protected static final int K_SELECTOR = ASSIST_PARSER + 1; // whether we are inside a message send
	protected static final int K_TYPE_DELIMITER = ASSIST_PARSER + 2; // whether we are inside a type declaration
	protected static final int K_METHOD_DELIMITER = ASSIST_PARSER + 3; // whether we are inside a method declaration
	protected static final int K_FIELD_INITIALIZER_DELIMITER = ASSIST_PARSER + 4; // whether we are inside a field initializer
	protected static final int K_ATTRIBUTE_VALUE_DELIMITER = ASSIST_PARSER + 5; // whether we are inside a annotation attribute valuer
	protected static final int K_ENUM_CONSTANT_DELIMITER = ASSIST_PARSER + 6; // whether we are inside a field initializer
	protected static final int K_LAMBDA_EXPRESSION_DELIMITER = ASSIST_PARSER + 7; // whether we are inside a lambda expression
	
	// selector constants
	protected static final int THIS_CONSTRUCTOR = -1;
	protected static final int SUPER_CONSTRUCTOR = -2;

	// enum constant constants
	protected static final int NO_BODY = 0;
	protected static final int WITH_BODY = 1;
	
	protected static final int EXPRESSION_BODY = 0;
	protected static final int BLOCK_BODY = 1;

	protected boolean isFirst = false;

	public AssistParser snapShot;
	private static final int[] RECOVERY_TOKENS = new int [] { TokenNameSEMICOLON, TokenNameRPAREN,};


public AssistParser(ProblemReporter problemReporter) {
	super(problemReporter, true);
	this.javadocParser.checkDocComment = false;

	setMethodsFullRecovery(false);
	setStatementsRecovery(false);
}

public abstract char[] assistIdentifier();

public void copyState(Parser from) {
	
	super.copyState(from);

	AssistParser parser = (AssistParser) from;
	
	this.previousToken = parser.previousToken;
	this.previousIdentifierPtr = parser.previousIdentifierPtr;
	
	this.lastModifiers = parser.lastModifiers;
	this.lastModifiersStart = parser.lastModifiersStart;
	
	this.bracketDepth = parser.bracketDepth;
	this.elementPtr = parser.elementPtr;
	
	int length;
	System.arraycopy(parser.blockStarts, 0, this.blockStarts = new int [length = parser.blockStarts.length], 0, length);
	System.arraycopy(parser.elementKindStack, 0, this.elementKindStack = new int [length = parser.elementKindStack.length], 0, length);
	System.arraycopy(parser.elementInfoStack, 0, this.elementInfoStack = new int [length = parser.elementInfoStack.length], 0, length);
	System.arraycopy(parser.elementObjectInfoStack, 0, this.elementObjectInfoStack = new Object [length = parser.elementObjectInfoStack.length], 0, length);
	
	this.previousKind = parser.previousKind;
	this.previousInfo = parser.previousInfo;
	this.previousObjectInfo = parser.previousObjectInfo;
}
/**
 * The parser become a simple parser which behave like a Parser
 * @return the state of the assist parser to be able to restore the assist parser state
 */
public Object becomeSimpleParser() {
	return null;
}
/**
 * Restore the parser as an assist parser
 * @param parserState
 */
public void restoreAssistParser(Object parserState) {
	//Do nothing
}
public int bodyEnd(AbstractMethodDeclaration method){
	return method.bodyEnd;
}
public int bodyEnd(Initializer initializer){
	return initializer.declarationSourceEnd;
}
/*
 * Build initial recovery state.
 * Recovery state is inferred from the current state of the parser (reduced node stack).
 */
public RecoveredElement buildInitialRecoveryState(){
	/* recovery in unit structure */
	if (this.referenceContext instanceof CompilationUnitDeclaration){
		RecoveredElement element = super.buildInitialRecoveryState();
		flushAssistState();
		flushElementStack();
		this.snapShot = null;
		return element;
	}

	/* recovery in method body */
	this.lastCheckPoint = 0;

	RecoveredElement element = null;
	if (this.referenceContext instanceof AbstractMethodDeclaration){
		element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this);
		this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart;
	} else {
		/* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
		if (this.referenceContext instanceof TypeDeclaration){
			TypeDeclaration type = (TypeDeclaration) this.referenceContext;
			FieldDeclaration[] fields = type.fields;
			int length = fields == null ? 0 : fields.length;
			for (int i = 0; i < length; i++){
				FieldDeclaration field = fields[i];
				if (field != null
						&& field.getKind() == AbstractVariableDeclaration.INITIALIZER
						&& field.declarationSourceStart <= this.scanner.initialPosition
						&& this.scanner.initialPosition <= field.declarationSourceEnd
						&& this.scanner.eofPosition <= field.declarationSourceEnd+1){
					element = new RecoveredInitializer(field, null, 1, this);
					this.lastCheckPoint = field.declarationSourceStart;
					break;
				}
			}
		}
	}

	if (element == null) return element;

	/* add initial block */
	Block block = new Block(0);
	int lastStart = this.blockStarts[0];
	block.sourceStart = lastStart;
	element = element.add(block, 1);
	int blockIndex = 1;	// ignore first block start, since manually rebuilt here

	ASTNode node = null, lastNode = null;
	for (int i = 0; i <= this.astPtr; i++, lastNode = node) {
		node = this.astStack[i];
		if(node instanceof ForeachStatement && ((ForeachStatement)node).action == null) {
			node = ((ForeachStatement)node).elementVariable;
		}
		/* check for intermediate block creation, so recovery can properly close them afterwards */
		int nodeStart = node.sourceStart;
		for (int j = blockIndex; j <= this.realBlockPtr; j++){
			if (this.blockStarts[j] >= 0) {
				if (this.blockStarts[j] > nodeStart){
					blockIndex = j; // shift the index to the new block
					break;
				}
				if (this.blockStarts[j] != lastStart){ // avoid multiple block if at same position
					block = new Block(0);
					block.sourceStart = lastStart = this.blockStarts[j];
					element = element.add(block, 1);
				}
			} else {
				if (-this.blockStarts[j] > nodeStart){
					blockIndex = j; // shift the index to the new block
					break;
				}
				block = new Block(0);
				block.sourceStart = lastStart = -this.blockStarts[j];
				element = element.add(block, 1);
			}
			blockIndex = j+1; // shift the index to the new block
		}
		
		if (node instanceof LocalDeclaration){
			LocalDeclaration local = (LocalDeclaration) node;
			if (local.declarationSourceEnd == 0){
				element = element.add(local, 0);
				if (local.initialization == null){
					this.lastCheckPoint = local.sourceEnd + 1;
				} else {
					this.lastCheckPoint = local.initialization.sourceEnd + 1;
				}
			} else {
				if (!local.isArgument()) {
					element = element.add(local, 0);
				} else {
					// Bug 442868 - For arguments, let the method continue to be the current element.
					element.add(local, 0);
				}
				this.lastCheckPoint = local.declarationSourceEnd + 1;
			}
			continue;
		}
		if (node instanceof AbstractMethodDeclaration){
			AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
			if (method.declarationSourceEnd == 0){
				element = element.add(method, 0);
				this.lastCheckPoint = method.bodyStart;
			} else {
				element = element.add(method, 0);
				this.lastCheckPoint = method.declarationSourceEnd + 1;
			}
			continue;
		}
		if (node instanceof Initializer){
			Initializer initializer = (Initializer) node;
			if (initializer.declarationSourceEnd == 0){
				element = element.add(initializer, 1);
				this.lastCheckPoint = initializer.sourceStart;
			} else {
				element = element.add(initializer, 0);
				this.lastCheckPoint = initializer.declarationSourceEnd + 1;
			}
			continue;
		}
		if (node instanceof FieldDeclaration){
			FieldDeclaration field = (FieldDeclaration) node;
			if (field.declarationSourceEnd == 0){
				element = element.add(field, 0);
				if (field.initialization == null){
					this.lastCheckPoint = field.sourceEnd + 1;
				} else {
					this.lastCheckPoint = field.initialization.sourceEnd + 1;
				}
			} else {
				element = element.add(field, 0);
				this.lastCheckPoint = field.declarationSourceEnd + 1;
			}
			continue;
		}
		if (node instanceof TypeDeclaration){
			TypeDeclaration type = (TypeDeclaration) node;
			if (type.declarationSourceEnd == 0){
				element = element.add(type, 0);
				this.lastCheckPoint = type.bodyStart;
			} else {
				element = element.add(type, 0);
				this.lastCheckPoint = type.declarationSourceEnd + 1;
			}
			continue;
		}
		if (this.assistNode != null && node instanceof Statement) {
			Statement stmt = (Statement) node;
			if (!(stmt instanceof Expression) || ((Expression) stmt).statementExpression()) {
				if (this.assistNode.sourceStart >= stmt.sourceStart && this.assistNode.sourceEnd <= stmt.sourceEnd) {
					element.add(stmt, 0);
					this.lastCheckPoint = stmt.sourceEnd + 1;
					this.isOrphanCompletionNode = false;
				}
			}
			continue;
		}
		if (node instanceof ImportReference){
			ImportReference importRef = (ImportReference) node;
			element = element.add(importRef, 0);
			this.lastCheckPoint = importRef.declarationSourceEnd + 1;
		}
	}
	if (this.currentToken == TokenNameRBRACE) {
		 if (isIndirectlyInsideLambdaExpression())
			 this.ignoreNextClosingBrace = true;
		 else 
			 this.currentToken = 0; // closing brace has already been taken care of
	}

	/* might need some extra block (after the last reduced node) */
	/* For block bodied lambdas we should create a block even though the lambda header appears before it, so elements from within don't get misattributed. */
	int pos = this.assistNode == null ? this.lastCheckPoint : this.assistNode.sourceStart;
	boolean createLambdaBlock = lastNode instanceof LambdaExpression && ((LambdaExpression) node).body() instanceof Block;
	for (int j = blockIndex; j <= this.realBlockPtr; j++){
		if (this.blockStarts[j] >= 0) {
			if ((this.blockStarts[j] < pos || createLambdaBlock) && (this.blockStarts[j] != lastStart)){ // avoid multiple block if at same position
				block = new Block(0);
				block.sourceStart = lastStart = this.blockStarts[j];
				element = element.add(block, 1);
				createLambdaBlock = false;
			}
		} else {
			if ((this.blockStarts[j] < pos)){ // avoid multiple block if at same position
				block = new Block(0);
				block.sourceStart = lastStart = -this.blockStarts[j];
				element = element.add(block, 1);
			}
		}
	}

	return element;
}
protected void consumeAnnotationTypeDeclarationHeader() {
	super.consumeAnnotationTypeDeclarationHeader();
	pushOnElementStack(K_TYPE_DELIMITER);
}
protected void consumeClassBodyDeclaration() {
	popElement(K_METHOD_DELIMITER);
	super.consumeClassBodyDeclaration();
}
protected void consumeClassBodyopt() {
	super.consumeClassBodyopt();
	popElement(K_SELECTOR);
}
protected void consumeClassHeader() {
	super.consumeClassHeader();
	pushOnElementStack(K_TYPE_DELIMITER);
}
protected void consumeConstructorBody() {
	super.consumeConstructorBody();
	popElement(K_METHOD_DELIMITER);
}
protected void consumeConstructorHeader() {
	super.consumeConstructorHeader();
	pushOnElementStack(K_METHOD_DELIMITER);
}
protected void consumeEnhancedForStatementHeaderInit(boolean hasModifiers) {
	super.consumeEnhancedForStatementHeaderInit(hasModifiers);

	if (this.currentElement != null) {
		LocalDeclaration localDecl = ((ForeachStatement)this.astStack[this.astPtr]).elementVariable;
		this.lastCheckPoint = localDecl.sourceEnd + 1;
		this.currentElement = this.currentElement.add(localDecl, 0);
	}
}
protected void consumeEnterAnonymousClassBody(boolean qualified) {
	super.consumeEnterAnonymousClassBody(qualified);
	popElement(K_SELECTOR);
	pushOnElementStack(K_TYPE_DELIMITER);
}
protected void consumeEnterMemberValue() {
	super.consumeEnterMemberValue();
	pushOnElementStack(K_ATTRIBUTE_VALUE_DELIMITER, this.identifierPtr);
}
protected void consumeEnumConstantHeader() {
	if(this.currentToken == TokenNameLBRACE) {
		popElement(K_ENUM_CONSTANT_DELIMITER);
		pushOnElementStack(K_ENUM_CONSTANT_DELIMITER, WITH_BODY);
		pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
		pushOnElementStack(K_TYPE_DELIMITER);
	}
	super.consumeEnumConstantHeader();
	if (triggerRecoveryUponLambdaClosure((Statement) this.astStack[this.astPtr], true) && this.currentElement != null)
		this.restartRecovery = true;
}
protected void consumeEnumConstantHeaderName() {
	super.consumeEnumConstantHeaderName();
	pushOnElementStack(K_ENUM_CONSTANT_DELIMITER);
}
protected void consumeEnumConstantWithClassBody() {
	popElement(K_TYPE_DELIMITER);
	popElement(K_FIELD_INITIALIZER_DELIMITER);
	popElement(K_ENUM_CONSTANT_DELIMITER);
	super.consumeEnumConstantWithClassBody();
}
protected void consumeEnumConstantNoClassBody() {
	popElement(K_ENUM_CONSTANT_DELIMITER);
	super.consumeEnumConstantNoClassBody();
}
protected void consumeEnumHeader() {
	super.consumeEnumHeader();
	pushOnElementStack(K_TYPE_DELIMITER);
}
protected void consumeExitMemberValue() {
	super.consumeExitMemberValue();
	popElement(K_ATTRIBUTE_VALUE_DELIMITER);
}

protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
	super.consumeExplicitConstructorInvocation(flag, recFlag);
	popElement(K_SELECTOR);
}

protected boolean triggerRecoveryUponLambdaClosure(Statement statement, boolean shouldCommit) {
	// Last block statement reduced is required to be on the AST stack top.
	boolean lambdaClosed = false;
	int statementStart, statementEnd;
	statementStart = statement.sourceStart;
	statementEnd = statement instanceof AbstractVariableDeclaration ? ((AbstractVariableDeclaration)statement).declarationSourceEnd : statement.sourceEnd;
	for (int i = this.elementPtr; i >= 0; --i) {
		if (this.elementKindStack[i] != K_LAMBDA_EXPRESSION_DELIMITER)
			continue;
		LambdaExpression expression = (LambdaExpression) this.elementObjectInfoStack[i];
		if (expression.sourceStart >= statementStart && expression.sourceEnd <= statementEnd) {
			this.elementPtr = i - 1;
			lambdaClosed = true;
		} else {
			if (shouldCommit) {
				int stackLength = this.stack.length;
				if (++this.stateStackTop >= stackLength) {
					System.arraycopy(
							this.stack, 0,
							this.stack = new int[stackLength + StackIncrement], 0,
							stackLength);
				}
				this.stack[this.stateStackTop] = this.unstackedAct;
				commit();
				this.stateStackTop --;
			}
			return false;
		}
	}

	if (lambdaClosed && this.currentElement != null && !(this.currentElement instanceof RecoveredField)) {
		if (!(statement instanceof AbstractVariableDeclaration)) { // added already as part of standard recovery since these contribute a name to the scope prevailing at the cursor.
			/* See if CompletionParser.attachOrphanCompletionNode has already added bits and pieces of AST to the recovery tree. If so, we want to
			   replace those fragments with the fuller statement that provides target type for the lambda that got closed just now. There is prior
			   art/precedent in the Java 7 world to this: Search for recoveredBlock.statements[--recoveredBlock.statementCount] = null;
			   See also that this concern does not arise in the case of field/local initialization since the initializer is replaced with full tree by consumeExitVariableWithInitialization.
			*/
			/*
			 * All the above comments will not work if the assist node is buried deeper. This happens when there the 
			 * lambda was part of a complex statement, such as it was one of the arguments to a method invocation. In which case,
			 * we start from the topmost recovery element and look for assist nodes. If the operation is successful, the method
			 * replaceAssistStatement() returns null. Else, it returns the original statement, thus falling back to replacing the
			 * last statement in the current recovered element.
			 */
			statement = replaceAssistStatement(this.currentElement.topElement(),
					this.assistNodeParent(), statementStart, statementEnd, statement);
			
			if (statement != null) {
				RecoveredBlock recoveredBlock = (RecoveredBlock) (this.currentElement instanceof RecoveredBlock ? this.currentElement : 
					(this.currentElement.parent instanceof RecoveredBlock) ? this.currentElement.parent : 
						this.currentElement instanceof RecoveredMethod ? ((RecoveredMethod) this.currentElement).methodBody : null);
				if (recoveredBlock != null) {
					RecoveredStatement recoveredStatement = recoveredBlock.statementCount > 0 ? recoveredBlock.statements[recoveredBlock.statementCount - 1] : null;
					ASTNode parseTree = recoveredStatement != null ? recoveredStatement.updatedStatement(0, new HashSet<TypeDeclaration>()) : null;
					if (parseTree != null) {
						if ((parseTree.sourceStart == 0 || parseTree.sourceEnd == 0) || (parseTree.sourceStart >= statementStart && parseTree.sourceEnd <= statementEnd)) {
							recoveredBlock.statements[recoveredBlock.statementCount - 1] = new RecoveredStatement(statement, recoveredBlock, 0);
							statement = null;
						} else if (recoveredStatement instanceof RecoveredLocalVariable && statement instanceof Expression) {
							RecoveredLocalVariable local = (RecoveredLocalVariable) recoveredStatement;
							if (local.localDeclaration != null && local.localDeclaration.initialization != null) {
								if ((local.localDeclaration.initialization.sourceStart == 0 || local.localDeclaration.initialization.sourceEnd == 0) || 
								        (local.localDeclaration.initialization.sourceStart >= statementStart && local.localDeclaration.initialization.sourceEnd <= statementEnd) ){
									local.localDeclaration.initialization = (Expression) statement;
									local.localDeclaration.declarationSourceEnd = statement.sourceEnd;
									local.localDeclaration.declarationEnd = statement.sourceEnd;
									statement = null;
								}
							}
						}
					}
				}
			}
			if (statement != null) {
				while (this.currentElement != null) {
					ASTNode tree = this.currentElement.parseTree();
					if (tree.sourceStart < statement.sourceStart) {
						this.currentElement.add(statement, 0);
						break;
					}
					this.currentElement = this.currentElement.parent;
				}
			}
		}
	}
	this.snapShot = null;
	return lambdaClosed;
}
public Statement replaceAssistStatement(RecoveredElement top, ASTNode assistParent, int start, int end, Statement stmt) {
	if (top == null) return null;
	if (top instanceof RecoveredBlock) {
		RecoveredBlock blk = (RecoveredBlock) top;
		RecoveredStatement[] statements = blk.statements;
		boolean found = false;
		if (statements != null) {
			for(int i = 0; i < statements.length; i++) {
				if (statements[i] == null) break;
				ASTNode node = statements[i].parseTree();
				if ((node.sourceStart >= start && node.sourceEnd <= end)) {
					if (!found) {
						statements[i] = new RecoveredStatement(stmt, blk, 0);
						found = true;
						blk.statementCount = i + 1;
					} else {
						// Proceed to wipe out the nodes after the assist node. Most likely
						// these are wrapped inside the just-closed-lambda. Even otherwise,
						// they are not much useful for completion.
						statements[i] = null;
					}
				}
			}
			if (found) return null;
		}
	} else if (top instanceof RecoveredMethod) {
		stmt = replaceAssistStatement(((RecoveredMethod) top).methodBody, assistParent, start, end, stmt);
	} else if (top instanceof RecoveredInitializer) {
		stmt = replaceAssistStatement(((RecoveredInitializer) top).initializerBody, assistParent, start, end, stmt);
	}
	return stmt;
}
protected ASTNode assistNodeParent() {
	return null;
}
protected ASTNode enclosingNode() {
	return null;
}

protected boolean isAssistParser() {
	return true;
}
protected void consumeBlockStatement() {
	super.consumeBlockStatement();
	if (triggerRecoveryUponLambdaClosure((Statement) this.astStack[this.astPtr], true) && this.currentElement != null)
		this.restartRecovery = true;
}
protected void consumeBlockStatements() {
	super.consumeBlockStatements();
	if (triggerRecoveryUponLambdaClosure((Statement) this.astStack[this.astPtr], true) && this.currentElement != null) {
		this.restartRecovery = true;
	}
}
protected void consumeFieldDeclaration() {
	super.consumeFieldDeclaration();
	if (triggerRecoveryUponLambdaClosure((Statement) this.astStack[this.astPtr], true)) {
		if (this.currentElement instanceof RecoveredType)
			popUntilElement(K_TYPE_DELIMITER);
		if (this.currentElement != null)
			this.restartRecovery = true;
	}
}
protected void consumeForceNoDiet() {
	super.consumeForceNoDiet();
	// if we are not in a method (i.e. we are not in a local variable initializer)
	// then we are entering a field initializer
	if (!isInsideMethod()) {
		if(topKnownElementKind(ASSIST_PARSER) != K_ENUM_CONSTANT_DELIMITER) {
			if(topKnownElementKind(ASSIST_PARSER, 2) != K_ENUM_CONSTANT_DELIMITER) {
				pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
			}
		} else {
			int info = topKnownElementInfo(ASSIST_PARSER);
			if(info != NO_BODY) {
				pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
			}
		}

	}
}
protected void consumeInterfaceHeader() {
	super.consumeInterfaceHeader();
	pushOnElementStack(K_TYPE_DELIMITER);
}
@Override
protected void consumeNestedLambda() {
	super.consumeNestedLambda();
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr];
	pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, EXPRESSION_BODY, lexp);
}
protected void consumeMethodBody() {
	super.consumeMethodBody();
	popElement(K_METHOD_DELIMITER);
}
protected void consumeMethodDeclaration(boolean isNotAbstract, boolean isDefaultMethod) {
	if (!isNotAbstract) {
		popElement(K_METHOD_DELIMITER);
	}
	super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
}
protected void consumeMethodHeader() {
	super.consumeMethodHeader();
	pushOnElementStack(K_METHOD_DELIMITER);
}
protected void consumeMethodInvocationName() {
	super.consumeMethodInvocationName();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
protected void consumeMethodInvocationNameWithTypeArguments() {
	super.consumeMethodInvocationNameWithTypeArguments();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
protected void consumeMethodInvocationPrimary() {
	super.consumeMethodInvocationPrimary();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
protected void consumeMethodInvocationPrimaryWithTypeArguments() {
	super.consumeMethodInvocationPrimaryWithTypeArguments();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
protected void consumeMethodInvocationSuper() {
	super.consumeMethodInvocationSuper();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
protected void consumeMethodInvocationSuperWithTypeArguments() {
	super.consumeMethodInvocationSuperWithTypeArguments();
	popElement(K_SELECTOR);
	MessageSend messageSend = (MessageSend)this.expressionStack[this.expressionPtr];
	if (messageSend == this.assistNode){
		this.lastCheckPoint = messageSend.sourceEnd + 1;
	}
}
protected void consumeNestedMethod() {
	super.consumeNestedMethod();
	if(!isInsideMethod()) pushOnElementStack(K_METHOD_DELIMITER);
}
protected void consumeOpenBlock() {
	// OpenBlock ::= $empty
	super.consumeOpenBlock();

	int stackLength = this.blockStarts.length;
	if (this.realBlockPtr >= stackLength) {
		System.arraycopy(
				this.blockStarts, 0,
				this.blockStarts = new int[stackLength + StackIncrement], 0,
				stackLength);
	}
	this.blockStarts[this.realBlockPtr] = this.scanner.startPosition;
	if (requireExtendedRecovery()) {
		// This is an epsilon production: We are in the state with kernel item: Block ::= .OpenBlock LBRACE BlockStatementsopt RBRACE
		if (this.currentToken == TokenNameLBRACE && this.unstackedAct > NUM_RULES) { // wait for chain reductions to finish before commit.
			stackLength = this.stack.length;
			if (++this.stateStackTop >= stackLength - 1) {   // Need two slots.
				System.arraycopy(
						this.stack, 0,
						this.stack = new int[stackLength + StackIncrement], 0,
						stackLength);
			}
			this.stack[this.stateStackTop++] = this.unstackedAct; // transition to Block ::= OpenBlock  .LBRACE BlockStatementsopt RBRACE
			this.stack[this.stateStackTop] = tAction(this.unstackedAct, this.currentToken); // transition to Block ::= OpenBlock LBRACE  .BlockStatementsopt RBRACE 
			commit();
			this.stateStackTop -= 2;
		}
	}
}
protected void consumeOpenFakeBlock() {
	// OpenBlock ::= $empty

	super.consumeOpenBlock();
	int stackLength = this.blockStarts.length;
	if (this.realBlockPtr >= stackLength) {
		System.arraycopy(
			this.blockStarts, 0,
			this.blockStarts = new int[stackLength + StackIncrement], 0,
			stackLength);
	}
	this.blockStarts[this.realBlockPtr] = -this.scanner.startPosition;
}
protected void consumePackageDeclarationName() {
	// PackageDeclarationName ::= 'package' Name
	/* build 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.consumePackageDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on package statement */
	ImportReference reference = createAssistPackageReference(subset, positions);
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	this.compilationUnit.currentPackage = reference;

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush comments defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
protected void consumePackageDeclarationNameWithModifiers() {
	// PackageDeclarationName ::= Modifiers 'package' PushRealModifiers Name
	/* build 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.consumePackageDeclarationNameWithModifiers();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	this.intPtr--; // we don't need the modifiers start
	this.intPtr--; // we don't need the package modifiers
	ImportReference reference = createAssistPackageReference(subset, positions);
	// consume annotations
	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
		System.arraycopy(
			this.expressionStack,
			(this.expressionPtr -= length) + 1,
			reference.annotations = new Annotation[length],
			0,
			length);
	}
	/* build specific assist node on package statement */
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	this.compilationUnit.currentPackage = reference;

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush comments defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
protected void consumeRestoreDiet() {
	super.consumeRestoreDiet();
	// if we are not in a method (i.e. we were not in a local variable initializer)
	// then we are exiting a field initializer
	if (!isInsideMethod()) {
		popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
		popElement(K_FIELD_INITIALIZER_DELIMITER);
	}
}
protected void consumeSingleStaticImportDeclarationName() {
	// SingleTypeImportDeclarationName ::= 'import' 'static' 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.consumeSingleStaticImportDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on import statement */
	ImportReference reference = createAssistImportReference(subset, positions, ClassFileConstants.AccStatic);
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush annotations defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.currentElement = this.currentElement.add(reference, 0);
		this.lastIgnoredToken = -1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
protected void consumeSingleTypeImportDeclarationName() {
	// SingleTypeImportDeclarationName ::= '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.consumeSingleTypeImportDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on import statement */
	ImportReference reference = createAssistImportReference(subset, positions, ClassFileConstants.AccDefault);
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush comments defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.currentElement = this.currentElement.add(reference, 0);
		this.lastIgnoredToken = -1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
protected void consumeStaticImportOnDemandDeclarationName() {
	// TypeImportOnDemandDeclarationName ::= 'import' 'static' 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.consumeStaticImportOnDemandDeclarationName();
		return;
	}
	/* retrieve identifiers subset and whole positions, the assist node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on import statement */
	ImportReference reference = createAssistImportReference(subset, positions, ClassFileConstants.AccStatic);
	reference.bits |= ASTNode.OnDemand;
	// star end position
	reference.trailingStarPosition = this.intStack[this.intPtr--];
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush annotations defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.currentElement = this.currentElement.add(reference, 0);
		this.lastIgnoredToken = -1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
protected void consumeStaticInitializer() {
	super.consumeStaticInitializer();
	popElement(K_METHOD_DELIMITER);
}
protected void consumeStaticOnly() {
	super.consumeStaticOnly();
	pushOnElementStack(K_METHOD_DELIMITER);
}
protected void consumeToken(int token) {
	super.consumeToken(token);

	if(this.isFirst) {
		this.isFirst = false;
		return;
	}
	// register message send selector only if inside a method or if looking at a field initializer
	// and if the current token is an open parenthesis
	if (isInsideMethod() || isInsideFieldInitialization() || isInsideAttributeValue() || isInsideEnumConstantnitialization()) {
		switch (token) {
			case TokenNameLPAREN :
				this.bracketDepth++;
				switch (this.previousToken) {
					case TokenNameIdentifier:
						this.pushOnElementStack(K_SELECTOR, this.identifierPtr);
						break;
					case TokenNamethis: // explicit constructor invocation, e.g. this(1, 2)
						this.pushOnElementStack(K_SELECTOR, THIS_CONSTRUCTOR);
						break;
					case TokenNamesuper: // explicit constructor invocation, e.g. super(1, 2)
						this.pushOnElementStack(K_SELECTOR, SUPER_CONSTRUCTOR);
						break;
					case TokenNameGREATER: // explicit constructor invocation, e.g. Fred<X>[(]1, 2)
					case TokenNameRIGHT_SHIFT: // or fred<X<X>>[(]1, 2)
					case TokenNameUNSIGNED_RIGHT_SHIFT: //or Fred<X<X<X>>>[(]1, 2)
						if(this.identifierPtr > -1) {
							this.pushOnElementStack(K_SELECTOR, this.identifierPtr);
						}
						break;
				}
				break;
			case TokenNameLBRACE:
				if (this.previousToken == TokenNameARROW) {
					popElement(K_LAMBDA_EXPRESSION_DELIMITER);
					pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, BLOCK_BODY, this.previousObjectInfo);
				}
				this.bracketDepth++;
				break;
			case TokenNameLBRACKET:
				this.bracketDepth++;
				break;
			case TokenNameRBRACE:
				this.bracketDepth--;
				break;
			case TokenNameRBRACKET:
				this.bracketDepth--;
				break;
			case TokenNameRPAREN:
				this.bracketDepth--;
				break;
		}
	} else {
		switch (token) {
			case TokenNameRBRACE :
				if(topKnownElementKind(ASSIST_PARSER) == K_TYPE_DELIMITER) {
					popElement(K_TYPE_DELIMITER);
				}
				break;
		}
	}
	this.previousToken = token;
	if (token == TokenNameIdentifier) {
		this.previousIdentifierPtr = this.identifierPtr;
	}
}
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 = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific assist node on import statement */
	ImportReference reference = createAssistImportReference(subset, positions, ClassFileConstants.AccDefault);
	reference.bits |= ASTNode.OnDemand;
	// star end position
	reference.trailingStarPosition = this.intStack[this.intPtr--];
	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;

	pushOnAstStack(reference);

	if (this.currentToken == TokenNameSEMICOLON){
		reference.declarationSourceEnd = this.scanner.currentPosition - 1;
	} else {
		reference.declarationSourceEnd = (int) positions[length-1];
	}
	//endPosition is just before the ;
	reference.declarationSourceStart = this.intStack[this.intPtr--];
	// flush comments defined prior to import statements
	reference.declarationSourceEnd = flushCommentsDefinedPriorTo(reference.declarationSourceEnd);

	// recovery
	if (this.currentElement != null){
		this.lastCheckPoint = reference.declarationSourceEnd+1;
		this.currentElement = this.currentElement.add(reference, 0);
		this.lastIgnoredToken = -1;
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
	}
}
public abstract ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod);
public abstract ImportReference createAssistPackageReference(char[][] tokens, long[] positions);
public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
public abstract TypeReference createParameterizedQualifiedAssistTypeReference(char[][] previousIdentifiers, TypeReference[][] typeArguments, char[] asistIdentifier, TypeReference[] assistTypeArguments, long[] positions);
public abstract NameReference createSingleAssistNameReference(char[] assistName, long position);
public abstract TypeReference createSingleAssistTypeReference(char[] assistName, long position);
public abstract TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position);
/*
 * Flush parser/scanner state regarding to code assist
 */
public void flushAssistState(){
	this.assistNode = null;
	this.isOrphanCompletionNode = false;
	setAssistIdentifier(null);
}
protected void flushElementStack() {
	for (int j = 0; j <= this.elementPtr; j++) {
		this.elementObjectInfoStack[j] = null;
	}

	this.elementPtr = -1;
	this.previousKind = 0;
	this.previousInfo = 0;
	this.previousObjectInfo = null;
}
/*
 * Build specific type reference nodes in case the cursor is located inside the type reference
 */
protected TypeReference getTypeReference(int dim) {

	int index;

	/* no need to take action if not inside completed identifiers */
	if ((index = indexOfAssistIdentifier(true)) < 0) {
		return super.getTypeReference(dim);
	}
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	TypeReference reference;
	int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
	if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
		this.identifierLengthPtr--;
		// generic type
		reference = getAssistTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
	} else {
		/* retrieve identifiers subset and whole positions, the assist node positions
			should include the entire replaced source. */

		char[][] subset = identifierSubSet(index);
		this.identifierLengthPtr--;
		this.identifierPtr -= length;
		long[] positions = new long[length];
		System.arraycopy(
			this.identifierPositionStack,
			this.identifierPtr + 1,
			positions,
			0,
			length);

		/* build specific assist on type reference */

		if (index == 0) {
//			genericsIdentifiersLengthPtr--;
			this.genericsLengthPtr--;
			/* assist inside first identifier */
			reference = createSingleAssistTypeReference(
							assistIdentifier(),
							positions[0]);
		} else {
//			genericsIdentifiersLengthPtr--;
			this.genericsLengthPtr--;
			/* assist inside subsequent identifier */
			reference =	createQualifiedAssistTypeReference(
							subset,
							assistIdentifier(),
							positions);
		}
		this.assistNode = reference;
		this.lastCheckPoint = reference.sourceEnd + 1;
	}
	return reference;
}
protected TypeReference getAssistTypeReferenceForGenericType(int dim, int identifierLength, int numberOfIdentifiers) {
	/* no need to take action if not inside completed identifiers */
	if (/*(indexOfAssistIdentifier()) < 0 ||*/ (identifierLength == 1 && numberOfIdentifiers == 1)) {
		int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
		TypeReference[] typeArguments;
		if (currentTypeArgumentsLength > -1) {
			typeArguments = new TypeReference[currentTypeArgumentsLength];
			this.genericsPtr -= currentTypeArgumentsLength;
			System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments, 0, currentTypeArgumentsLength);
		} else {
			typeArguments = TypeReference.NO_TYPE_ARGUMENTS;
		}
		long[] positions = new long[identifierLength];
		System.arraycopy(
			this.identifierPositionStack,
			this.identifierPtr,
			positions,
			0,
			identifierLength);

		this.identifierPtr--;

		TypeReference reference = createParameterizedSingleAssistTypeReference(
				typeArguments,
				assistIdentifier(),
				positions[0]);

		this.assistNode = reference;
		this.lastCheckPoint = reference.sourceEnd + 1;
		return reference;
	}

	TypeReference[][] typeArguments = new TypeReference[numberOfIdentifiers][];
	char[][] tokens = new char[numberOfIdentifiers][];
	long[] positions = new long[numberOfIdentifiers];
	int index = numberOfIdentifiers;
	int currentIdentifiersLength = identifierLength;
	while (index > 0) {
		int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
		if (currentTypeArgumentsLength > 0) {
			this.genericsPtr -= currentTypeArgumentsLength;
			System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments[index - 1] = new TypeReference[currentTypeArgumentsLength], 0, currentTypeArgumentsLength);
		}
		switch(currentIdentifiersLength) {
			case 1 :
				// we are in a case A<B>.C<D> or A<B>.C<D>
				tokens[index - 1] = this.identifierStack[this.identifierPtr];
				positions[index - 1] = this.identifierPositionStack[this.identifierPtr--];
				break;
			default:
				// we are in a case A.B.C<B>.C<D> or A.B.C<B>...
				this.identifierPtr -= currentIdentifiersLength;
				System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, index - currentIdentifiersLength, currentIdentifiersLength);
				System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, index - currentIdentifiersLength, currentIdentifiersLength);
		}
		index -= currentIdentifiersLength;
		if (index > 0) {
			currentIdentifiersLength = this.identifierLengthStack[this.identifierLengthPtr--];
		}
	}

	// remove completion token
	int realLength = numberOfIdentifiers;
	for (int i = 0; i < numberOfIdentifiers; i++) {
		if(tokens[i] == assistIdentifier()) {
			realLength = i;
		}
	}
	TypeReference reference;
	if(realLength == 0) {
		if(typeArguments[0] != null && typeArguments[0].length > 0) {
			reference = createParameterizedSingleAssistTypeReference(typeArguments[0], assistIdentifier(), positions[0]);
		} else {
			reference = createSingleAssistTypeReference(assistIdentifier(), positions[0]);
		}
	} else {
		TypeReference[] assistTypeArguments = typeArguments[realLength];
		System.arraycopy(tokens, 0, tokens = new char[realLength][], 0, realLength);
		System.arraycopy(typeArguments, 0, typeArguments = new TypeReference[realLength][], 0, realLength);

		boolean isParameterized = false;
		for (int i = 0; i < typeArguments.length; i++) {
			if(typeArguments[i] != null) {
				isParameterized = true;
			}
		}
		if(isParameterized || (assistTypeArguments != null && assistTypeArguments.length > 0)) {
			reference = createParameterizedQualifiedAssistTypeReference(tokens, typeArguments, assistIdentifier(), assistTypeArguments, positions);
		} else {
			reference = createQualifiedAssistTypeReference(tokens, assistIdentifier(), positions);
		}
	}

	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	return reference;
}
/*
 * 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 completionIndex;

	/* no need to take action if not inside completed identifiers */
	if ((completionIndex = indexOfAssistIdentifier()) < 0) {
		return super.getUnspecifiedReferenceOptimized();
	}

	consumeNonTypeUseName();
	
	/* retrieve identifiers subset and whole positions, the completion node positions
		should include the entire replaced source. */
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	char[][] subset = identifierSubSet(completionIndex);
	this.identifierLengthPtr--;
	this.identifierPtr -= length;
	long[] positions = new long[length];
	System.arraycopy(
		this.identifierPositionStack,
		this.identifierPtr + 1,
		positions,
		0,
		length);

	/* build specific completion on name reference */
	NameReference reference;
	if (completionIndex == 0) {
		/* completion inside first identifier */
		reference = createSingleAssistNameReference(assistIdentifier(), positions[0]);
	} else {
		/* completion inside subsequent identifier */
		reference = createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
	}
	reference.bits &= ~ASTNode.RestrictiveFlagMASK;
	reference.bits |= Binding.LOCAL | Binding.FIELD;

	this.assistNode = reference;
	this.lastCheckPoint = reference.sourceEnd + 1;
	return reference;
}
public void goForBlockStatementsopt() {
	super.goForBlockStatementsopt();
	this.isFirst = true;
}
public void goForHeaders(){
	super.goForHeaders();
	this.isFirst = true;
}
public void goForCompilationUnit(){
	super.goForCompilationUnit();
	this.isFirst = true;
}
public void goForBlockStatementsOrCatchHeader() {
	super.goForBlockStatementsOrCatchHeader();
	this.isFirst = true;
}
/*
 * Retrieve a partial subset of a qualified name reference up to the completion point.
 * It does not pop the actual awaiting identifiers, so as to be able to retrieve position
 * information afterwards.
 */
protected char[][] identifierSubSet(int subsetLength){

	if (subsetLength == 0) return null;

	char[][] subset;
	System.arraycopy(
		this.identifierStack,
		this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + 1,
		(subset = new char[subsetLength][]),
		0,
		subsetLength);
	return subset;
}

protected int indexOfAssistIdentifier(){
	return this.indexOfAssistIdentifier(false);
}
/*
 * Iterate the most recent group of awaiting identifiers (grouped for qualified name reference (e.g. aa.bb.cc)
 * so as to check whether one of them is the assist identifier.
 * If so, then answer the index of the assist identifier (0 being the first identifier of the set).
 *	e.g. aa(0).bb(1).cc(2)
 * If no assist identifier was found, answers -1.
 */
protected int indexOfAssistIdentifier(boolean useGenericsStack){

	if (this.identifierLengthPtr < 0){
		return -1; // no awaiting identifier
	}

	char[] assistIdentifier ;
	if ((assistIdentifier = assistIdentifier()) == null){
		return -1; // no assist identifier found yet
	}

	// iterate awaiting identifiers backwards
	int length = this.identifierLengthStack[this.identifierLengthPtr];
	if(useGenericsStack && length > 0 && this.genericsIdentifiersLengthPtr > -1 ) {
		length = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
	}
	for (int i = 0; i < length; i++){
		if (this.identifierStack[this.identifierPtr - i] == assistIdentifier){
			return length - i - 1;
		}
	}
	// none of the awaiting identifiers is the completion one
	return -1;
}
public void initialize() {
	super.initialize();
	flushAssistState();
	flushElementStack();
	this.previousIdentifierPtr = -1;
	this.bracketDepth = 0;
}
public void initialize(boolean parsingCompilationUnit) {
	super.initialize(parsingCompilationUnit);
	flushAssistState();
	flushElementStack();
	this.previousIdentifierPtr = -1;
	this.bracketDepth = 0;
}
public abstract void initializeScanner();
protected boolean isIndirectlyInsideFieldInitialization(){
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == K_FIELD_INITIALIZER_DELIMITER)
			return true;
		i--;
	}
	return false;
}
protected boolean isIndirectlyInsideEnumConstantnitialization(){
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == K_ENUM_CONSTANT_DELIMITER)
			return true;
		i--;
	}
	return false;
}
protected boolean isIndirectlyInsideMethod(){
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == K_METHOD_DELIMITER)
			return true;
		i--;
	}
	return false;
}
protected boolean isIndirectlyInsideLambdaExpression(){
	int i = this.elementPtr;
	while (i > -1) {
		if (this.elementKindStack[i] == K_LAMBDA_EXPRESSION_DELIMITER)
			return true;
		i--;
	}
	return false;
}
protected boolean isIndirectlyInsideLambdaBlock(){
	int i = this.elementPtr;
	while (i > -1) {
		if (this.elementKindStack[i] == K_LAMBDA_EXPRESSION_DELIMITER && this.elementInfoStack[i] == BLOCK_BODY)
			return true;
		i--;
	}
	return false;
}
protected boolean isIndirectlyInsideType(){
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == K_TYPE_DELIMITER)
			return true;
		i--;
	}
	return false;
}
protected boolean isInsideAttributeValue(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return false;
			case K_METHOD_DELIMITER : return false;
			case K_FIELD_INITIALIZER_DELIMITER : return false;
			case K_ATTRIBUTE_VALUE_DELIMITER : return true;
		}
		i--;
	}
	return false;
}
protected boolean isInsideFieldInitialization(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return false;
			case K_METHOD_DELIMITER : return false;
			case K_FIELD_INITIALIZER_DELIMITER : 
				return true;
		}
		i--;
	}
	return false;
}
protected boolean isInsideEnumConstantnitialization(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return false;
			case K_METHOD_DELIMITER : return false;
			case K_ENUM_CONSTANT_DELIMITER :
				return true;
		}
		i--;
	}
	return false;
}
protected boolean isInsideMethod(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return false;
			case K_METHOD_DELIMITER : return true;
			case K_FIELD_INITIALIZER_DELIMITER : return false;
		}
		i--;
	}
	return false;
}
protected boolean isInsideType(){
	int i = this.elementPtr;
	while(i > -1) {
		switch (this.elementKindStack[i]) {
			case K_TYPE_DELIMITER : return true;
			case K_METHOD_DELIMITER : return false;
			case K_FIELD_INITIALIZER_DELIMITER : return false;
		}
		i--;
	}
	return false;
}
protected int lastIndexOfElement(int kind) {
	int i = this.elementPtr;
	while(i > -1) {
		if(this.elementKindStack[i] == kind) return i;
		i--;
	}
	return -1;
}
/**
 * Parse the block statements inside the given method declaration and try to complete at the
 * cursor location.
 */
public void parseBlockStatements(AbstractMethodDeclaration md, CompilationUnitDeclaration unit) {
	if (md instanceof MethodDeclaration) {
		parseBlockStatements((MethodDeclaration) md, unit);
	} else if (md instanceof ConstructorDeclaration) {
		parseBlockStatements((ConstructorDeclaration) md, unit);
	}
}
/**
 * Parse the block statements inside the given constructor declaration and try to complete at the
 * cursor location.
 */
public void parseBlockStatements(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
	//only parse the method body of cd
	//fill out its statements

	//convert bugs into parse error

	initialize();
	// set the lastModifiers to reflect the modifiers of the constructor whose
	// block statements are being parsed
	// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202634
	this.lastModifiers = cd.modifiers;
	this.lastModifiersStart = cd.modifiersSourceStart;
	// simulate goForConstructorBody except that we don't want to balance brackets because they are not going to be balanced
	goForBlockStatementsopt();

	this.referenceContext = cd;
	this.compilationUnit = unit;

	this.scanner.resetTo(cd.bodyStart, bodyEnd(cd));
	consumeNestedMethod();
	try {
		parse();
	} catch (AbortCompilation ex) {
		this.lastAct = ERROR_ACTION;
	}

	if (this.lastAct == ERROR_ACTION) {
		cd.bits |= ASTNode.HasSyntaxErrors;
		return;
	}

	// attach the statements as we might be searching for a reference to a local type
	cd.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
	int length;
	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
		this.astPtr -= length;
		if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall)
			//avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
			{
			System.arraycopy(
				this.astStack,
				this.astPtr + 2,
				cd.statements = new Statement[length - 1],
				0,
				length - 1);
			cd.constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1];
		} else { //need to add explicitly the super();
			System.arraycopy(
				this.astStack,
				this.astPtr + 1,
				cd.statements = new Statement[length],
				0,
				length);
			cd.constructorCall = SuperReference.implicitSuperConstructorCall();
		}
	} else {
		cd.constructorCall = SuperReference.implicitSuperConstructorCall();
		if (!containsComment(cd.bodyStart, cd.bodyEnd)) {
			cd.bits |= ASTNode.UndocumentedEmptyBlock;
		}
	}

	if (cd.constructorCall.sourceEnd == 0) {
		cd.constructorCall.sourceEnd = cd.sourceEnd;
		cd.constructorCall.sourceStart = cd.sourceStart;
	}
}
/**
 * Parse the block statements inside the given initializer and try to complete at the
 * cursor location.
 */
public void parseBlockStatements(
	Initializer initializer,
	TypeDeclaration type,
	CompilationUnitDeclaration unit) {

	initialize();
	// set the lastModifiers to reflect the modifiers of the initializer whose
	// block statements are being parsed
	// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202634
	this.lastModifiers = initializer.modifiers;
	this.lastModifiersStart = initializer.modifiersSourceStart;
	// simulate goForInitializer except that we don't want to balance brackets because they are not going to be balanced
	goForBlockStatementsopt();

	this.referenceContext = type;
	this.compilationUnit = unit;

	this.scanner.resetTo(initializer.sourceStart, bodyEnd(initializer)); // just after the beginning {
	consumeNestedMethod();
	try {
		parse();
	} catch (AbortCompilation ex) {
		this.lastAct = ERROR_ACTION;
	} finally {
		this.nestedMethod[this.nestedType]--;
	}

	if (this.lastAct == ERROR_ACTION) {
		initializer.bits |= ASTNode.HasSyntaxErrors;
		return;
	}

	// attach the statements as we might be searching for a reference to a local type
	initializer.block.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
	int length;
	if ((length = this.astLengthStack[this.astLengthPtr--]) > 0) {
		System.arraycopy(this.astStack, (this.astPtr -= length) + 1, initializer.block.statements = new Statement[length], 0, length);
	} else {
		// check whether this block at least contains some comment in it
		if (!containsComment(initializer.block.sourceStart, initializer.block.sourceEnd)) {
			initializer.block.bits |= ASTNode.UndocumentedEmptyBlock;
		}
	}

	// mark initializer with local type if one was found during parsing
	if ((type.bits & ASTNode.HasLocalType) != 0) {
		initializer.bits |= ASTNode.HasLocalType;
	}
}

/**
 * Parse the block statements inside the given method declaration and try to complete at the
 * cursor location.
 */
public void parseBlockStatements(MethodDeclaration md, CompilationUnitDeclaration unit) {
	//only parse the method body of md
	//fill out method statements

	//convert bugs into parse error

	if (md.isAbstract())
		return;
	if (md.isNative())
		return;
	if ((md.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0)
		return;

	initialize();
	// set the lastModifiers to reflect the modifiers of the method whose
	// block statements are being parsed
	// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202634
	this.lastModifiers = md.modifiers;
	this.lastModifiersStart = md.modifiersSourceStart;
	// simulate goForMethodBody except that we don't want to balance brackets because they are not going to be balanced
	goForBlockStatementsopt();

	this.referenceContext = md;
	this.compilationUnit = unit;

	this.scanner.resetTo(md.bodyStart, bodyEnd(md)); // reset the scanner to parser from { down to the cursor location
	consumeNestedMethod();
	try {
		parse();
	} catch (AbortCompilation ex) {
		this.lastAct = ERROR_ACTION;
	} finally {
		this.nestedMethod[this.nestedType]--;
	}

	if (this.lastAct == ERROR_ACTION) {
		md.bits |= ASTNode.HasSyntaxErrors;
		return;
	}

	// attach the statements as we might be searching for a reference to a local type
	md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
	int length;
	if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
		System.arraycopy(
			this.astStack,
			(this.astPtr -= length) + 1,
			md.statements = new Statement[length],
			0,
			length);
	} else {
		if (!containsComment(md.bodyStart, md.bodyEnd)) {
			md.bits |= ASTNode.UndocumentedEmptyBlock;
		}
	}

}

// the name is a misnomer, we allow "pop"s not just at the TOS. Lambda wants to be sticky till fully reduced, however we do want other elements popped at the right point, so ... 
protected void popElement(int kind) {
	
	if (this.elementPtr < 0)
		return;
	
	int stackPointer = this.elementPtr;

	if (kind != K_LAMBDA_EXPRESSION_DELIMITER) {
		while (this.elementKindStack[stackPointer] == K_LAMBDA_EXPRESSION_DELIMITER) {
			if (--stackPointer < 0) break;
		}
	}
	if (stackPointer < 0 || this.elementKindStack[stackPointer] != kind)
		return;
	
	this.previousKind = this.elementKindStack[stackPointer];
	this.previousInfo = this.elementInfoStack[stackPointer];
	this.previousObjectInfo = this.elementObjectInfoStack[stackPointer];

	final int length = this.elementPtr - stackPointer;
	if (length > 0) {
		System.arraycopy(this.elementKindStack, stackPointer + 1, this.elementKindStack, stackPointer, length);
		System.arraycopy(this.elementInfoStack, stackPointer + 1, this.elementInfoStack, stackPointer, length);
		System.arraycopy(this.elementObjectInfoStack, stackPointer + 1, this.elementObjectInfoStack, stackPointer, length);
	}
	this.elementObjectInfoStack[this.elementPtr] = null;
	this.elementPtr--;
 }
protected void popUntilElement(int kind){
	if(this.elementPtr < 0) return;
	int i = this.elementPtr;
	while (i >= 0 && this.elementKindStack[i] != kind) {
		i--;
	}
	if(i >= 0) {
		if(i < this.elementPtr) {
			this.previousKind = this.elementKindStack[i+1];
			this.previousInfo = this.elementInfoStack[i+1];
			this.previousObjectInfo = this.elementObjectInfoStack[i+1];

			for (int j = i + 1; j <= this.elementPtr; j++) {
				this.elementObjectInfoStack[j] = null;
			}
		}
		this.elementPtr = i;
	}
}
/*
 * Prepares the state of the parser to go for BlockStatements.
 */
protected void prepareForBlockStatements() {
	this.nestedMethod[this.nestedType = 0] = 1;
	this.variablesCounter[this.nestedType] = 0;
	this.realBlockStack[this.realBlockPtr = 1] = 0;

	// initialize element stack
	int fieldInitializerIndex = lastIndexOfElement(K_FIELD_INITIALIZER_DELIMITER);
	int methodIndex = lastIndexOfElement(K_METHOD_DELIMITER);
	if(methodIndex == fieldInitializerIndex) {
		// there is no method and no field initializer
		flushElementStack();
	} else if(methodIndex > fieldInitializerIndex) {
		popUntilElement(K_METHOD_DELIMITER);
	} else {
		popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
	}
}
/*
 * Prepares the state of the parser to go for Headers.
 */
protected void prepareForHeaders() {
	this.nestedMethod[this.nestedType = 0] = 0;
	this.variablesCounter[this.nestedType] = 0;
	this.realBlockStack[this.realBlockPtr = 0] = 0;

	popUntilElement(K_TYPE_DELIMITER);

	if(this.topKnownElementKind(ASSIST_PARSER) != K_TYPE_DELIMITER) {
		// is outside a type and inside a compilation unit.
		// remove all elements.
		flushElementStack();
	}
}

public boolean requireExtendedRecovery() {
	return lastIndexOfElement(K_LAMBDA_EXPRESSION_DELIMITER) >= 0;
}

protected void pushOnElementStack(int kind){
	this.pushOnElementStack(kind, 0, null);
}
protected void pushOnElementStack(int kind, int info){
	this.pushOnElementStack(kind, info, null);
}
protected void pushOnElementStack(int kind, int info, Object objectInfo){
	if (this.elementPtr < -1) return;

	this.previousKind = 0;
	this.previousInfo = 0;
	this.previousObjectInfo = null;

	int stackLength = this.elementKindStack.length;
	if (++this.elementPtr >= stackLength) {
		System.arraycopy(
			this.elementKindStack, 0,
			this.elementKindStack = new int[stackLength + StackIncrement], 0,
			stackLength);
		System.arraycopy(
			this.elementInfoStack, 0,
			this.elementInfoStack = new int[stackLength + StackIncrement], 0,
			stackLength);
		System.arraycopy(
			this.elementObjectInfoStack, 0,
			this.elementObjectInfoStack = new Object[stackLength + StackIncrement], 0,
			stackLength);
	}
	this.elementKindStack[this.elementPtr] = kind;
	this.elementInfoStack[this.elementPtr] = info;
	this.elementObjectInfoStack[this.elementPtr] = objectInfo;
}
public void recoveryExitFromVariable() {
	if(this.currentElement != null && this.currentElement instanceof RecoveredField
		&& !(this.currentElement instanceof RecoveredInitializer)) {
		RecoveredElement oldElement = this.currentElement;
		super.recoveryExitFromVariable();
		if(oldElement != this.currentElement) {
			popElement(K_FIELD_INITIALIZER_DELIMITER);
		}
	} else {
		super.recoveryExitFromVariable();
	}
}
public void recoveryTokenCheck() {
	RecoveredElement oldElement = this.currentElement;
	switch (this.currentToken) {
		case TokenNameLBRACE :
			super.recoveryTokenCheck();
			if(this.currentElement instanceof RecoveredInitializer) {
				if(oldElement instanceof RecoveredField) {
					popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
					popElement(K_FIELD_INITIALIZER_DELIMITER);
				}
				if(this.currentElement != oldElement
					&& topKnownElementKind(ASSIST_PARSER) != K_METHOD_DELIMITER) {
					pushOnElementStack(K_METHOD_DELIMITER);
				}
			}
			break;
		case TokenNameRBRACE :
			super.recoveryTokenCheck();
			if(this.currentElement != oldElement && !isInsideAttributeValue() && !isIndirectlyInsideLambdaExpression()) {
				if(oldElement instanceof RecoveredInitializer
					|| oldElement instanceof RecoveredMethod
					|| (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredInitializer)
					|| (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredMethod)) {
					popUntilElement(K_METHOD_DELIMITER);
					popElement(K_METHOD_DELIMITER);
				} else if(oldElement instanceof RecoveredType) {
					popUntilElement(K_TYPE_DELIMITER);
					if(!(this.referenceContext instanceof CompilationUnitDeclaration)
							|| isIndirectlyInsideFieldInitialization()
							|| this.currentElement instanceof RecoveredUnit) {
						popElement(K_TYPE_DELIMITER);
					}
				}
			}
			break;
		default :
			super.recoveryTokenCheck();
			break;
	}
}
public void reset(){
	flushAssistState();
}

protected void commit() {
	if (this.snapShot == null) {
		this.snapShot = createSnapShotParser();
	}
	this.snapShot.copyState(this);
}

protected boolean assistNodeNeedsStacking() {
	return false;
}

protected void shouldStackAssistNode() {
	// Not relevant here.
}

protected int getNextToken() {
	try {
		return this.scanner.getNextToken();
	} catch (InvalidInputException e) {
		return TokenNameEOF;
	}
}

protected abstract AssistParser createSnapShotParser();

// We get here on real syntax error or syntax error triggered by fake EOF at completion site, never due to triggered recovery.
protected int fallBackToSpringForward(Statement unused) {
	int nextToken;
	int automatonState = automatonState();
			
	// If triggered fake EOF at completion site, see if the real next token would have passed muster.
	if (this.currentToken == TokenNameEOF) {
		if (this.scanner.eofPosition < this.scanner.source.length) {
			shouldStackAssistNode();
			this.scanner.eofPosition = this.scanner.source.length;
			nextToken = getNextToken();
			if (automatonWillShift(nextToken, automatonState)) {
				this.currentToken = nextToken;
				return RESUME;
			}
			this.scanner.ungetToken(nextToken); // spit out what has been bitten more than we can chew.
		} else {
			return HALT; // don't know how to proceed.
		}
	} else {
		nextToken = this.currentToken;
		this.scanner.ungetToken(nextToken);
		if (nextToken == TokenNameRBRACE)
			ignoreNextClosingBrace(); // having ungotten it, recoveryTokenCheck will see this again. 
	}
	// OK, next token is no good to resume "in place", attempt some local repair. FIXME: need to make sure we don't get stuck keep reducing empty statements !!
	for (int i = 0, length = RECOVERY_TOKENS.length; i < length; i++) {
		if (automatonWillShift(RECOVERY_TOKENS[i], automatonState)) {
			this.currentToken = RECOVERY_TOKENS[i];
			return RESUME;
		}
	}
	// OK, no in place resumption, no local repair, fast forward to next statement.
	if (this.snapShot == null)
		return RESTART;

	this.copyState(this.snapShot);
	if (assistNodeNeedsStacking()) {
		this.currentToken = TokenNameSEMICOLON;
		return RESUME;
	}
	this.currentToken = this.scanner.fastForward(unused);
	return RESUME;
}


/*
 * 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 int resumeAfterRecovery() {
	if (requireExtendedRecovery()) {
		if (this.unstackedAct == ERROR_ACTION) {
			int mode = fallBackToSpringForward((Statement) null);
			this.resumedAfterRepair = mode == RESUME;
			if (mode == RESUME || mode == HALT)
				return mode;
			// else fall through and RESTART
		} else {
			if (this.currentToken == TokenNameLBRACE)
				this.ignoreNextOpeningBrace = true;  // already accounted for in recovery token check.
			return RESUME;
		}
	}
		
	// reset internal stacks
	this.astPtr = -1;
	this.astLengthPtr = -1;
	this.expressionPtr = -1;
	this.expressionLengthPtr = -1;
	this.typeAnnotationLengthPtr = -1;
	this.typeAnnotationPtr = -1;
	
	this.identifierPtr = -1;
	this.identifierLengthPtr	= -1;
	this.intPtr = -1;
	
	
	this.dimensions = 0 ;
	this.recoveredStaticInitializerStart = 0;

	this.genericsIdentifiersLengthPtr = -1;
	this.genericsLengthPtr = -1;
	this.genericsPtr = -1;
	
	this.valueLambdaNestDepth = -1;

	this.modifiers = ClassFileConstants.AccDefault;
	this.modifiersSourceStart = -1;

	// if in diet mode, reset the diet counter because we're going to restart outside an initializer.
	if (this.diet) this.dietInt = 0;

	/* attempt to move checkpoint location */
	if (this.unstackedAct != ERROR_ACTION && this.resumedAfterRepair) {
		this.scanner.ungetToken(this.currentToken);  // effectively move recovery checkpoint *backwards*.
	} else {
		if (!moveRecoveryCheckpoint()) return HALT;
	}
	this.resumedAfterRepair = false;

	// only look for headers
	if (this.referenceContext instanceof CompilationUnitDeclaration
		|| this.assistNode != null){
		if(isInsideMethod() &&
			isIndirectlyInsideFieldInitialization() &&
			this.assistNode == null
			){
			prepareForBlockStatements();
			goForBlockStatementsOrCatchHeader();
		} else if((isInsideArrayInitializer()) &&
				isIndirectlyInsideFieldInitialization() &&
				this.assistNode == null){
			prepareForBlockStatements();
			goForBlockStatementsopt();
		} else {
			prepareForHeaders();
			goForHeaders();
			this.diet = true; // passed this point, will not consider method bodies
			this.dietInt = 0;
		}
		return RESTART;
	}
	if (this.referenceContext instanceof AbstractMethodDeclaration
		|| this.referenceContext instanceof TypeDeclaration){

		if (this.currentElement instanceof RecoveredType){
			prepareForHeaders();
			goForHeaders();
		} else {
			prepareForBlockStatements();
			goForBlockStatementsOrCatchHeader();
		}
		return RESTART;
	}
	// does not know how to restart
	return HALT;
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292087
// To be implemented in children viz. CompletionParser that are aware of array initializers
protected boolean isInsideArrayInitializer() {
	return false;
}
public abstract void setAssistIdentifier(char[] assistIdent);
protected int topKnownElementInfo(int owner) {
	return topKnownElementInfo(owner, 0);
}
protected int topKnownElementInfo(int owner, int offSet) {
	int i = this.elementPtr;
	while(i > -1) {
		if((this.elementKindStack[i] & owner) != 0) {
			if(offSet <= 0) return this.elementInfoStack[i];
			offSet--;
		}
		i--;
	}
	return 0;
}
protected int topKnownElementKind(int owner) {
	return topKnownElementKind(owner, 0);
}
protected int topKnownElementKind(int owner, int offSet) {
	int i = this.elementPtr;
	while(i > -1) {
		if((this.elementKindStack[i] & owner) != 0) {
			if(offSet <= 0) return this.elementKindStack[i];
			offSet--;
		}
		i--;
	}
	return 0;
}
protected Object topKnownElementObjectInfo(int owner, int offSet) {
	int i = this.elementPtr;
	while(i > -1) {
		if((this.elementKindStack[i] & owner) != 0) {
			if(offSet <= 0) return this.elementObjectInfoStack[i];
			offSet--;
		}
		i--;
	}
	return null;
}
protected Object topKnownElementObjectInfo(int owner) {
	return topKnownElementObjectInfo(owner, 0);
}
/**
 * If the given ast node is inside an explicit constructor call
 * then wrap it with a fake constructor call.
 * Returns the wrapped completion node or the completion node itself.
 */
protected ASTNode wrapWithExplicitConstructorCallIfNeeded(ASTNode ast) {
	int selector;
	if (ast != null && topKnownElementKind(ASSIST_PARSER) == K_SELECTOR && ast instanceof Expression &&
			(((selector = topKnownElementInfo(ASSIST_PARSER)) == THIS_CONSTRUCTOR) ||
			(selector == SUPER_CONSTRUCTOR))) {
		ExplicitConstructorCall call = new ExplicitConstructorCall(
			(selector == THIS_CONSTRUCTOR) ?
				ExplicitConstructorCall.This :
				ExplicitConstructorCall.Super
		);
		call.arguments = new Expression[] {(Expression)ast};
		call.sourceStart = ast.sourceStart;
		call.sourceEnd = ast.sourceEnd;
		return call;
	} else {
		return ast;
	}
}
}
