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