/******************************************************************************* * Copyright (c) 2000, 2003 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 net.sourceforge.phpdt.internal.core.jdom; import java.util.Stack; import net.sourceforge.phpdt.core.compiler.IProblem; import net.sourceforge.phpdt.core.jdom.IDOMCompilationUnit; import net.sourceforge.phpdt.core.jdom.IDOMFactory; import net.sourceforge.phpdt.core.jdom.IDOMNode; import net.sourceforge.phpdt.internal.compiler.IDocumentElementRequestor; import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit; import net.sourceforge.phpdt.internal.core.util.ReferenceInfoAdapter; /** * An abstract DOM builder that contains shared functionality of DOMBuilder and * SimpleDOMBuilder. */ public class AbstractDOMBuilder extends ReferenceInfoAdapter implements ILineStartFinder { /** * Set to true when an error is encounterd while fuzzy parsing */ protected boolean fAbort; /** * True when a compilation unit is being constructed. False when any other * type of document fragment is being constructed. */ protected boolean fBuildingCU = false; /** * True when a compilation unit or type is being constructed. False when any * other type of document fragment is being constructed. */ protected boolean fBuildingType = false; /** * The String on which the JDOM is being created. */ protected char[] fDocument = null; /** * The source positions of all of the line separators in the document. */ protected int[] fLineStartPositions = new int[] { 0 }; /** * A stack of enclosing scopes used when constructing a compilation unit or * type. The top of the stack is the document fragment that children are * added to. */ protected Stack fStack = null; /** * The number of fields constructed in the current document. This is used * when building a single field document fragment, since the DOMBuilder only * accepts documents with one field declaration. */ protected int fFieldCount; /** * The current node being constructed. */ protected DOMNode fNode; /** * AbstractDOMBuilder constructor. */ public AbstractDOMBuilder() { super(); } /** * Accepts the line separator table and converts it into a line start table. * *
* A line separator might corresponds to several characters in the source. * * @see IDocumentElementRequestor#acceptLineSeparatorPositions(int[]) */ public void acceptLineSeparatorPositions(int[] positions) { if (positions != null) { int length = positions.length; if (length > 0) { fLineStartPositions = new int[length + 1]; fLineStartPositions[0] = 0; int documentLength = fDocument.length; for (int i = 0; i < length; i++) { int iPlusOne = i + 1; int positionPlusOne = positions[i] + 1; if (positionPlusOne < documentLength) { if (iPlusOne < length) { // more separators fLineStartPositions[iPlusOne] = positionPlusOne; } else { // no more separators if (fDocument[positionPlusOne] == '\n') { fLineStartPositions[iPlusOne] = positionPlusOne + 1; } else { fLineStartPositions[iPlusOne] = positionPlusOne; } } } else { fLineStartPositions[iPlusOne] = positionPlusOne; } } } } } /** * Does nothing. */ public void acceptProblem(IProblem problem) { } // TODO: (olivier) unused? /** * Adds the given node to the current enclosing scope, building the JDOM * tree. Nodes are only added to an enclosing scope when a compilation unit * or type is being built (since those are the only nodes that have * children). * *
* NOTE: nodes are added to the JDOM via the method #basicAddChild such that * the nodes in the newly created JDOM are not fragmented. */ protected void addChild(IDOMNode child) { if (fStack.size() > 0) { DOMNode parent = (DOMNode) fStack.peek(); if (fBuildingCU || fBuildingType) { parent.basicAddChild(child); } } } /** * @see IDOMFactory#createCompilationUnit(String, String) */ public IDOMCompilationUnit createCompilationUnit(char[] contents, char[] name) { return createCompilationUnit(new CompilationUnit(contents, name)); } /** * @see IDOMFactory#createCompilationUnit(String, String) */ public IDOMCompilationUnit createCompilationUnit( ICompilationUnit compilationUnit) { if (fAbort) { return null; } fNode.normalize(this); return (IDOMCompilationUnit) fNode; } /** * @see IDocumentElementRequestor#enterClass(int, int[], int, int, int, * char[], int, int, char[], int, int, char[][], int[], int[], int) */ public void enterCompilationUnit() { if (fBuildingCU) { IDOMCompilationUnit cu = new DOMCompilationUnit(fDocument, new int[] { 0, fDocument.length - 1 }); fStack.push(cu); } } /** * Finishes the configuration of the compilation unit DOM object which was * created by a previous enterCompilationUnit call. * * @see IDocumentElementRequestor#exitCompilationUnit(int) */ public void exitCompilationUnit(int declarationEnd) { DOMCompilationUnit cu = (DOMCompilationUnit) fStack.pop(); cu.setSourceRangeEnd(declarationEnd); fNode = cu; } /** * Finishes the configuration of the class and interface DOM objects. * * @param bodyEnd - * a source position corresponding to the closing bracket of the * class * @param declarationEnd - * a source position corresponding to the end of the class * declaration. This can include whitespace and comments * following the closing bracket. */ protected void exitType(int bodyEnd, int declarationEnd) { DOMType type = (DOMType) fStack.pop(); type.setSourceRangeEnd(declarationEnd); type.setCloseBodyRangeStart(bodyEnd); type.setCloseBodyRangeEnd(bodyEnd); fNode = type; } /** * @see ILineStartFinder#getLineStart(int) */ public int getLineStart(int position) { int lineSeparatorCount = fLineStartPositions.length; // reverse traversal intentional. for (int i = lineSeparatorCount - 1; i >= 0; i--) { if (fLineStartPositions[i] <= position) return fLineStartPositions[i]; } return 0; } /** * Initializes the builder to create a document fragment. * * @param sourceCode - * the document containing the source code to be analyzed * @param buildingCompilationUnit - * true if a the document is being analyzed to create a * compilation unit, otherwise false * @param buildingType - * true if the document is being analyzed to create a type or * compilation unit */ protected void initializeBuild(char[] sourceCode, boolean buildingCompilationUnit, boolean buildingType) { fBuildingCU = buildingCompilationUnit; fBuildingType = buildingType; fStack = new Stack(); fDocument = sourceCode; fFieldCount = 0; fAbort = false; } }