1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.parser;
14 * Internal initializer structure for parsing recovery
16 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
17 import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
18 import net.sourceforge.phpdt.internal.compiler.ast.Block;
19 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
21 import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
22 import net.sourceforge.phpdt.internal.compiler.ast.LocalTypeDeclaration;
23 import net.sourceforge.phpdt.internal.compiler.ast.Statement;
24 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
25 import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypes;
26 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
27 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
29 public class RecoveredInitializer extends RecoveredField implements CompilerModifiers, ITerminalSymbols, BaseTypes {
31 public RecoveredType[] localTypes;
32 public int localTypeCount;
34 public RecoveredBlock initializerBody;
35 public RecoveredInitializer(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance){
36 this(fieldDeclaration, parent, bracketBalance, null);
38 public RecoveredInitializer(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){
39 super(fieldDeclaration, parent, bracketBalance, parser);
40 this.foundOpeningBrace = true;
43 * Record a nested block declaration
45 public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalance) {
47 /* default behavior is to delegate recording to parent if any,
48 do not consider elements passed the known end (if set)
49 it must be belonging to an enclosing element
51 if (fieldDeclaration.declarationSourceEnd > 0
52 && nestedBlockDeclaration.sourceStart
53 > fieldDeclaration.declarationSourceEnd){
54 if (this.parent == null){
55 return this; // ignore
57 return this.parent.add(nestedBlockDeclaration, bracketBalance);
60 /* consider that if the opening brace was not found, it is there */
61 if (!foundOpeningBrace){
62 foundOpeningBrace = true;
63 this.bracketBalance++;
66 initializerBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalance);
67 if (nestedBlockDeclaration.sourceEnd == 0) return initializerBody;
71 * Record a field declaration (act like inside method body)
73 public RecoveredElement add(FieldDeclaration newFieldDeclaration, int bracketBalance) {
75 /* local variables inside initializer can only be final and non void */
76 char[][] fieldTypeName;
77 if ((newFieldDeclaration.modifiers & ~AccFinal) != 0 /* local var can only be final */
78 || (newFieldDeclaration.type == null) // initializer
79 || ((fieldTypeName = newFieldDeclaration.type.getTypeName()).length == 1 // non void
80 && CharOperation.equals(fieldTypeName[0], VoidBinding.sourceName()))){
81 if (this.parent == null) {
82 return this; // ignore
84 this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(newFieldDeclaration.declarationSourceStart - 1));
85 return this.parent.add(newFieldDeclaration, bracketBalance);
89 /* default behavior is to delegate recording to parent if any,
90 do not consider elements passed the known end (if set)
91 it must be belonging to an enclosing element
93 if (this.fieldDeclaration.declarationSourceEnd > 0
94 && newFieldDeclaration.declarationSourceStart
95 > this.fieldDeclaration.declarationSourceEnd){
96 if (this.parent == null) {
97 return this; // ignore
99 return this.parent.add(newFieldDeclaration, bracketBalance);
102 // still inside initializer, treat as local variable
103 return this; // ignore
106 * Record a local declaration - regular method should have been created a block body
108 public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalance) {
110 /* do not consider a type starting passed the type end (if set)
111 it must be belonging to an enclosing type */
112 if (fieldDeclaration.declarationSourceEnd != 0
113 && localDeclaration.declarationSourceStart > fieldDeclaration.declarationSourceEnd){
114 if (parent == null) {
115 return this; // ignore
117 return this.parent.add(localDeclaration, bracketBalance);
120 /* method body should have been created */
121 Block block = new Block(0);
122 block.sourceStart = ((Initializer)fieldDeclaration).bodyStart;
123 RecoveredElement element = this.add(block, 1);
124 return element.add(localDeclaration, bracketBalance);
127 * Record a statement - regular method should have been created a block body
129 public RecoveredElement add(Statement statement, int bracketBalance) {
131 /* do not consider a statement starting passed the initializer end (if set)
132 it must be belonging to an enclosing type */
133 if (fieldDeclaration.declarationSourceEnd != 0
134 && statement.sourceStart > fieldDeclaration.declarationSourceEnd){
135 if (parent == null) {
136 return this; // ignore
138 return this.parent.add(statement, bracketBalance);
141 /* initializer body should have been created */
142 Block block = new Block(0);
143 block.sourceStart = ((Initializer)fieldDeclaration).bodyStart;
144 RecoveredElement element = this.add(block, 1);
145 return element.add(statement, bracketBalance);
147 public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
149 /* do not consider a type starting passed the type end (if set)
150 it must be belonging to an enclosing type */
151 if (fieldDeclaration.declarationSourceEnd != 0
152 && typeDeclaration.declarationSourceStart > fieldDeclaration.declarationSourceEnd){
153 if (parent == null) {
154 return this; // ignore
156 return this.parent.add(typeDeclaration, bracketBalance);
159 if (typeDeclaration instanceof LocalTypeDeclaration){
160 /* method body should have been created */
161 Block block = new Block(0);
162 block.sourceStart = ((Initializer)fieldDeclaration).bodyStart;
163 RecoveredElement element = this.add(block, 1);
164 return element.add(typeDeclaration, bracketBalance);
166 if (localTypes == null) {
167 localTypes = new RecoveredType[5];
170 if (localTypeCount == localTypes.length) {
174 (localTypes = new RecoveredType[2 * localTypeCount]),
179 RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalance);
180 localTypes[localTypeCount++] = element;
182 /* consider that if the opening brace was not found, it is there */
183 if (!foundOpeningBrace){
184 foundOpeningBrace = true;
185 this.bracketBalance++;
189 public String toString(int tab) {
190 StringBuffer result = new StringBuffer(tabString(tab));
191 result.append("Recovered initializer:\n"); //$NON-NLS-1$
192 result.append(this.fieldDeclaration.toString(tab + 1));
193 if (this.initializerBody != null) {
194 result.append("\n"); //$NON-NLS-1$
195 result.append(this.initializerBody.toString(tab + 1));
197 return result.toString();
199 public FieldDeclaration updatedFieldDeclaration(){
201 if (initializerBody != null){
202 Block block = initializerBody.updatedBlock();
204 ((Initializer)fieldDeclaration).block = block;
206 if (this.localTypeCount > 0) fieldDeclaration.bits |= AstNode.HasLocalTypeMASK;
209 if (fieldDeclaration.sourceEnd == 0){
210 fieldDeclaration.sourceEnd = fieldDeclaration.declarationSourceEnd;
212 return fieldDeclaration;
215 * A closing brace got consumed, might have closed the current element,
216 * in which case both the currentElement is exited
218 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
219 if ((--bracketBalance <= 0) && (parent != null)){
220 this.updateSourceEndIfNecessary(braceEnd);
226 * An opening brace got consumed, might be the expected opening one of the current element,
227 * in which case the bodyStart is updated.
229 public RecoveredElement updateOnOpeningBrace(int currentPosition){
231 return this; // request to restart
234 * Update the declarationSourceEnd of the corresponding parse node
236 public void updateSourceEndIfNecessary(int sourceEnd){
237 if (this.fieldDeclaration.declarationSourceEnd == 0) {
238 this.fieldDeclaration.sourceEnd = sourceEnd;
239 this.fieldDeclaration.declarationSourceEnd = sourceEnd;
240 this.fieldDeclaration.declarationEnd = sourceEnd;