KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > parser > RecoveredBlock


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.parser;
12
13 import org.eclipse.jdt.core.compiler.*;
14 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
15 import org.eclipse.jdt.internal.compiler.ast.Argument;
16 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
17 import org.eclipse.jdt.internal.compiler.ast.Block;
18 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
19 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
20 import org.eclipse.jdt.internal.compiler.ast.Statement;
21 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
22 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
23 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
24
25 public class RecoveredBlock extends RecoveredStatement implements TerminalTokens {
26
27     public Block blockDeclaration;
28     public RecoveredStatement[] statements;
29     public int statementCount;
30     public boolean preserveContent = false;
31     public RecoveredLocalVariable pendingArgument;
32     
33 public RecoveredBlock(Block block, RecoveredElement parent, int bracketBalance){
34     super(block, parent, bracketBalance);
35     this.blockDeclaration = block;
36     this.foundOpeningBrace = true;
37     
38     this.preserveContent = this.parser().methodRecoveryActivated || this.parser().statementRecoveryActivated;
39 }
40 public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
41     if (this.parent != null && this.parent instanceof RecoveredMethod) {
42         RecoveredMethod enclosingRecoveredMethod = (RecoveredMethod) this.parent;
43         if (enclosingRecoveredMethod.methodBody == this && enclosingRecoveredMethod.parent == null) {
44             // the element cannot be added because we are in the body of a top level method
45
return this; // ignore this element
46
}
47     }
48     return super.add(methodDeclaration, bracketBalanceValue);
49 }
50 /*
51  * Record a nested block declaration
52  */

53 public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
54
55     /* do not consider a nested block starting passed the block end (if set)
56         it must be belonging to an enclosing block */

57     if (this.blockDeclaration.sourceEnd != 0
58         && nestedBlockDeclaration.sourceStart > this.blockDeclaration.sourceEnd){
59         return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
60     }
61             
62     RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue);
63
64     // if we have a pending Argument, promote it into the new block
65
if (this.pendingArgument != null){
66         element.attach(this.pendingArgument);
67         this.pendingArgument = null;
68     }
69     if(this.parser().statementRecoveryActivated) {
70         this.addBlockStatement(element);
71     }
72     this.attach(element);
73     if (nestedBlockDeclaration.sourceEnd == 0) return element;
74     return this;
75 }
76 /*
77  * Record a local declaration
78  */

79 public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
80     return this.add(localDeclaration, bracketBalanceValue, false);
81 }
82 /*
83  * Record a local declaration
84  */

85 public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue, boolean delegatedByParent) {
86
87     /* local variables inside method can only be final and non void */
88 /*
89     char[][] localTypeName;
90     if ((localDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final
91         || (localDeclaration.type == null) // initializer
92         || ((localTypeName = localDeclaration.type.getTypeName()).length == 1 // non void
93             && CharOperation.equals(localTypeName[0], VoidBinding.sourceName()))){
94
95         if (delegatedByParent){
96             return this; //ignore
97         } else {
98             this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));
99             return this.parent.add(localDeclaration, bracketBalance);
100         }
101     }
102 */

103         /* do not consider a local variable starting passed the block end (if set)
104         it must be belonging to an enclosing block */

105     if (this.blockDeclaration.sourceEnd != 0
106             && localDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){
107         if (delegatedByParent) return this; //ignore
108
return this.parent.add(localDeclaration, bracketBalanceValue);
109     }
110
111     RecoveredLocalVariable element = new RecoveredLocalVariable(localDeclaration, this, bracketBalanceValue);
112
113     if (localDeclaration instanceof Argument){
114         this.pendingArgument = element;
115         return this;
116     }
117     
118     this.attach(element);
119     if (localDeclaration.declarationSourceEnd == 0) return element;
120     return this;
121 }
122 /*
123  * Record a statement declaration
124  */

125 public RecoveredElement add(Statement stmt, int bracketBalanceValue) {
126     return this.add(stmt, bracketBalanceValue, false);
127 }
128
129 /*
130  * Record a statement declaration
131  */

132 public RecoveredElement add(Statement stmt, int bracketBalanceValue, boolean delegatedByParent) {
133
134     /* do not consider a nested block starting passed the block end (if set)
135         it must be belonging to an enclosing block */

136     if (this.blockDeclaration.sourceEnd != 0
137             && stmt.sourceStart > this.blockDeclaration.sourceEnd){
138         if (delegatedByParent) return this; //ignore
139
return this.parent.add(stmt, bracketBalanceValue);
140     }
141             
142     RecoveredStatement element = new RecoveredStatement(stmt, this, bracketBalanceValue);
143     this.attach(element);
144     if (stmt.sourceEnd == 0) return element;
145     return this;
146 }
147 /*
148  * Addition of a type to an initializer (act like inside method body)
149  */

