/*******************************************************************************
* Copyright (c) 2000, 2009 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.che.ide.ext.java.jdt.internal.compiler.parser;
import org.eclipse.che.ide.ext.java.jdt.core.compiler.CharOperation;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ClassFileConstants;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.Annotation;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.Argument;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.Block;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.Statement;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.che.ide.ext.java.jdt.internal.compiler.util.Util;
import java.util.HashSet;
import java.util.Set;
/** Internal method structure for parsing recovery */
public class RecoveredMethod extends RecoveredElement implements TerminalTokens {
public AbstractMethodDeclaration methodDeclaration;
public RecoveredAnnotation[] annotations;
public int annotationCount;
public int modifiers;
public int modifiersStart;
public RecoveredType[] localTypes;
public int localTypeCount;
public RecoveredBlock methodBody;
public boolean discardBody = true;
int pendingModifiers;
int pendingModifersSourceStart = -1;
RecoveredAnnotation[] pendingAnnotations;
int pendingAnnotationCount;
public RecoveredMethod(AbstractMethodDeclaration methodDeclaration, RecoveredElement parent, int bracketBalance,
Parser parser) {
super(parent, bracketBalance, parser);
this.methodDeclaration = methodDeclaration;
this.foundOpeningBrace = !bodyStartsAtHeaderEnd();
if (this.foundOpeningBrace) {
this.bracketBalance++;
}
}
/* Record a nested block declaration */
public RecoveredElement add(Block nestedBlockDeclaration, int 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 (this.methodDeclaration.declarationSourceEnd > 0
&& nestedBlockDeclaration.sourceStart > this.methodDeclaration.declarationSourceEnd) {
resetPendingModifiers();
if (this.parent == null) {
return this; // ignore
} else {
return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
}
}
/* consider that if the opening brace was not found, it is there */
if (!this.foundOpeningBrace) {
this.foundOpeningBrace = true;
this.bracketBalance++;
}
this.methodBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue);
if (nestedBlockDeclaration.sourceEnd == 0)
return this.methodBody;
return this;
}
/* Record a field declaration */
public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
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(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 (this.methodDeclaration.declarationSourceEnd > 0
&& fieldDeclaration.declarationSourceStart > this.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 (!this.foundOpeningBrace) {
this.foundOpeningBrace = true;
this.bracketBalance++;
}
// still inside method, treat as local variable
return this; // ignore
}
/*
* Record a local declaration - regular method should have been created a block body
*/
public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
resetPendingModifiers();
/* local variables inside method can only be final and non void */
/*
* char[][] localTypeName; if ((localDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final ||
* (localDeclaration.type == null) // initializer || ((localTypeName = localDeclaration.type.getTypeName()).length == 1 //
* non void && CharOperation.equals(localTypeName[0], VoidBinding.sourceName()))){ if (this.parent == null){ return this; //
* ignore } else { this.updateSourceEndIfNecessary (this.previousAvailableLineEnd(localDeclaration.declarationSourceStart -
* 1)); return this.parent.add(localDeclaration, bracketBalance); } }
*/
/*
* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type
*/
if (this.methodDeclaration.declarationSourceEnd != 0
&& localDeclaration.declarationSourceStart > this.methodDeclaration.declarationSourceEnd) {
if (this.parent == null) {
return this; // ignore
} else {
return this.parent.add(localDeclaration, bracketBalanceValue);
}
}
if (this.methodBody == null) {
Block block = new Block(0);
block.sourceStart = this.methodDeclaration.bodyStart;
RecoveredElement currentBlock = this.add(block, 1);
if (this.bracketBalance > 0) {
for (int i = 0; i < this.bracketBalance - 1; i++) {
currentBlock = currentBlock.add(new Block(0), 1);
}
this.bracketBalance = 1;
}
return currentBlock.add(localDeclaration, bracketBalanceValue);
}
return this.methodBody.add(localDeclaration, bracketBalanceValue, true);
}
/* Record a statement - regular method should have been created a block body */
public RecoveredElement add(Statement statement, int bracketBalanceValue) {
resetPendingModifiers();
/*
* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type
*/
if (this.methodDeclaration.declarationSourceEnd != 0
&& statement.sourceStart > this.methodDeclaration.declarationSourceEnd) {
if (this.parent == null) {
return this; // ignore
} else {
return this.parent.add(statement, bracketBalanceValue);
}
}
if (this.methodBody == null) {
Block block = new Block(0);
block.sourceStart = this.methodDeclaration.bodyStart;
RecoveredElement currentBlock = this.add(block, 1);
if (this.bracketBalance > 0) {
for (int i = 0; i < this.bracketBalance - 1; i++) {
currentBlock = currentBlock.add(new Block(0), 1);
}
this.bracketBalance = 1;
}
return currentBlock.add(statement, bracketBalanceValue);
}
return this.methodBody.add(statement, bracketBalanceValue, true);
}
public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
/*
* do not consider a type starting passed the type end (if set) it must be belonging to an enclosing type
*/
if (this.methodDeclaration.declarationSourceEnd != 0
&& typeDeclaration.declarationSourceStart > this.methodDeclaration.declarationSourceEnd) {
if (this.parent == null) {
return this; // ignore
}
return this.parent.add(typeDeclaration, bracketBalanceValue);
}
if ((typeDeclaration.bits & ASTNode.IsLocalType) != 0 || parser().methodRecoveryActivated
|| parser().statementRecoveryActivated) {
if (this.methodBody == null) {
Block block = new Block(0);
block.sourceStart = this.methodDeclaration.bodyStart;
this.add(block, 1);
}
this.methodBody.attachPendingModifiers(this.pendingAnnotations, this.pendingAnnotationCount,
this.pendingModifiers, this.pendingModifersSourceStart);
resetPendingModifiers();
return this.methodBody.add(typeDeclaration, bracketBalanceValue, true);
}
switch (TypeDeclaration.kind(typeDeclaration.modifiers)) {
case TypeDeclaration.INTERFACE_DECL:
case TypeDeclaration.ANNOTATION_TYPE_DECL:
resetPendingModifiers();
this.updateSourceEndIfNecessary(previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));
if (this.parent == null) {
return this; // ignore
}
// close the constructor
return this.parent.add(typeDeclaration, bracketBalanceValue);
}
if (this.localTypes == null) {
this.localTypes = new RecoveredType[5];
this.localTypeCount = 0;
} else {
if (this.localTypeCount == this.localTypes.length) {
System.arraycopy(this.localTypes, 0, (this.localTypes = new RecoveredType[2 * this.localTypeCount]), 0,
this.localTypeCount);
}
}
RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
this.localTypes[this.localTypeCount++] = element;
if (this.pendingAnnotationCount > 0) {
element.attach(this.pendingAnnotations, this.pendingAnnotationCount, this.pendingModifiers,
this.pendingModifersSourceStart);
}
resetPendingModifiers();
/* consider that if the opening brace was not found, it is there */
if (!this.foundOpeningBrace) {
this.foundOpeningBrace = true;
this.bracketBalance++;
}
return element;
}
public boolean bodyStartsAtHeaderEnd() {
return this.methodDeclaration.bodyStart == this.methodDeclaration.sourceEnd + 1;
}
/* Answer the associated parsed structure */
public ASTNode parseTree() {
return this.methodDeclaration;
}
public void resetPendingModifiers() {
this.pendingAnnotations = null;
this.pendingAnnotationCount = 0;
this.pendingModifiers = 0;
this.pendingModifersSourceStart = -1;
}
/* Answer the very source end of the corresponding parse node */
public int sourceEnd() {
return this.methodDeclaration.declarationSourceEnd;
}
public String toString(int tab) {
StringBuffer result = new StringBuffer(tabString(tab));
result.append("Recovered method:\n"); //$NON-NLS-1$
this.methodDeclaration.print(tab + 1, result);
if (this.annotations != null) {
for (int i = 0; i < this.annotationCount; i++) {
result.append("\n"); //$NON-NLS-1$
result.append(this.annotations[i].toString(tab + 1));
}
}
if (this.localTypes != null) {
for (int i = 0; i < this.localTypeCount; i++) {
result.append("\n"); //$NON-NLS-1$
result.append(this.localTypes[i].toString(tab + 1));
}
}
if (this.methodBody != null) {
result.append("\n"); //$NON-NLS-1$
result.append(this.methodBody.toString(tab + 1));
}
return result.toString();
}
/* Update the bodyStart of the corresponding parse node */
public void updateBodyStart(int bodyStart) {
this.foundOpeningBrace = true;
this.methodDeclaration.bodyStart = bodyStart;
}
public AbstractMethodDeclaration updatedMethodDeclaration(int depth, Set knownTypes) {
/* update annotations */
if (this.modifiers != 0) {
this.methodDeclaration.modifiers |= this.modifiers;
if (this.modifiersStart < this.methodDeclaration.declarationSourceStart) {
this.methodDeclaration.declarationSourceStart = this.modifiersStart;
}
}
/* update annotations */
if (this.annotationCount > 0) {
int existingCount = this.methodDeclaration.annotations == null ? 0 : this.methodDeclaration.annotations.length;
Annotation[] annotationReferences = new Annotation[existingCount + this.annotationCount];
if (existingCount > 0) {
System.arraycopy(this.methodDeclaration.annotations, 0, annotationReferences, this.annotationCount,
existingCount);
}
for (int i = 0; i < this.annotationCount; i++) {
annotationReferences[i] = this.annotations[i].updatedAnnotationReference();
}
this.methodDeclaration.annotations = annotationReferences;
int start = this.annotations[0].annotation.sourceStart;
if (start < this.methodDeclaration.declarationSourceStart) {
this.methodDeclaration.declarationSourceStart = start;
}
}
if (this.methodBody != null) {
Block block = this.methodBody.updatedBlock(depth, knownTypes);
if (block != null) {
this.methodDeclaration.statements = block.statements;
if (this.methodDeclaration.declarationSourceEnd == 0) {
this.methodDeclaration.declarationSourceEnd = block.sourceEnd;
this.methodDeclaration.bodyEnd = block.sourceEnd;
}
/*
* first statement might be an explict constructor call destinated to a special slot
*/
if (this.methodDeclaration.isConstructor()) {
ConstructorDeclaration constructor = (ConstructorDeclaration)this.methodDeclaration;
if (this.methodDeclaration.statements != null
&& this.methodDeclaration.statements[0] instanceof ExplicitConstructorCall) {
constructor.constructorCall = (ExplicitConstructorCall)this.methodDeclaration.statements[0];
int length = this.methodDeclaration.statements.length;
System.arraycopy(this.methodDeclaration.statements, 1, (this.methodDeclaration.statements =
new Statement[length - 1]), 0, length - 1);
}
if (constructor.constructorCall == null) { // add implicit constructor call
constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
}
}
}
} else {
if (this.methodDeclaration.declarationSourceEnd == 0) {
if (this.methodDeclaration.sourceEnd + 1 == this.methodDeclaration.bodyStart) {
// right brace is missing
this.methodDeclaration.declarationSourceEnd = this.methodDeclaration.sourceEnd;
this.methodDeclaration.bodyStart = this.methodDeclaration.sourceEnd;
this.methodDeclaration.bodyEnd = this.methodDeclaration.sourceEnd;
} else {
this.methodDeclaration.declarationSourceEnd = this.methodDeclaration.bodyStart;
this.methodDeclaration.bodyEnd = this.methodDeclaration.bodyStart;
}
}
}
if (this.localTypeCount > 0)
this.methodDeclaration.bits |= ASTNode.HasLocalType;
return this.methodDeclaration;
}
/*
* 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 (bodyStartsAtHeaderEnd() && this.parent != null) {
Parser parser = 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 (this.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 */
this.methodDeclaration.sourceEnd =
this.methodDeclaration.arguments[this.methodDeclaration.arguments.length - 1].sourceEnd;
this.methodDeclaration.bodyStart = this.methodDeclaration.sourceEnd + 1;
parser.lastCheckPoint = this.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;
}
}
}
}
}
public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd) {
if (this.methodDeclaration.isAnnotationMethod()) {
this.updateSourceEndIfNecessary(braceStart, braceEnd);
if (!this.foundOpeningBrace && this.parent != null) {
return this.parent.updateOnClosingBrace(braceStart, braceEnd);
}
return this;
}
if (this.parent != null && this.parent instanceof RecoveredType) {
int mods = ((RecoveredType)this.parent).typeDeclaration.modifiers;
if (TypeDeclaration.kind(mods) == TypeDeclaration.INTERFACE_DECL) {
if (!this.foundOpeningBrace) {
this.updateSourceEndIfNecessary(braceStart - 1, braceStart - 1);
return this.parent.updateOnClosingBrace(braceStart, braceEnd);
}
}
}
return super.updateOnClosingBrace(braceStart, braceEnd);
}
/*
* An opening brace got consumed, might be the expected opening one of the current element, in which case the bodyStart is
* updated.
*/
public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd) {
/* in case the opening brace is close enough to the signature */
if (this.bracketBalance == 0) {
/*
* if (parser.scanner.searchLineNumber(methodDeclaration.sourceEnd) != parser.scanner.searchLineNumber(braceEnd)){
*/
switch (parser().lastIgnoredToken) {
case -1:
case TokenNamethrows:
break;
default:
this.foundOpeningBrace = true;
this.bracketBalance = 1; // pretend the brace was already there
}
}
return super.updateOnOpeningBrace(braceStart, braceEnd);
}
public void updateParseTree() {
updatedMethodDeclaration(0, new HashSet());
}
/* Update the declarationSourceEnd of the corresponding parse node */
public void updateSourceEndIfNecessary(int braceStart, int braceEnd) {
if (this.methodDeclaration.declarationSourceEnd == 0) {
if (parser().rBraceSuccessorStart >= braceEnd) {
this.methodDeclaration.declarationSourceEnd = parser().rBraceEnd;
this.methodDeclaration.bodyEnd = parser().rBraceStart;
} else {
this.methodDeclaration.declarationSourceEnd = braceEnd;
this.methodDeclaration.bodyEnd = braceStart - 1;
}
}
}
public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengthPtr, int annotationStart,
int bracketBalanceValue) {
if (this.pendingAnnotations == null) {
this.pendingAnnotations = new RecoveredAnnotation[5];
this.pendingAnnotationCount = 0;
} else {
if (this.pendingAnnotationCount == this.pendingAnnotations.length) {
System.arraycopy(this.pendingAnnotations, 0, (this.pendingAnnotations =
new RecoveredAnnotation[2 * this.pendingAnnotationCount]), 0, this.pendingAnnotationCount);
}
}
RecoveredAnnotation element =
new RecoveredAnnotation(identifierPtr, identifierLengthPtr, annotationStart, this, bracketBalanceValue);
this.pendingAnnotations[this.pendingAnnotationCount++] = element;
return element;
}
public void addModifier(int flag, int modifiersSourceStart) {
this.pendingModifiers |= flag;
if (this.pendingModifersSourceStart < 0) {
this.pendingModifersSourceStart = modifiersSourceStart;
}
}
void attach(TypeParameter[] parameters, int startPos) {
if (this.methodDeclaration.modifiers != ClassFileConstants.AccDefault)
return;
int lastParameterEnd = parameters[parameters.length - 1].sourceEnd;
Parser parser = parser();
Scanner scanner = parser.scanner;
if (Util.getLineNumber(this.methodDeclaration.declarationSourceStart, scanner.lineEnds, 0, scanner.linePtr) != Util
.getLineNumber(lastParameterEnd, scanner.lineEnds, 0, scanner.linePtr))
return;
if (parser.modifiersSourceStart > lastParameterEnd
&& parser.modifiersSourceStart < this.methodDeclaration.declarationSourceStart)
return;
if (this.methodDeclaration instanceof MethodDeclaration) {
((MethodDeclaration)this.methodDeclaration).typeParameters = parameters;
this.methodDeclaration.declarationSourceStart = startPos;
} else if (this.methodDeclaration instanceof ConstructorDeclaration) {
((ConstructorDeclaration)this.methodDeclaration).typeParameters = parameters;
this.methodDeclaration.declarationSourceStart = startPos;
}
}
public void attach(RecoveredAnnotation[] annots, int annotCount, int mods, int modsSourceStart) {
if (annotCount > 0) {
Annotation[] existingAnnotations = this.methodDeclaration.annotations;
if (existingAnnotations != null) {
this.annotations = new RecoveredAnnotation[annotCount];
this.annotationCount = 0;
next:
for (int i = 0; i < annotCount; i++) {
for (int j = 0; j < existingAnnotations.length; j++) {
if (annots[i].annotation == existingAnnotations[j])
continue next;
}
this.annotations[this.annotationCount++] = annots[i];
}
} else {
this.annotations = annots;
this.annotationCount = annotCount;
}
}
if (mods != 0) {
this.modifiers = mods;
this.modifiersStart = modsSourceStart;
}
}
}