/******************************************************************************* * Copyright (c) 2008 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.compiler.parser; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; public class RecoveredAnnotation extends RecoveredElement { public static final int MARKER= 0; public static final int NORMAL= 1; public static final int SINGLE_MEMBER= 2; private int kind; private int identifierPtr; private int identifierLengthPtr; private int sourceStart; public boolean hasPendingMemberValueName; public int memberValuPairEqualEnd= -1; public Annotation annotation; public RecoveredAnnotation(int identifierPtr, int identifierLengthPtr, int sourceStart, RecoveredElement parent, int bracketBalance) { super(parent, bracketBalance); this.kind= MARKER; this.identifierPtr= identifierPtr; this.identifierLengthPtr= identifierLengthPtr; this.sourceStart= sourceStart; } public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { if (this.annotation == null && (typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) { // ignore anonymous type in annotations when annotation isn't fully recovered return this; } return super.add(typeDeclaration, bracketBalanceValue); } public RecoveredElement addAnnotationName(int identPtr, int identLengthPtr, int annotationStart, int bracketBalanceValue) { RecoveredAnnotation element= new RecoveredAnnotation(identPtr, identLengthPtr, annotationStart, this, bracketBalanceValue); return element; } public RecoveredElement addAnnotation(Annotation annot, int index) { this.annotation= annot; if (this.parent != null) return this.parent; return this; } public void updateFromParserState() { Parser parser= parser(); if (this.annotation == null && this.identifierPtr <= parser.identifierPtr) { Annotation annot= null; boolean needUpdateRParenPos= false; MemberValuePair pendingMemberValueName= null; if (this.hasPendingMemberValueName && this.identifierPtr < parser.identifierPtr) { char[] memberValueName= parser.identifierStack[this.identifierPtr + 1]; long pos= parser.identifierPositionStack[this.identifierPtr + 1]; int start= (int)(pos >>> 32); int end= (int)pos; int valueEnd= this.memberValuPairEqualEnd > -1 ? this.memberValuPairEqualEnd : end; SingleNameReference fakeExpression= new SingleNameReference(RecoveryScanner.FAKE_IDENTIFIER, (((long)valueEnd + 1) << 32) + (valueEnd)); pendingMemberValueName= new MemberValuePair(memberValueName, start, end, fakeExpression); } parser.identifierPtr= this.identifierPtr; parser.identifierLengthPtr= this.identifierLengthPtr; TypeReference typeReference= parser.getAnnotationType(); switch (this.kind) { case NORMAL: if (parser.astPtr > -1 && parser.astStack[parser.astPtr] instanceof MemberValuePair) { MemberValuePair[] memberValuePairs= null; int argLength= parser.astLengthStack[parser.astLengthPtr]; int argStart= parser.astPtr - argLength + 1; if (argLength > 0) { int annotationEnd; if (pendingMemberValueName != null) { memberValuePairs= new MemberValuePair[argLength + 1]; System.arraycopy(parser.astStack, argStart, memberValuePairs, 0, argLength); parser.astLengthPtr--; parser.astPtr-= argLength; memberValuePairs[argLength]= pendingMemberValueName; annotationEnd= pendingMemberValueName.sourceEnd; } else { memberValuePairs= new MemberValuePair[argLength]; System.arraycopy(parser.astStack, argStart, memberValuePairs, 0, argLength); parser.astLengthPtr--; parser.astPtr-= argLength; MemberValuePair lastMemberValuePair= memberValuePairs[memberValuePairs.length - 1]; annotationEnd= lastMemberValuePair.value != null ? lastMemberValuePair.value instanceof Annotation ? ((Annotation)lastMemberValuePair.value).declarationSourceEnd : lastMemberValuePair.value.sourceEnd : lastMemberValuePair.sourceEnd; } NormalAnnotation normalAnnotation= new NormalAnnotation(typeReference, this.sourceStart); normalAnnotation.memberValuePairs= memberValuePairs; normalAnnotation.declarationSourceEnd= annotationEnd; normalAnnotation.bits|= ASTNode.IsRecovered; annot= normalAnnotation; needUpdateRParenPos= true; } } break; case SINGLE_MEMBER: if (parser.expressionPtr > -1) { Expression memberValue= parser.expressionStack[parser.expressionPtr--]; SingleMemberAnnotation singleMemberAnnotation= new SingleMemberAnnotation(typeReference, this.sourceStart); singleMemberAnnotation.memberValue= memberValue; singleMemberAnnotation.declarationSourceEnd= memberValue.sourceEnd; singleMemberAnnotation.bits|= ASTNode.IsRecovered; annot= singleMemberAnnotation; needUpdateRParenPos= true; } break; } if (!needUpdateRParenPos) { if (pendingMemberValueName != null) { NormalAnnotation normalAnnotation= new NormalAnnotation(typeReference, this.sourceStart); normalAnnotation.memberValuePairs= new MemberValuePair[] { pendingMemberValueName }; normalAnnotation.declarationSourceEnd= pendingMemberValueName.value.sourceEnd; normalAnnotation.bits|= ASTNode.IsRecovered; annot= normalAnnotation; } else { MarkerAnnotation markerAnnotation= new MarkerAnnotation(typeReference, this.sourceStart); markerAnnotation.declarationSourceEnd= markerAnnotation.sourceEnd; markerAnnotation.bits|= ASTNode.IsRecovered; annot= markerAnnotation; } } parser.currentElement= addAnnotation(annot, this.identifierPtr); parser.annotationRecoveryCheckPoint(annot.sourceStart, annot.declarationSourceEnd); if (this.parent != null) { this.parent.updateFromParserState(); } } } public ASTNode parseTree() { return this.annotation; } public void resetPendingModifiers() { if (this.parent != null) this.parent.resetPendingModifiers(); } public void setKind(int kind) { this.kind= kind; } public int sourceEnd() { if (this.annotation == null) { Parser parser= parser(); if (this.identifierPtr < parser.identifierPositionStack.length) { return (int)parser.identifierPositionStack[this.identifierPtr]; } else { return this.sourceStart; } } return this.annotation.declarationSourceEnd; } public String toString(int tab) { if (this.annotation != null) { return tabString(tab) + "Recovered annotation:\n" + this.annotation.print(tab + 1, new StringBuffer(10)); //$NON-NLS-1$ } else { return tabString(tab) + "Recovered annotation: identiferPtr=" + this.identifierPtr + " identiferlengthPtr=" + this.identifierLengthPtr + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } public Annotation updatedAnnotationReference() { return this.annotation; } public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd) { if (this.bracketBalance > 0) { // was an member value array initializer this.bracketBalance--; return this; } if (this.parent != null) { return this.parent.updateOnClosingBrace(braceStart, braceEnd); } return this; } public void updateParseTree() { updatedAnnotationReference(); } }