150 public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
151     return this.add(typeDeclaration, bracketBalanceValue, false);
152 }
153 /*
154  * Addition of a type to an initializer (act like inside method body)
155  */

156 public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue, boolean delegatedByParent) {
157
158     /* do not consider a type starting passed the block end (if set)
159         it must be belonging to an enclosing block */

160     if (this.blockDeclaration.sourceEnd != 0
161             && typeDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){
162         if (delegatedByParent) return this; //ignore
163
return this.parent.add(typeDeclaration, bracketBalanceValue);
164     }
165             
166     RecoveredStatement element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
167     this.attach(element);
168     if (typeDeclaration.declarationSourceEnd == 0) return element;
169     return this;
170 }
171 /*
172  * Attach a recovered statement
173  */

174 void attach(RecoveredStatement recoveredStatement) {
175
176     if (this.statements == null) {
177         this.statements = new RecoveredStatement[5];
178         this.statementCount = 0;
179     } else {
180         if (this.statementCount == this.statements.length) {
181             System.arraycopy(
182                 this.statements,
183                 0,
184                 (this.statements = new RecoveredStatement[2 * this.statementCount]),
185                 0,
186                 this.statementCount);
187         }
188     }
189     this.statements[this.statementCount++] = recoveredStatement;
190 }
191 /*
192  * Answer the associated parsed structure
193  */

194 public ASTNode parseTree(){
195     return this.blockDeclaration;
196 }
197 public String JavaDoc toString(int tab) {
198     StringBuffer JavaDoc result = new StringBuffer JavaDoc(tabString(tab));
199     result.append("Recovered block:\n"); //$NON-NLS-1$
200
this.blockDeclaration.print(tab + 1, result);
201     if (this.statements != null) {
202         for (int i = 0; i < this.statementCount; i++) {
203             result.append("\n"); //$NON-NLS-1$
204
result.append(this.statements[i].toString(tab + 1));
205         }
206     }
207     return result.toString();
208 }
209 /*
210  * Rebuild a block from the nested structure which is in scope
211  */

212 public Block updatedBlock(){
213
214     // if block was not marked to be preserved or empty, then ignore it
215
if (!this.preserveContent || this.statementCount == 0) return null;
216
217     Statement[] updatedStatements = new Statement[this.statementCount];
218     int updatedCount = 0;
219     
220     
221     // may need to update the end of the last statement
222
RecoveredStatement lastStatement = statements[statementCount - 1];
223     RecoveredMethod enclosingMethod = this.enclosingMethod();
224     RecoveredInitializer enclosingIntializer = this.enclosingInitializer();
225     int bodyEndValue = 0;
226     if(enclosingMethod != null) {
227         bodyEndValue = enclosingMethod.methodDeclaration.bodyEnd;
228         if(enclosingIntializer != null && enclosingMethod.methodDeclaration.sourceStart < enclosingIntializer.fieldDeclaration.sourceStart) {
229             bodyEndValue = enclosingIntializer.fieldDeclaration.declarationSourceEnd;
230         }
231     } else if(enclosingIntializer != null) {
232         bodyEndValue = enclosingIntializer.fieldDeclaration.declarationSourceEnd;
233     } else {
234         bodyEndValue = this.blockDeclaration.sourceEnd - 1;
235     }
236     
237     if(lastStatement instanceof RecoveredLocalVariable) {
238         RecoveredLocalVariable lastLocalVariable = (RecoveredLocalVariable) lastStatement;
239         if(lastLocalVariable.localDeclaration.declarationSourceEnd == 0) {
240             lastLocalVariable.localDeclaration.declarationSourceEnd = bodyEndValue;
241             lastLocalVariable.localDeclaration.declarationEnd = bodyEndValue;
242         }
243     } else if(lastStatement instanceof RecoveredBlock) {
244         RecoveredBlock lastBlock = (RecoveredBlock) lastStatement;
245         if(lastBlock.blockDeclaration.sourceEnd == 0) {
246             lastBlock.blockDeclaration.sourceEnd = bodyEndValue;
247         }
248     } else if(!(lastStatement instanceof RecoveredType)){
249         if(lastStatement.statement.sourceEnd == 0) {
250             lastStatement.statement.sourceEnd = bodyEndValue;
251         }
252     }
253     
254     int lastEnd = blockDeclaration.sourceStart;
255     
256     // only collect the non-null updated statements
257
for (int i = 0; i < this.statementCount; i++){
258         Statement updatedStatement = this.statements[i].updatedStatement();
259         if (updatedStatement != null){
260             updatedStatements[updatedCount++] = updatedStatement;
261             
262             if (updatedStatement instanceof LocalDeclaration) {
263                 LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement;
264                 if(localDeclaration.declarationSourceEnd > lastEnd) {
265                     lastEnd = localDeclaration.declarationSourceEnd;
266                 }
267             } else if (updatedStatement instanceof TypeDeclaration) {
268                 TypeDeclaration typeDeclaration = (TypeDeclaration) updatedStatement;
269                 if(typeDeclaration.declarationSourceEnd > lastEnd) {
270                     lastEnd = typeDeclaration.declarationSourceEnd;
271                 }
272             } else {
273                 if (updatedStatement.sourceEnd > lastEnd) {
274                     lastEnd = updatedStatement.sourceEnd;
275                 }
276             }
277         }
278     }
279     if (updatedCount == 0) return null; // not interesting block
280

281     // resize statement collection if necessary
282
if (updatedCount != this.statementCount){
283         this.blockDeclaration.statements = new Statement[updatedCount];
284         System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount);
285     } else {
286         this.blockDeclaration.statements = updatedStatements;
287     }
288
289     if (this.blockDeclaration.sourceEnd == 0) {
290         if(lastEnd < bodyEndValue) {
291             this.blockDeclaration.sourceEnd = bodyEndValue;
292         } else {
293             this.blockDeclaration.sourceEnd = lastEnd;
294         }
295     }
296     
297     return this.blockDeclaration;
298 }
299 /*
300  * Rebuild a statement from the nested structure which is in scope
301  */

