merged src/java and src/rsc
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / parser / RecoveredElement.java
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java
new file mode 100644 (file)
index 0000000..bea72d2
--- /dev/null
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+/**
+ * Internal structure for parsing recovery 
+ */
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+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.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+
+public class RecoveredElement {
+
+       public RecoveredElement parent;
+       public int bracketBalance;
+       public boolean foundOpeningBrace;
+       protected Parser recoveringParser;
+public RecoveredElement(RecoveredElement parent, int bracketBalance){
+       this(parent, bracketBalance, null);
+}
+public RecoveredElement(RecoveredElement parent, int bracketBalance, Parser parser){
+       this.parent = parent;
+       this.bracketBalance = bracketBalance;
+       this.recoveringParser = parser;
+}
+/*
+ *     Record a method declaration
+ */
+public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(methodDeclaration.declarationSourceStart - 1));   
+       return this.parent.add(methodDeclaration, bracketBalanceValue);
+}
+/*
+ * Record a nested block declaration
+ */
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(nestedBlockDeclaration.sourceStart - 1)); 
+       return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
+}
+/*
+ * Record a field declaration
+ */
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));    
+       return this.parent.add(fieldDeclaration, bracketBalanceValue);
+}
+/*
+ *     Record an import reference
+ */
+public RecoveredElement add(ImportReference importReference, int bracketBalanceValue){
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(importReference.declarationSourceStart - 1));     
+       return this.parent.add(importReference, bracketBalanceValue);
+}
+/*
+ * Record a local declaration
+ */
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));    
+       return this.parent.add(localDeclaration, bracketBalanceValue);
+}
+/*
+ * Record a statement
+ */
+public RecoveredElement add(Statement statement, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(statement.sourceStart - 1));      
+       return this.parent.add(statement, bracketBalanceValue);
+}
+/*
+ *     Record a type declaration
+ */
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue){
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));     
+       return this.parent.add(typeDeclaration, bracketBalanceValue);
+}
+/*
+ * Answer the depth of this element, considering the parent link.
+ */
+public int depth(){
+       int depth = 0;
+       RecoveredElement current = this;
+       while ((current = current.parent) != null) depth++;
+       return depth;
+}
+/*
+ * Answer the enclosing method node, or null if none
+ */
+public RecoveredInitializer enclosingInitializer(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredInitializer){
+                       return (RecoveredInitializer) current;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/*
+ * Answer the enclosing method node, or null if none
+ */
+public RecoveredMethod enclosingMethod(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredMethod){
+                       return (RecoveredMethod) current;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/*
+ * Answer the enclosing type node, or null if none
+ */
+public RecoveredType enclosingType(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredType){
+                       return (RecoveredType) current;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/*
+ * Answer the closest specified parser
+ */
+public Parser parser(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current.recoveringParser != null){
+                       return current.recoveringParser;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return null;
+}
+/*
+ * Iterate the enclosing blocks and tag them so as to preserve their content
+ */
+public void preserveEnclosingBlocks(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredBlock){
+                       ((RecoveredBlock)current).preserveContent = true;
+               }
+               if (current instanceof RecoveredType){ // for anonymous types
+                       ((RecoveredType)current).preserveContent = true;
+               }
+               current = current.parent;
+       }
+}
+/*
+ * Answer the position of the previous line end if
+ * there is nothing but spaces in between it and the
+ * line end. Used to trim spaces on unclosed elements.
+ */
+public int previousAvailableLineEnd(int position){
+
+       Parser parser = this.parser();
+       if (parser == null) return position;
+       
+       Scanner scanner = parser.scanner;
+       if (scanner.lineEnds == null) return position;
+       
+       int index = scanner.getLineNumber(position);
+       if (index < 2) return position;
+       int previousLineEnd = scanner.lineEnds[index-2];
+
+       char[] source = scanner.source;
+       for (int i = previousLineEnd+1; i < position; i++){
+               if (!(source[i] == ' ' || source[i] == '\t')) return position;
+       }
+       return previousLineEnd;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+       return 0;
+}
+protected String tabString(int tab) {
+       StringBuffer result = new StringBuffer();
+       for (int i = tab; i > 0; i--) {
+               result.append("  "); //$NON-NLS-1$
+       }
+       return result.toString();
+}
+/*
+ * Answer the top node
+ */
+public RecoveredElement topElement(){
+       RecoveredElement current = this;
+       while (current.parent != null){
+               current = current.parent;
+       }
+       return current;
+}
+public String toString() {
+       return toString(0);
+}
+public String toString(int tab) {
+       return super.toString();
+}
+/*
+ * Answer the enclosing type node, or null if none
+ */
+public RecoveredType type(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredType){
+                       return (RecoveredType) current;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void updateBodyStart(int bodyStart){
+       this.foundOpeningBrace = true;  
+}
+/*
+ * Update the corresponding parse node from parser state which
+ * is about to disappear because of restarting recovery
+ */
+public void updateFromParserState(){
+       // default implementation: do nothing
+}
+/*
+ * A closing brace got consumed, might have closed the current element,
+ * in which case both the currentElement is exited
+ */
+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.
+ */
+/*public RecoveredElement updateOnOpeningBrace(int braceEnd){return null;}*/
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
+
+       if (this.bracketBalance++ == 0){
+               this.updateBodyStart(braceEnd + 1);
+               return this;
+       }
+       return null; // no update is necessary
+}
+/*
+ * Final update the corresponding parse node
+ */
+public void updateParseTree(){
+       // default implementation: do nothing
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int braceStart, int braceEnd){
+       // default implementation: do nothing
+}
+public void updateSourceEndIfNecessary(int sourceEnd){
+       this.updateSourceEndIfNecessary(sourceEnd + 1, sourceEnd);
+}
+}