/* * Record a field declaration */ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) { this.resetPendingModifiers(); /* local variables inside method can only be final and non void */ char[][] fieldTypeName; if ((fieldDeclaration.modifiers & ~ClassFileConstants.AccFinal) != 0 // local var can only be final || (fieldDeclaration.type == null) // initializer || ((fieldTypeName = fieldDeclaration.type.getTypeName()).length == 1 // non void && CharOperation.equals(fieldTypeName[0], TypeBinding.VOID.sourceName()))) { if (this.parent == null) { return this; // ignore } else { this.updateSourceEndIfNecessary( this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1)); return this.parent.add(fieldDeclaration, bracketBalanceValue); } } /* default behavior is to delegate recording to parent if any, do not consider elements passed the known end (if set) it must be belonging to an enclosing element */ if (methodDeclaration.declarationSourceEnd > 0 && fieldDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd) { if (this.parent == null) { return this; // ignore } else { return this.parent.add(fieldDeclaration, bracketBalanceValue); } } /* consider that if the opening brace was not found, it is there */ if (!foundOpeningBrace) { foundOpeningBrace = true; this.bracketBalance++; } // still inside method, treat as local variable return this; // ignore }
/* * Update the corresponding parse node from parser state which * is about to disappear because of restarting recovery */ public void updateFromParserState() { // if parent is null then recovery already occured in diet parser. if (this.bodyStartsAtHeaderEnd() && this.parent != null) { Parser parser = this.parser(); /* might want to recover arguments or thrown exceptions */ if (parser.listLength > 0 && parser.astLengthPtr > 0) { // awaiting interface type references /* has consumed the arguments - listed elements must be thrown exceptions */ if (methodDeclaration.sourceEnd == parser.rParenPos) { // protection for bugs 15142 int length = parser.astLengthStack[parser.astLengthPtr]; int astPtr = parser.astPtr - length; boolean canConsume = astPtr >= 0; if (canConsume) { if ((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) { canConsume = false; } for (int i = 1, max = length + 1; i < max; i++) { if (!(parser.astStack[astPtr + i] instanceof TypeReference)) { canConsume = false; } } } if (canConsume) { parser.consumeMethodHeaderThrowsClause(); // will reset typeListLength to zero // thus this check will only be performed on first errorCheck after void foo() throws X, // Y, } else { parser.listLength = 0; } } else { /* has not consumed arguments yet, listed elements must be arguments */ if (parser.currentToken == TokenNameLPAREN || parser.currentToken == TokenNameSEMICOLON) { /* if currentToken is parenthesis this last argument is a method/field signature */ parser.astLengthStack[parser.astLengthPtr]--; parser.astPtr--; parser.listLength--; parser.currentToken = 0; } int argLength = parser.astLengthStack[parser.astLengthPtr]; int argStart = parser.astPtr - argLength + 1; boolean needUpdateRParenPos = parser.rParenPos < parser.lParenPos; // 12387 : rParenPos will be used // remove unfinished annotation nodes MemberValuePair[] memberValuePairs = null; while (argLength > 0 && parser.astStack[parser.astPtr] instanceof MemberValuePair) { System.arraycopy( parser.astStack, argStart, memberValuePairs = new MemberValuePair[argLength], 0, argLength); parser.astLengthPtr--; parser.astPtr -= argLength; argLength = parser.astLengthStack[parser.astLengthPtr]; argStart = parser.astPtr - argLength + 1; needUpdateRParenPos = true; } // to compute bodyStart, and thus used to set next checkpoint. int count; for (count = 0; count < argLength; count++) { ASTNode aNode = parser.astStack[argStart + count]; if (aNode instanceof Argument) { Argument argument = (Argument) aNode; /* cannot be an argument if non final */ char[][] argTypeName = argument.type.getTypeName(); if ((argument.modifiers & ~ClassFileConstants.AccFinal) != 0 || (argTypeName.length == 1 && CharOperation.equals(argTypeName[0], TypeBinding.VOID.sourceName()))) { parser.astLengthStack[parser.astLengthPtr] = count; parser.astPtr = argStart + count - 1; parser.listLength = count; parser.currentToken = 0; break; } if (needUpdateRParenPos) parser.rParenPos = argument.sourceEnd + 1; } else { parser.astLengthStack[parser.astLengthPtr] = count; parser.astPtr = argStart + count - 1; parser.listLength = count; parser.currentToken = 0; break; } } if (parser.listLength > 0 && parser.astLengthPtr > 0) { // protection for bugs 15142 int length = parser.astLengthStack[parser.astLengthPtr]; int astPtr = parser.astPtr - length; boolean canConsume = astPtr >= 0; if (canConsume) { if ((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) { canConsume = false; } for (int i = 1, max = length + 1; i < max; i++) { if (!(parser.astStack[astPtr + i] instanceof Argument)) { canConsume = false; } } } if (canConsume) { parser.consumeMethodHeaderRightParen(); /* fix-up positions, given they were updated against rParenPos, which did not get set */ if (parser.currentElement == this) { // parameter addition might have added an awaiting (no return type) // method - see 1FVXQZ4 */ methodDeclaration.sourceEnd = methodDeclaration.arguments[methodDeclaration.arguments.length - 1].sourceEnd; methodDeclaration.bodyStart = methodDeclaration.sourceEnd + 1; parser.lastCheckPoint = methodDeclaration.bodyStart; } } } if (memberValuePairs != null) { System.arraycopy( memberValuePairs, 0, parser.astStack, parser.astPtr + 1, memberValuePairs.length); parser.astPtr += memberValuePairs.length; parser.astLengthStack[++parser.astLengthPtr] = memberValuePairs.length; } } } } }