302 public Statement updatedStatement(){
303
304     return this.updatedBlock();
305 }
306 /*
307  * A closing brace got consumed, might have closed the current element,
308  * in which case both the currentElement is exited
309  */

310 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
311     if ((--this.bracketBalance <= 0) && (this.parent != null)){
312         this.updateSourceEndIfNecessary(braceStart, braceEnd);
313
314         /* if the block is the method body, then it closes the method too */
315         RecoveredMethod method = enclosingMethod();
316         if (method != null && method.methodBody == this){
317             return this.parent.updateOnClosingBrace(braceStart, braceEnd);
318         }
319         RecoveredInitializer initializer = enclosingInitializer();
320         if (initializer != null && initializer.initializerBody == this){
321             return this.parent.updateOnClosingBrace(braceStart, braceEnd);
322         }
323         return this.parent;
324     }
325     return this;
326 }
327 /*
328  * An opening brace got consumed, might be the expected opening one of the current element,
329  * in which case the bodyStart is updated.
330  */

331 public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
332
333     // create a nested block
334
Block block = new Block(0);
335     block.sourceStart = parser().scanner.startPosition;
336     return this.add(block, 1);
337 }
338 /*
339  * Final update the corresponding parse node
340  */

341 public void updateParseTree(){
342
343     this.updatedBlock();
344 }
345 /*
346  * Rebuild a flattened block from the nested structure which is in scope
347  */

348 public Statement updateStatement(){
349
350     // if block was closed or empty, then ignore it
351
if (this.blockDeclaration.sourceEnd != 0 || this.statementCount == 0) return null;
352
353     Statement[] updatedStatements = new Statement[this.statementCount];
354     int updatedCount = 0;
355     
356     // only collect the non-null updated statements
357
for (int i = 0; i < this.statementCount; i++){
358         Statement updatedStatement = this.statements[i].updatedStatement();
359         if (updatedStatement != null){
360             updatedStatements[updatedCount++] = updatedStatement;
361         }
362     }
363     if (updatedCount == 0) return null; // not interesting block
364

365     // resize statement collection if necessary
366
if (updatedCount != this.statementCount){
367         this.blockDeclaration.statements = new Statement[updatedCount];
368         System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount);
369     } else {
370         this.blockDeclaration.statements = updatedStatements;
371     }
372
373     return this.blockDeclaration;
374 }
375
376 /*
377  * Record a field declaration
378  */

379 public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
380
381     /* local variables inside method can only be final and non void */
382     char[][] fieldTypeName;
383     if ((fieldDeclaration.modifiers & ~ClassFileConstants.AccFinal) != 0 // local var can only be final
384
|| (fieldDeclaration.type == null) // initializer
385
|| ((fieldTypeName = fieldDeclaration.type.getTypeName()).length == 1 // non void
386
&& CharOperation.equals(fieldTypeName[0], TypeBinding.VOID.sourceName()))){
387         this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));
388         return this.parent.add(fieldDeclaration, bracketBalanceValue);
389     }
390     
391     /* do not consider a local variable starting passed the block end (if set)
392         it must be belonging to an enclosing block */

393     if (this.blockDeclaration.sourceEnd != 0
394         && fieldDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){
395         return this.parent.add(fieldDeclaration, bracketBalanceValue);
396     }
397
398     // ignore the added field, since indicates a local variable behind recovery point
399
// which thus got parsed as a field reference. This can happen if restarting after
400
// having reduced an assistNode to get the following context (see 1GEK7SG)
401
return this;
402 }
403 }
404
Popular Tags