+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v0.5
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v05.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- ******************************************************************************/
-package net.sourceforge.phpdt.internal.codeassist.complete;
-
-/*
- * 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 net.sourceforge.phpdt.internal.codeassist.impl.AssistParser;
-import net.sourceforge.phpdt.internal.compiler.CompilationResult;
-import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
-import net.sourceforge.phpdt.internal.compiler.ast.AbstractVariableDeclaration;
-import net.sourceforge.phpdt.internal.compiler.ast.AllocationExpression;
-import net.sourceforge.phpdt.internal.compiler.ast.Argument;
-import net.sourceforge.phpdt.internal.compiler.ast.Assignment;
-import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
-import net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression;
-import net.sourceforge.phpdt.internal.compiler.ast.CastExpression;
-import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
-import net.sourceforge.phpdt.internal.compiler.ast.ConditionalExpression;
-import net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall;
-import net.sourceforge.phpdt.internal.compiler.ast.Expression;
-import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
-import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
-import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
-import net.sourceforge.phpdt.internal.compiler.ast.InstanceOfExpression;
-import net.sourceforge.phpdt.internal.compiler.ast.LabeledStatement;
-import net.sourceforge.phpdt.internal.compiler.ast.Literal;
-import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
-import net.sourceforge.phpdt.internal.compiler.ast.NameReference;
-import net.sourceforge.phpdt.internal.compiler.ast.QualifiedAllocationExpression;
-import net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference;
-import net.sourceforge.phpdt.internal.compiler.ast.Reference;
-import net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference;
-import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
-import net.sourceforge.phpdt.internal.compiler.ast.Statement;
-import net.sourceforge.phpdt.internal.compiler.ast.SuperReference;
-import net.sourceforge.phpdt.internal.compiler.ast.ThisReference;
-import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
-import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
-import net.sourceforge.phpdt.internal.compiler.ast.UnaryExpression;
-import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
-import net.sourceforge.phpdt.internal.compiler.parser.RecoveredMethod;
-import net.sourceforge.phpdt.internal.compiler.parser.RecoveredType;
-import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
-
-public class CompletionParser extends AssistParser {
-
- /* public fields */
-
- public int cursorLocation;
- public char[][] labels; // the visible labels up to the cursor location
- public AstNode assistNodeParent; // the parent node of assist node
- /* 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
-
- boolean nextTypeReferenceIsClass;
- boolean nextTypeReferenceIsException;
- boolean nextTypeReferenceIsInterface;
-
- int bracketDepth;
- int throwBracketDepth;
-
- // 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];
-
- // last modifiers info
- int lastModifiers = AccDefault;
- int lastModifiersStart = -1;
-
-public CompletionParser(ProblemReporter problemReporter, boolean assertMode) {
- super(problemReporter, assertMode);
-}
-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){
- CompletionOnFieldType fieldDeclaration = new CompletionOnFieldType((TypeReference)orphan, false);
-
- // retrieve available modifiers if any
- if (intPtr >= 2 && intStack[intPtr-1] == this.lastModifiersStart && intStack[intPtr-2] == this.lastModifiers){
- fieldDeclaration.modifiersSourceStart = intStack[intPtr-1];
- fieldDeclaration.modifiers = intStack[intPtr-2];
- }
-
- currentElement = currentElement.add(fieldDeclaration, 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, true), 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.getLineNumber(orphan.sourceStart) == scanner.getLineNumber(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.inFieldInitializationStack[this.inFieldInitializationPtr])) {
- 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.getLineNumber(expression.sourceStart) == scanner.getLineNumber(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
-
- if(this.throwBracketDepth != -1 && this.throwBracketDepth == this.bracketDepth) {
- this.nextTypeReferenceIsException = true;
- }
- TypeReference type = getTypeReference(0);
- this.nextTypeReferenceIsException = false;
- this.assistNode = type;
- this.lastCheckPoint = type.sourceEnd + 1;
- if (this.invocationType == ALLOCATION) {
- // non qualified allocation expression
- AllocationExpression allocExpr = new AllocationExpression();
- allocExpr.type = type;
- allocExpr.sourceStart = type.sourceStart;
- allocExpr.sourceEnd = type.sourceEnd;
- pushOnExpressionStack(allocExpr);
- this.isOrphanCompletionNode = false;
- } 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--];
- if (dim == 0) {
- typeRef.sourceEnd = this.intStack[this.intPtr--];
- } else {
- this.intPtr--;
- typeRef.sourceEnd = this.endPosition;
- }
- //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 special flags for primitive types
- while (this.identifierLengthPtr >= 0 && this.identifierLengthStack[this.identifierLengthPtr] < 0) {
- this.identifierLengthPtr--;
- }
-
- // 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
- int selectorPtr = this.selectorStack[this.invocationPtr];
- messageSend.selector = this.identifierStack[selectorPtr];
- // remove selector
- if (this.identifierLengthPtr >=0 && this.identifierLengthStack[this.identifierLengthPtr] == 1) {
- this.identifierPtr--;
- this.identifierLengthPtr--;
- }
-
- // the entire message may be replaced in case qualification is needed
- messageSend.sourceStart = (int)(this.identifierPositionStack[selectorPtr] >> 32); //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.getLineNumber(lastErrorEndPosition)
- == scanner.getLineNumber(((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.getLineNumber(lastErrorEndPosition)
- == scanner.getLineNumber(((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)
- && !insideFieldInitialization()) 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 consumeClassHeaderExtends() {
- this.nextTypeReferenceIsClass = true;
- super.consumeClassHeaderExtends();
- this.nextTypeReferenceIsClass = false;
-}
-protected void consumeClassTypeElt() {
- this.nextTypeReferenceIsException = true;
- super.consumeClassTypeElt();
- this.nextTypeReferenceIsException = false;
-}
-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--;
- if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
-}
-protected void consumeConstructorHeader() {
- super.consumeConstructorHeader();
- pushBlockInvocationPtr();
-}
-protected void consumeConstructorHeaderName() {
-
- /* no need to take action if not inside assist identifiers */
- if (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;
-}
-protected void consumeEnterVariable() {
- identifierPtr--;
- identifierLengthPtr--;
-
- boolean isLocalDeclaration = nestedMethod[nestedType] != 0;
- int variableIndex = variablesCounter[nestedType];
- int extendedDimension = intStack[intPtr + 1];
-
- if(isLocalDeclaration || indexOfAssistIdentifier() < 0 || variableIndex != 0 || extendedDimension != 0) {
- identifierPtr++;
- identifierLengthPtr++;
- super.consumeEnterVariable();
- } else {
- restartRecovery = true;
-
- // recovery
- if (currentElement != null) {
- int nameSourceStart = (int)(identifierPositionStack[identifierPtr] >>> 32);
- intPtr--;
-
- TypeReference type = getTypeReference(intStack[intPtr--]);
- intPtr--;
-
- if (!(currentElement instanceof RecoveredType)
- && (currentToken == TokenNameDOT
- || (scanner.getLineNumber(type.sourceStart)
- != scanner.getLineNumber(nameSourceStart)))){
- lastCheckPoint = nameSourceStart;
- restartRecovery = true;
- return;
- }
-
- FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
- completionFieldDecl.modifiers = intStack[intPtr--];
- assistNode = completionFieldDecl;
- lastCheckPoint = type.sourceEnd + 1;
- currentElement = currentElement.add(completionFieldDecl, 0);
- lastIgnoredToken = -1;
- }
- }
-}
-protected void consumeExitVariableWithInitialization() {
- super.consumeExitVariableWithInitialization();
-
- // does not keep the initialization if completion is not inside
- AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
- if (cursorLocation + 1 < variable.initialization.sourceStart ||
- cursorLocation > variable.initialization.sourceEnd) {
- variable.initialization = null;
- }
-}
-
-/*
- * 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 consumeFormalParameter() {
- if (this.indexOfAssistIdentifier() < 0) {
- super.consumeFormalParameter();
- } else {
-
- identifierLengthPtr--;
- char[] name = identifierStack[identifierPtr];
- long namePositions = identifierPositionStack[identifierPtr--];
- TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
- intPtr -= 2;
- Argument arg =
- new CompletionOnArgumentName(
- name,
- namePositions,
- type,
- intStack[intPtr + 1] & ~AccDeprecated); // modifiers
- pushOnAstStack(arg);
-
- assistNode = arg;
- this.lastCheckPoint = (int) namePositions;
- isOrphanCompletionNode = true;
-
- /* if incomplete method header, listLength counter will not have been reset,
- indicating that some arguments are available on the stack */
- listLength++;
- }
-}
-protected void consumeInterfaceType() {
- this.nextTypeReferenceIsInterface = true;
- super.consumeInterfaceType();
- this.nextTypeReferenceIsInterface = false;
-}
-protected void consumeMethodHeaderName() {
- if(this.indexOfAssistIdentifier() < 0) {
- identifierPtr--;
- identifierLengthPtr--;
- if(this.indexOfAssistIdentifier() != 0) {
- identifierPtr++;
- identifierLengthPtr++;
- super.consumeMethodHeaderName();
- } else {
- restartRecovery = true;
-
- // recovery
- if (currentElement != null) {
- //name
- char[] selector = identifierStack[identifierPtr + 1];
- long selectorSource = identifierPositionStack[identifierPtr + 1];
-
- //type
- TypeReference type = getTypeReference(intStack[intPtr--]);
- ((CompletionOnSingleTypeReference)type).isCompletionNode = false;
- //modifiers
- int declarationSourceStart = intStack[intPtr--];
- int modifiers = intStack[intPtr--];
-
- if(scanner.getLineNumber(type.sourceStart) != scanner.getLineNumber((int) (selectorSource >>> 32))) {
- FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
- completionFieldDecl.modifiers = modifiers;
- assistNode = completionFieldDecl;
- lastCheckPoint = type.sourceEnd + 1;
- currentElement = currentElement.add(completionFieldDecl, 0);
- lastIgnoredToken = -1;
- } else {
- CompletionOnMethodReturnType md = new CompletionOnMethodReturnType(type, this.compilationUnit.compilationResult);
- md.selector = selector;
- md.declarationSourceStart = declarationSourceStart;
- md.modifiers = modifiers;
- md.bodyStart = lParenPos+1;
- listLength = 0; // initialize listLength before reading parameters/throws
- assistNode = md;
- this.lastCheckPoint = md.bodyStart;
- currentElement = currentElement.add(md, 0);
- lastIgnoredToken = -1;
- }
- }
- }
- } else {
- // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
- CompletionOnMethodName md = new CompletionOnMethodName(this.compilationUnit.compilationResult);
-
- //name
- md.selector = identifierStack[identifierPtr];
- long selectorSource = identifierPositionStack[identifierPtr--];
- //type
- md.returnType = getTypeReference(intStack[intPtr--]);
- //modifiers
- md.declarationSourceStart = intStack[intPtr--];
- md.modifiers = intStack[intPtr--];
-
- //highlight starts at selector start
- md.sourceStart = (int) (selectorSource >>> 32);
- md.selectorEnd = (int) selectorSource;
- pushOnAstStack(md);
- md.sourceEnd = lParenPos;
- md.bodyStart = lParenPos+1;
- listLength = 0; // initialize listLength before reading parameters/throws
-
- this.assistNode = md;
- this.lastCheckPoint = md.sourceEnd;
- // recovery
- if (currentElement != null){
- if (currentElement instanceof RecoveredType
- //|| md.modifiers != 0
- || (scanner.getLineNumber(md.returnType.sourceStart)
- == scanner.getLineNumber(md.sourceStart))){
- lastCheckPoint = md.bodyStart;
- currentElement = currentElement.add(md, 0);
- lastIgnoredToken = -1;
- } else {
- lastCheckPoint = md.sourceStart;
- restartRecovery = true;
- }
- }
- }
-}
-
-
-protected void consumeMethodBody() {
- super.consumeMethodBody();
- this.labelCounterPtr--;
- if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
-}
-
-protected void consumeMethodHeader() {
- super.consumeMethodHeader();
- pushBlockInvocationPtr();
-}
-protected void consumeModifiers() {
- super.consumeModifiers();
- // save from stack values
- this.lastModifiersStart = intStack[intPtr];
- this.lastModifiers = intStack[intPtr-1];
-}
-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.insideFieldInitialization()) {
- this.scanner.eofPosition = cursorLocation < Integer.MAX_VALUE ? cursorLocation+1 : cursorLocation;
- }
-
- // if in a method or if in a field initializer
- if (this.inMethodStack[this.inMethodPtr] || this.inFieldInitializationStack[this.inFieldInitializationPtr]) {
- 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;
- this.bracketDepth++;
- 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.bracketDepth++;
- this.pushBlockInvocationPtr();
- break;
- case TokenNameLBRACKET:
- this.betweenNewAndLeftBraket = false;
- this.bracketDepth++;
- break;
- case TokenNameRBRACE:
- this.bracketDepth--;
- if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
- break;
- case TokenNameRBRACKET:
- this.bracketDepth--;
- break;
- case TokenNameRPAREN:
- this.betweenCatchAndRightParen = false;
- this.bracketDepth--;
- break;
- case TokenNameCOLON:
- if (previous == TokenNameIdentifier) {
- if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]++;
- }
- break;
-// case TokenNamethrow:
-// this.throwBracketDepth= bracketDepth;
-// 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 || this.nextTypeReferenceIsException // check for exception scenario
- ? new CompletionOnQualifiedExceptionReference(
- previousIdentifiers,
- name,
- positions)
- : this.nextTypeReferenceIsInterface
- ? new CompletionOnQualifiedInterfaceReference(
- previousIdentifiers,
- name,
- positions)
- : this.nextTypeReferenceIsClass
- ? new CompletionOnQualifiedClassReference(
- 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 || this.nextTypeReferenceIsException // check for exception scenario
- ? new CompletionOnExceptionReference(name, position)
- : this.nextTypeReferenceIsInterface
- ? new CompletionOnInterfaceReference(name, position)
- : this.nextTypeReferenceIsClass
- ? new CompletionOnClassReference(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;
- 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.bracketDepth = 0;
- this.throwBracketDepth = -1;
- this.invocationType = NO_RECEIVER;
- this.qualifier = -1;
- this.blockInvocationPtr = -1;
-}
-public void initializeScanner(){
- this.scanner = new CompletionScanner(this.assertMode);
-}
-/**
- * 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[]")
- 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.blockInvocationStack;
- 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), false), 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 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)
- || insideFieldInitialization())) {
-
- /* 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;
- int end = currentElement.topElement().sourceEnd();
- scanner.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
- } 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();
-
- // if an assist node has been found and a recovered element exists,
- // mark enclosing blocks as to be preserved
- if (this.assistNode != null && this.currentElement != null) {
- currentElement.preserveEnclosingBlocks();
- }
-
- /* check and update recovered state based on current token,
- this action is also performed when shifting token after recovery
- got activated once.
- */
- this.recoveryTokenCheck();
-}
-
-protected LocalDeclaration createLocalDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
- if (this.indexOfAssistIdentifier() < 0) {
- return super.createLocalDeclaration(initialization, name, sourceStart, sourceEnd);
- } else {
- CompletionOnLocalName local = new CompletionOnLocalName(initialization, name, sourceStart, sourceEnd);
- this.assistNode = local;
- this.lastCheckPoint = sourceEnd + 1;
- return local;
- }
-}
-
-protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
- if (this.indexOfAssistIdentifier() < 0) {
- return super.createFieldDeclaration(initialization, name, sourceStart, sourceEnd);
- } else {
- CompletionOnFieldName field = new CompletionOnFieldName(initialization, name, sourceStart, sourceEnd);
- this.assistNode = field;
- this.lastCheckPoint = sourceEnd + 1;
- return field;
- }
-}
-
-}