Makefile fixup
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / parser / RecoveredElement.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.parser;
12
13 /**
14  * Internal structure for parsing recovery 
15  */
16 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
17 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
18 import org.eclipse.jdt.internal.compiler.ast.Block;
19 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
20 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
21 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
22 import org.eclipse.jdt.internal.compiler.ast.Statement;
23 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
24
25 public class RecoveredElement {
26
27         public RecoveredElement parent;
28         public int bracketBalance;
29         public boolean foundOpeningBrace;
30         protected Parser recoveringParser;
31 public RecoveredElement(RecoveredElement parent, int bracketBalance){
32         this(parent, bracketBalance, null);
33 }
34 public RecoveredElement(RecoveredElement parent, int bracketBalance, Parser parser){
35         this.parent = parent;
36         this.bracketBalance = bracketBalance;
37         this.recoveringParser = parser;
38 }
39 /*
40  *      Record a method declaration
41  */
42 public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
43
44         /* default behavior is to delegate recording to parent if any */
45         if (this.parent == null) return this; // ignore
46         this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(methodDeclaration.declarationSourceStart - 1));   
47         return this.parent.add(methodDeclaration, bracketBalanceValue);
48 }
49 /*
50  * Record a nested block declaration
51  */
52 public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
53
54         /* default behavior is to delegate recording to parent if any */
55         if (this.parent == null) return this; // ignore
56         this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(nestedBlockDeclaration.sourceStart - 1)); 
57         return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
58 }
59 /*
60  * Record a field declaration
61  */
62 public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
63
64         /* default behavior is to delegate recording to parent if any */
65         if (this.parent == null) return this; // ignore
66         this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));    
67         return this.parent.add(fieldDeclaration, bracketBalanceValue);
68 }
69 /*
70  *      Record an import reference
71  */
72 public RecoveredElement add(ImportReference importReference, int bracketBalanceValue){
73
74         /* default behavior is to delegate recording to parent if any */
75         if (this.parent == null) return this; // ignore
76         this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(importReference.declarationSourceStart - 1));     
77         return this.parent.add(importReference, bracketBalanceValue);
78 }
79 /*
80  * Record a local declaration
81  */
82 public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
83
84         /* default behavior is to delegate recording to parent if any */
85         if (this.parent == null) return this; // ignore
86         this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));    
87         return this.parent.add(localDeclaration, bracketBalanceValue);
88 }
89 /*
90  * Record a statement
91  */
92 public RecoveredElement add(Statement statement, int bracketBalanceValue) {
93
94         /* default behavior is to delegate recording to parent if any */
95         if (this.parent == null) return this; // ignore
96         this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(statement.sourceStart - 1));      
97         return this.parent.add(statement, bracketBalanceValue);
98 }
99 /*
100  *      Record a type declaration
101  */
102 public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue){
103
104         /* default behavior is to delegate recording to parent if any */
105         if (this.parent == null) return this; // ignore
106         this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));     
107         return this.parent.add(typeDeclaration, bracketBalanceValue);
108 }
109 /*
110  * Answer the depth of this element, considering the parent link.
111  */
112 public int depth(){
113         int depth = 0;
114         RecoveredElement current = this;
115         while ((current = current.parent) != null) depth++;
116         return depth;
117 }
118 /*
119  * Answer the enclosing method node, or null if none
120  */
121 public RecoveredInitializer enclosingInitializer(){
122         RecoveredElement current = this;
123         while (current != null){
124                 if (current instanceof RecoveredInitializer){
125                         return (RecoveredInitializer) current;
126                 }
127                 current = current.parent;
128         }
129         return null;
130 }
131 /*
132  * Answer the enclosing method node, or null if none
133  */
134 public RecoveredMethod enclosingMethod(){
135         RecoveredElement current = this;
136         while (current != null){
137                 if (current instanceof RecoveredMethod){
138                         return (RecoveredMethod) current;
139                 }
140                 current = current.parent;
141         }
142         return null;
143 }
144 /*
145  * Answer the enclosing type node, or null if none
146  */
147 public RecoveredType enclosingType(){
148         RecoveredElement current = this;
149         while (current != null){
150                 if (current instanceof RecoveredType){
151                         return (RecoveredType) current;
152                 }
153                 current = current.parent;
154         }
155         return null;
156 }
157 /*
158  * Answer the closest specified parser
159  */
160 public Parser parser(){
161         RecoveredElement current = this;
162         while (current != null){
163                 if (current.recoveringParser != null){
164                         return current.recoveringParser;
165                 }
166                 current = current.parent;
167         }
168         return null;
169 }
170 /* 
171  * Answer the associated parsed structure
172  */
173 public ASTNode parseTree(){
174         return null;
175 }
176 /*
177  * Iterate the enclosing blocks and tag them so as to preserve their content
178  */
179 public void preserveEnclosingBlocks(){
180         RecoveredElement current = this;
181         while (current != null){
182                 if (current instanceof RecoveredBlock){
183                         ((RecoveredBlock)current).preserveContent = true;
184                 }
185                 if (current instanceof RecoveredType){ // for anonymous types
186                         ((RecoveredType)current).preserveContent = true;
187                 }
188                 current = current.parent;
189         }
190 }
191 /*
192  * Answer the position of the previous line end if
193  * there is nothing but spaces in between it and the
194  * line end. Used to trim spaces on unclosed elements.
195  */
196 public int previousAvailableLineEnd(int position){
197
198         Parser parser = this.parser();
199         if (parser == null) return position;
200         
201         Scanner scanner = parser.scanner;
202         if (scanner.lineEnds == null) return position;
203         
204         int index = scanner.getLineNumber(position);
205         if (index < 2) return position;
206         int previousLineEnd = scanner.lineEnds[index-2];
207
208         char[] source = scanner.source;
209         for (int i = previousLineEnd+1; i < position; i++){
210                 if (!(source[i] == ' ' || source[i] == '\t')) return position;
211         }
212         return previousLineEnd;
213 }
214 /*
215  * Answer the very source end of the corresponding parse node
216  */
217 public int sourceEnd(){
218         return 0;
219 }
220 protected String tabString(int tab) {
221         StringBuffer result = new StringBuffer();
222         for (int i = tab; i > 0; i--) {
223                 result.append("  "); //$NON-NLS-1$
224         }
225         return result.toString();
226 }
227 /*
228  * Answer the top node
229  */
230 public RecoveredElement topElement(){
231         RecoveredElement current = this;
232         while (current.parent != null){
233                 current = current.parent;
234         }
235         return current;
236 }
237 public String toString() {
238         return toString(0);
239 }
240 public String toString(int tab) {
241         return super.toString();
242 }
243 /*
244  * Answer the enclosing type node, or null if none
245  */
246 public RecoveredType type(){
247         RecoveredElement current = this;
248         while (current != null){
249                 if (current instanceof RecoveredType){
250                         return (RecoveredType) current;
251                 }
252                 current = current.parent;
253         }
254         return null;
255 }
256 /*
257  * Update the bodyStart of the corresponding parse node
258  */
259 public void updateBodyStart(int bodyStart){
260         this.foundOpeningBrace = true;  
261 }
262 /*
263  * Update the corresponding parse node from parser state which
264  * is about to disappear because of restarting recovery
265  */
266 public void updateFromParserState(){
267         // default implementation: do nothing
268 }
269 /*
270  * A closing brace got consumed, might have closed the current element,
271  * in which case both the currentElement is exited
272  */
273 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
274         if ((--this.bracketBalance <= 0) && (this.parent != null)){
275                 this.updateSourceEndIfNecessary(braceStart, braceEnd);
276                 return this.parent;
277         }
278         return this;
279 }
280 /*
281  * An opening brace got consumed, might be the expected opening one of the current element,
282  * in which case the bodyStart is updated.
283  */
284 /*public RecoveredElement updateOnOpeningBrace(int braceEnd){return null;}*/
285 public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
286
287         if (this.bracketBalance++ == 0){
288                 this.updateBodyStart(braceEnd + 1);
289                 return this;
290         }
291         return null; // no update is necessary
292 }
293 /*
294  * Final update the corresponding parse node
295  */
296 public void updateParseTree(){
297         // default implementation: do nothing
298 }
299 /*
300  * Update the declarationSourceEnd of the corresponding parse node
301  */
302 public void updateSourceEndIfNecessary(int braceStart, int braceEnd){
303         // default implementation: do nothing
304 }
305 public void updateSourceEndIfNecessary(int sourceEnd){
306         this.updateSourceEndIfNecessary(sourceEnd + 1, sourceEnd);
307 }
308 }