/*******************************************************************************
* 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();
}
}