RC2 compatibility
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / jdom / AbstractDOMBuilder.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 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 net.sourceforge.phpdt.internal.core.jdom;
12
13 import java.util.Stack;
14
15 import net.sourceforge.phpdt.core.compiler.IProblem;
16 import net.sourceforge.phpdt.core.jdom.IDOMCompilationUnit;
17 import net.sourceforge.phpdt.core.jdom.IDOMFactory;
18 import net.sourceforge.phpdt.core.jdom.IDOMNode;
19 import net.sourceforge.phpdt.internal.compiler.IDocumentElementRequestor;
20 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
21 import net.sourceforge.phpdt.internal.core.util.ReferenceInfoAdapter;
22
23 /**
24  * An abstract DOM builder that contains shared functionality of DOMBuilder and SimpleDOMBuilder.
25  */
26 public class AbstractDOMBuilder extends ReferenceInfoAdapter implements ILineStartFinder {
27         /**
28          * Set to true when an error is encounterd while
29          * fuzzy parsing
30          */
31         protected boolean fAbort;
32         
33         /**
34          * True when a compilation unit is being constructed.
35          * False when any other type of document fragment is
36          * being constructed.
37          */
38         protected boolean fBuildingCU = false;
39
40         /**
41          * True when a compilation unit or type is being
42          * constructed. False when any other type of document
43          * fragment is being constructed.
44          */
45         protected boolean fBuildingType= false;
46
47         /**
48          * The String on which the JDOM is being created.
49          */
50         protected char[] fDocument= null;
51                 
52         /**
53          * The source positions of all of the line separators in the document.
54          */
55         protected int[] fLineStartPositions = new int[] { 0 };
56
57         /**
58          * A stack of enclosing scopes used when constructing
59          * a compilation unit or type. The top of the stack
60          * is the document fragment that children are added to.
61          */
62         protected Stack fStack = null;  
63
64         /**
65          * The number of fields constructed in the current
66          * document. This is used when building a single
67          * field document fragment, since the DOMBuilder only
68          * accepts documents with one field declaration.
69          */
70         protected int fFieldCount;
71
72         /**
73          * The current node being constructed.
74          */
75         protected DOMNode fNode;
76 /**
77  * AbstractDOMBuilder constructor.
78  */
79 public AbstractDOMBuilder() {
80         super();
81 }
82 /**
83  * Accepts the line separator table and converts it into a line start table.
84  *
85  * <p>A line separator might corresponds to several characters in the source.
86  *
87  * @see IDocumentElementRequestor#acceptLineSeparatorPositions(int[])
88  */
89 public void acceptLineSeparatorPositions(int[] positions) {
90         if (positions != null) {
91                 int length = positions.length;
92                 if (length > 0) {
93                         fLineStartPositions = new int[length + 1];
94                         fLineStartPositions[0] = 0;
95                         int documentLength = fDocument.length;
96                         for (int i = 0; i < length; i++) {
97                                 int iPlusOne = i + 1;
98                                 int positionPlusOne = positions[i] + 1; 
99                                 if (positionPlusOne < documentLength) {
100                                         if (iPlusOne < length) {
101                                                 // more separators
102                                                 fLineStartPositions[iPlusOne] = positionPlusOne;
103                                         } else {
104                                                 // no more separators
105                                                 if (fDocument[positionPlusOne] == '\n') {
106                                                         fLineStartPositions[iPlusOne] = positionPlusOne + 1;
107                                                 } else {
108                                                         fLineStartPositions[iPlusOne] = positionPlusOne;
109                                                 }
110                                         }
111                                 } else {
112                                         fLineStartPositions[iPlusOne] = positionPlusOne;
113                                 }
114                         }
115                 }
116         }
117 }
118 /**
119  * Does nothing.
120  */
121 public void acceptProblem(IProblem problem) {} //TODO: (olivier) unused?
122 /**
123  * Adds the given node to the current enclosing scope, building the JDOM
124  * tree. Nodes are only added to an enclosing scope when a compilation unit or type
125  * is being built (since those are the only nodes that have children).
126  *
127  * <p>NOTE: nodes are added to the JDOM via the method #basicAddChild such that
128  * the nodes in the newly created JDOM are not fragmented. 
129  */
130 protected void addChild(IDOMNode child) {
131         if (fStack.size() > 0) {
132                 DOMNode parent = (DOMNode) fStack.peek();
133                 if (fBuildingCU || fBuildingType) {
134                         parent.basicAddChild(child);
135                 }
136         }
137 }
138 /**
139  * @see IDOMFactory#createCompilationUnit(String, String)
140  */
141 public IDOMCompilationUnit createCompilationUnit(char[] contents, char[] name) {
142         return createCompilationUnit(new CompilationUnit(contents, name));
143 }
144 /**
145  * @see IDOMFactory#createCompilationUnit(String, String)
146  */
147 public IDOMCompilationUnit createCompilationUnit(ICompilationUnit compilationUnit) {
148         if (fAbort) {
149                 return null;
150         }
151         fNode.normalize(this);
152         return (IDOMCompilationUnit)fNode;
153 }
154 /**
155  * @see IDocumentElementRequestor#enterClass(int, int[], int, int, int, char[], int, int, char[], int, int, char[][], int[], int[], int)
156  */
157 public void enterCompilationUnit() {
158         if (fBuildingCU) {
159                 IDOMCompilationUnit cu= new DOMCompilationUnit(fDocument, new int[] {0, fDocument.length - 1});
160                 fStack.push(cu);
161         }
162 }
163 /**
164  * Finishes the configuration of the compilation unit DOM object which
165  * was created by a previous enterCompilationUnit call.
166  *
167  * @see IDocumentElementRequestor#exitCompilationUnit(int)
168  */
169 public void exitCompilationUnit(int declarationEnd) {
170         DOMCompilationUnit cu = (DOMCompilationUnit) fStack.pop();
171         cu.setSourceRangeEnd(declarationEnd);
172         fNode = cu;
173 }
174 /**
175  * Finishes the configuration of the class and interface DOM objects.
176  *
177  * @param bodyEnd - a source position corresponding to the closing bracket of the class
178  * @param declarationEnd - a source position corresponding to the end of the class
179  *              declaration.  This can include whitespace and comments following the closing bracket.
180  */
181 protected void exitType(int bodyEnd, int declarationEnd) {
182         DOMType type = (DOMType)fStack.pop();
183         type.setSourceRangeEnd(declarationEnd);
184         type.setCloseBodyRangeStart(bodyEnd);
185         type.setCloseBodyRangeEnd(bodyEnd);
186         fNode = type;
187 }
188 /**
189  * @see ILineStartFinder#getLineStart(int)
190  */
191 public int getLineStart(int position) {
192         int lineSeparatorCount = fLineStartPositions.length;
193         // reverse traversal intentional.
194         for(int i = lineSeparatorCount - 1; i >= 0; i--) {
195                 if (fLineStartPositions[i] <= position)
196                         return fLineStartPositions[i];
197         }
198         return 0;
199 }
200 /**
201  * Initializes the builder to create a document fragment.
202  *
203  * @param sourceCode - the document containing the source code to be analyzed
204  * @param buildingCompilationUnit - true if a the document is being analyzed to
205  *              create a compilation unit, otherwise false
206  * @param buildingType - true if the document is being analyzed to create a
207  *              type or compilation unit
208  */
209 protected void initializeBuild(char[] sourceCode, boolean buildingCompilationUnit, boolean buildingType) {
210         fBuildingCU = buildingCompilationUnit;
211         fBuildingType = buildingType;
212         fStack = new Stack();
213         fDocument = sourceCode;
214         fFieldCount = 0;
215         fAbort = false;
216 }
217 }