}
if (element == null) return element;
/* add initial block */
Block block = new Block(0);
int lastStart = this.blockStarts[0];
block.sourceStart = lastStart;
element = element.add(block, 1);
int blockIndex = 1; // ignore first block start, since manually rebuilt here
ASTNode node = null, lastNode = null;
for (int i = 0; i <= this.astPtr; i++, lastNode = node) {
node = this.astStack[i];
if(node instanceof ForeachStatement && ((ForeachStatement)node).action == null) {
node = ((ForeachStatement)node).elementVariable;
}
/* check for intermediate block creation, so recovery can properly close them afterwards */
int nodeStart = node.sourceStart;
for (int j = blockIndex; j <= this.realBlockPtr; j++){
if (this.blockStarts[j] >= 0) {
if (this.blockStarts[j] > nodeStart){
blockIndex = j; // shift the index to the new block
break;
}
if (this.blockStarts[j] != lastStart){ // avoid multiple block if at same position
block = new Block(0, lastNode instanceof LambdaExpression);
block.sourceStart = lastStart = this.blockStarts[j];
element = element.add(block, 1);
}
} else {
if (-this.blockStarts[j] > nodeStart){
blockIndex = j; // shift the index to the new block
break;
}
block = new Block(0);
block.sourceStart = lastStart = -this.blockStarts[j];
element = element.add(block, 1);
}
blockIndex = j+1; // shift the index to the new block
}
if (node instanceof LocalDeclaration){
LocalDeclaration local = (LocalDeclaration) node;
if (local.declarationSourceEnd == 0){
element = element.add(local, 0);
if (local.initialization == null){
this.lastCheckPoint = local.sourceEnd + 1;
} else {
this.lastCheckPoint = local.initialization.sourceEnd + 1;
}
} else {
element = element.add(local, 0);
this.lastCheckPoint = local.declarationSourceEnd + 1;
}
continue;
}
if (node instanceof AbstractMethodDeclaration){
AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
if (method.declarationSourceEnd == 0){
element = element.add(method, 0);
this.lastCheckPoint = method.bodyStart;
} else {
element = element.add(method, 0);
this.lastCheckPoint = method.declarationSourceEnd + 1;
}
continue;
}
if (node instanceof Initializer){
Initializer initializer = (Initializer) node;
if (initializer.declarationSourceEnd == 0){
element = element.add(initializer, 1);
this.lastCheckPoint = initializer.sourceStart;
} else {
element = element.add(initializer, 0);
this.lastCheckPoint = initializer.declarationSourceEnd + 1;
}
continue;
}
if (node instanceof FieldDeclaration){
FieldDeclaration field = (FieldDeclaration) node;
if (field.declarationSourceEnd == 0){
element = element.add(field, 0);
if (field.initialization == null){
this.lastCheckPoint = field.sourceEnd + 1;
} else {
this.lastCheckPoint = field.initialization.sourceEnd + 1;
}
} else {
element = element.add(field, 0);
this.lastCheckPoint = field.declarationSourceEnd + 1;
}
continue;
}
if (node instanceof TypeDeclaration){
TypeDeclaration type = (TypeDeclaration) node;
if (type.declarationSourceEnd == 0){
element = element.add(type, 0);
this.lastCheckPoint = type.bodyStart;
} else {
element = element.add(type, 0);
this.lastCheckPoint = type.declarationSourceEnd + 1;
}
continue;
}
if (this.assistNode != null && node instanceof Statement) {
Statement stmt = (Statement) node;
if (!(stmt instanceof Expression) || ((Expression) stmt).statementExpression()) {
if (this.assistNode.sourceStart >= stmt.sourceStart && this.assistNode.sourceEnd <= stmt.sourceEnd) {
element.add(stmt, 0);
this.lastCheckPoint = stmt.sourceEnd + 1;
this.isOrphanCompletionNode = false;
}
}
continue;
}
if (node instanceof ImportReference){
ImportReference importRef = (ImportReference) node;
element = element.add(importRef, 0);
this.lastCheckPoint = importRef.declarationSourceEnd + 1;
}
}
if (this.currentToken == TokenNameRBRACE && !isIndirectlyInsideLambdaExpression()) {
this.currentToken = 0; // closing brace has already been taken care of
}
/* might need some extra block (after the last reduced node) */
/* For block bodied lambdas we should create a block even though the lambda header appears before it, so elements from within don't get misattributed. */
int pos = this.assistNode == null ? this.lastCheckPoint : this.assistNode.sourceStart;
boolean createLambdaBlock = lastNode instanceof LambdaExpression && ((LambdaExpression) node).body() instanceof Block;
for (int j = blockIndex; j <= this.realBlockPtr; j++){
if (this.blockStarts[j] >= 0) {
if ((this.blockStarts[j] < pos || createLambdaBlock) && (this.blockStarts[j] != lastStart)){ // avoid multiple block if at same position
block = new Block(0, createLambdaBlock);
block.sourceStart = lastStart = this.blockStarts[j];
element = element.add(block, 1);
createLambdaBlock = false;
}
} else {
if ((this.blockStarts[j] < pos)){ // avoid multiple block if at same position
block = new Block(0);
block.sourceStart = lastStart = -this.blockStarts[j];
element = element.add(block, 1);
}
}
}