org.eclipse.jdt.internal.compiler.parser.RecoveredInitializer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ecj Show documentation
Show all versions of ecj Show documentation
Eclipse Compiler for Java(TM)
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.parser;
import java.util.Set;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
public class RecoveredInitializer extends RecoveredField implements TerminalTokens {
public RecoveredType[] localTypes;
public int localTypeCount;
public RecoveredBlock initializerBody;
int pendingModifiers;
int pendingModifersSourceStart = -1;
RecoveredAnnotation[] pendingAnnotations;
int pendingAnnotationCount;
public RecoveredInitializer(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance){
this(fieldDeclaration, parent, bracketBalance, null);
}
public RecoveredInitializer(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){
super(fieldDeclaration, parent, bracketBalance, parser);
this.foundOpeningBrace = true;
}
/*
* Record a nested block declaration
*/
@Override
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.fieldDeclaration.declarationSourceEnd > 0
&& nestedBlockDeclaration.sourceStart > this.fieldDeclaration.declarationSourceEnd){
resetPendingModifiers();
if (this.parent == null) return this; // ignore
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++;
}
if (this.initializerBody == null) {
return this.initializerBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue);
}
this.initializerBody.blockDeclaration.sourceEnd = 0; /* needed to allow adding more elements to the existing initializerBody */
if (nestedBlockDeclaration.sourceEnd == 0) return this.initializerBody;
return this.initializerBody.add(nestedBlockDeclaration, bracketBalanceValue, true);
}
/*
* Record a field declaration (act like inside method body)
*/
@Override
public RecoveredElement add(FieldDeclaration newFieldDeclaration, int bracketBalanceValue) {
resetPendingModifiers();
/* local variables inside initializer can only be final and non void */
char[][] fieldTypeName;
if ((newFieldDeclaration.modifiers & ~ClassFileConstants.AccFinal) != 0 /* local var can only be final */
|| (newFieldDeclaration.type == null) // initializer
|| ((fieldTypeName = newFieldDeclaration.type.getTypeName()).length == 1 // non void
&& CharOperation.equals(fieldTypeName[0], TypeBinding.VOID.sourceName()))){
if (this.parent == null) return this; // ignore
this.updateSourceEndIfNecessary(previousAvailableLineEnd(newFieldDeclaration.declarationSourceStart - 1));
return this.parent.add(newFieldDeclaration, 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.fieldDeclaration.declarationSourceEnd > 0
&& newFieldDeclaration.declarationSourceStart > this.fieldDeclaration.declarationSourceEnd){
if (this.parent == null) return this; // ignore
return this.parent.add(newFieldDeclaration, bracketBalanceValue);
}
// still inside initializer, treat as local variable
return this; // ignore
}
/*
* Record a local declaration - regular method should have been created a block body
*/
@Override
public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
/* do not consider a type starting passed the type end (if set)
it must be belonging to an enclosing type */
if (this.fieldDeclaration.declarationSourceEnd != 0
&& localDeclaration.declarationSourceStart > this.fieldDeclaration.declarationSourceEnd){
resetPendingModifiers();
if (this.parent == null) return this; // ignore
return this.parent.add(localDeclaration, bracketBalanceValue);
}
/* method body should have been created */
if (this.initializerBody == null) {
Block block = new Block(0);
block.sourceStart = ((Initializer)this.fieldDeclaration).sourceStart;
RecoveredElement element = this.add(block, 1);
if (this.bracketBalance > 0){
for (int i = 0; i < this.bracketBalance - 1; i++){
element = element.add(new Block(0), 1);
}
this.bracketBalance = 1;
}
return element.add(localDeclaration, bracketBalanceValue);
}
this.initializerBody.attachPendingModifiers(
this.pendingAnnotations,
this.pendingAnnotationCount,
this.pendingModifiers,
this.pendingModifersSourceStart);
resetPendingModifiers();
return this.initializerBody.add(localDeclaration, bracketBalanceValue, true);
}
/*
* Record a statement - regular method should have been created a block body
*/
@Override
public RecoveredElement add(Statement statement, int bracketBalanceValue) {
/* do not consider a statement starting passed the initializer end (if set)
it must be belonging to an enclosing type */
if (this.fieldDeclaration.declarationSourceEnd != 0
&& statement.sourceStart > this.fieldDeclaration.declarationSourceEnd){
resetPendingModifiers();
if (this.parent == null) return this; // ignore
return this.parent.add(statement, bracketBalanceValue);
}
/* initializer body should have been created */
Block block = new Block(0);
block.sourceStart = ((Initializer)this.fieldDeclaration).sourceStart;
RecoveredElement element = this.add(block, 1);
if (this.initializerBody != null) {
this.initializerBody.attachPendingModifiers(
this.pendingAnnotations,
this.pendingAnnotationCount,
this.pendingModifiers,
this.pendingModifersSourceStart);
}
resetPendingModifiers();
return element.add(statement, bracketBalanceValue);
}
@Override
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.fieldDeclaration.declarationSourceEnd != 0
&& typeDeclaration.declarationSourceStart > this.fieldDeclaration.declarationSourceEnd){
resetPendingModifiers();
if (this.parent == null) return this; // ignore
return this.parent.add(typeDeclaration, bracketBalanceValue);
}
if ((typeDeclaration.bits & ASTNode.IsLocalType) != 0 || parser().methodRecoveryActivated || parser().statementRecoveryActivated){
/* method body should have been created */
Block block = new Block(0);
block.sourceStart = ((Initializer)this.fieldDeclaration).sourceStart;
RecoveredElement element = this.add(block, 1);
if (this.initializerBody != null) {
this.initializerBody.attachPendingModifiers(
this.pendingAnnotations,
this.pendingAnnotationCount,
this.pendingModifiers,
this.pendingModifersSourceStart);
}
resetPendingModifiers();
return element.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;
}
@Override
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;
}
@Override
public void addModifier(int flag, int modifiersSourceStart) {
this.pendingModifiers |= flag;
if (this.pendingModifersSourceStart < 0) {
this.pendingModifersSourceStart = modifiersSourceStart;
}
}
@Override
public void resetPendingModifiers() {
this.pendingAnnotations = null;
this.pendingAnnotationCount = 0;
this.pendingModifiers = 0;
this.pendingModifersSourceStart = -1;
}
@Override
public String toString(int tab) {
StringBuffer result = new StringBuffer(tabString(tab));
result.append("Recovered initializer:\n"); //$NON-NLS-1$
this.fieldDeclaration.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.initializerBody != null) {
result.append("\n"); //$NON-NLS-1$
result.append(this.initializerBody.toString(tab + 1));
}
return result.toString();
}
@Override
public FieldDeclaration updatedFieldDeclaration(int depth, Set knownTypes){
if (this.initializerBody != null){
Block block = this.initializerBody.updatedBlock(depth, knownTypes);
if (block != null){
Initializer initializer = (Initializer) this.fieldDeclaration;
initializer.block = block;
if (initializer.declarationSourceEnd == 0) {
initializer.declarationSourceEnd = block.sourceEnd;
initializer.bodyEnd = block.sourceEnd;
}
}
if (this.localTypeCount > 0) this.fieldDeclaration.bits |= ASTNode.HasLocalType;
}
if (this.fieldDeclaration.sourceEnd == 0){
this.fieldDeclaration.sourceEnd = this.fieldDeclaration.declarationSourceEnd;
}
return this.fieldDeclaration;
}
/*
* A closing brace got consumed, might have closed the current element,
* in which case both the currentElement is exited
*/
@Override
public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
if ((--this.bracketBalance <= 0) && (this.parent != null)){
this.updateSourceEndIfNecessary(braceStart, braceEnd);
return this.parent;
}
return this;
}
/*
* An opening brace got consumed, might be the expected opening one of the current element,
* in which case the bodyStart is updated.
*/
@Override
public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
this.bracketBalance++;
return this; // request to restart
}
/*
* Update the declarationSourceEnd of the corresponding parse node
*/
@Override
public void updateSourceEndIfNecessary(int braceStart, int braceEnd){
if (this.fieldDeclaration.declarationSourceEnd == 0) {
Initializer initializer = (Initializer)this.fieldDeclaration;
if(parser().rBraceSuccessorStart >= braceEnd) {
if (initializer.bodyStart < parser().rBraceEnd) {
initializer.declarationSourceEnd = parser().rBraceEnd;
} else {
initializer.declarationSourceEnd = initializer.bodyStart;
}
if (initializer.bodyStart < parser().rBraceStart) {
initializer.bodyEnd = parser().rBraceStart;
} else {
initializer.bodyEnd = initializer.bodyStart;
}
} else {
if (braceEnd < initializer.declarationSourceStart) {
initializer.declarationSourceEnd = initializer.declarationSourceStart;
initializer.bodyEnd = initializer.declarationSourceEnd;
} else {
initializer.declarationSourceEnd = braceEnd;
initializer.bodyEnd = braceStart - 1;
}
if (initializer.bodyStart > initializer.declarationSourceEnd) {
initializer.bodyStart = initializer.declarationSourceEnd;
if(initializer.block != null) {
initializer.block.sourceStart = initializer.declarationSourceStart;
}
}
}
if(initializer.block != null) {
initializer.block.sourceEnd = initializer.declarationSourceEnd;
}
}
}
}