/******************************************************************************* * Copyright (c) 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Zend Technologies *******************************************************************************/ package org2.eclipse.php.internal.core.ast.nodes; import java.io.IOException; import java.io.Reader; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java_cup.runtime.Scanner; import java_cup.runtime.lr_parser; import org.eclipse.core.resources.IResource; import org.eclipse.jface.text.IDocument; import org.eclipse.text.edits.TextEdit; import org2.eclipse.php.internal.core.CoreMessages; import org2.eclipse.php.internal.core.PHPVersion; import org2.eclipse.php.internal.core.ast.rewrite.ASTRewrite; import org2.eclipse.php.internal.core.ast.scanner.AbstractASTParser; import org2.eclipse.php.internal.core.ast.scanner.AstLexer; import com.aptana.core.build.IBuildParticipant.BuildType; import com.aptana.core.resources.IUniformResource; import com.aptana.editor.php.internal.core.builder.BuildProblemReporter; /** * Umbrella owner and abstract syntax tree node factory. An <code>AST</code> * instance serves as the common owner of any number of AST nodes, and as the * factory for creating new AST nodes owned by that instance. * <p> * Abstract syntax trees may be hand constructed by clients, using the * <code>new<i>TYPE</i></code> factory methods to create new nodes, and the * various <code>set<i>CHILD</i></code> methods (see * {@link org.eclipse.php.internal.core.ast.nodes.ASTNode} and its subclasses) * to connect them together. * </p> * <p> * Each AST node belongs to a unique AST instance, called the owning AST. The * children of an AST node always have the same owner as their parent node. If a * node from one AST is to be added to a different AST, the subtree must be * cloned first to ensures that the added nodes have the correct owning AST. * </p> * <p> * There can be any number of AST nodes owned by a single AST instance that are * unparented. Each of these nodes is the root of a separate little tree of * nodes. The method <code>ASTNode.getProgramRoot()</code> navigates from any * node to the root of the tree that it is contained in. Ordinarily, an AST * instance has one main tree (rooted at a <code>Program</code>), with * newly-created nodes appearing as additional roots until they are parented * somewhere under the main tree. One can navigate from any node to its AST * instance, but not conversely. * </p> * <p> * The class {@link ASTParser} parses a string containing a PHP source code and * returns an abstract syntax tree for it. The resulting nodes carry source * ranges relating the node back to the original source characters. * </p> * <p> * Programs created by <code>ASTParser</code> from a source document can be * serialized after arbitrary modifications with minimal loss of original * formatting. Here is an example: * * <pre> * * Document doc = new Document("<?\n class X {} \n echo 'hello world';\n ?>"); * ASTParser parser = ASTParser.newParser(AST.PHP5); * parser.setSource(doc.get().toCharArray()); * Program program = parser.createAST(null); * program.recordModifications(); * AST ast = program.getAST(); * EchoStatement echo = ast.newEchoStatement(); * echo.setExpression(ast.newScalar("hello world"); * program.statements().add(echo); * TextEdit edits = program.rewrite(document, null); * UndoEdit undo = edits.apply(document); * * </pre> * * See also {@link ASTRewrite} for an alternative way to describe and serialize * changes to a read-only AST. * </p> * <p> * Clients may create instances of this class using {@link #newAST(int)}, but * this class is not intended to be subclassed. * </p> * * @see ASTParser * @see ASTNode * @since 2.0 */ @SuppressWarnings({"rawtypes"}) public class AST { /** * The scanner capabilities to the AST - all has package access to enable * ASTParser access */ final AstLexer lexer; final lr_parser parser; final PHPVersion apiLevel; final boolean useASPTags; /** * The event handler for this AST. Initially an event handler that does not * nothing. * * @since 3.0 */ private NodeEventHandler eventHandler = new NodeEventHandler(); /** * Internal modification count; initially 0; increases monotonically <b>by * one or more</b> as the AST is successively modified. */ private long modificationCount = 0; /** * Internal original modification count; value is equals to <code> * modificationCount</code> at the end of the parse (<code>ASTParser * </code>). If this ast is not created with a parser then value is 0. * * @since 3.0 */ private long originalModificationCount = 0; /** * When disableEvents > 0, events are not reported and the modification * count stays fixed. * <p> * This mechanism is used in lazy initialization of a node to prevent events * from being reported for the modification of the node as well as for the * creation of the missing child. * </p> * * @since 3.0 */ private int disableEvents = 0; /** * Internal object unique to the AST instance. Readers must synchronize on * this object when the modifying instance fields. * * @since 3.0 */ private final Object internalASTLock = new Object(); /** * Default value of <code>flag<code> when a new node is created. */ private int defaultNodeFlag = 0; /** * Internal ast rewriter used to record ast modification when record mode is * enabled. */ InternalASTRewrite rewriter; // Error reporting private List<ASTError> reportedErrors; // Can be an IResource or an IUniformResource, in case we are dealing with a script outside the workspace. private Object resource; private BuildProblemReporter problemReporter; /** * The binding resolver for this AST. Initially a binding resolver that does * not resolve names at all. */ // private BindingResolver resolver = new BindingResolver(); /** * Creates a new AST. */ public AST(Reader reader, PHPVersion apiLevel, boolean aspTagsAsPhp, boolean useShortTags) throws IOException { this(reader, apiLevel, aspTagsAsPhp, useShortTags, null, BuildType.RECONCILE); } /** * Creates a new AST. This constructor get the IResource reference that this AST is created for. * * @param reader * @param apiLevel * @param aspTagsAsPhp * @param resource * An {@link IResource} that this AST is being created for, or an IUniformResource, in case we are * dealing with a script outside the workspace (may be null) - [Aptana Mod] * @throws IOException */ public AST(Reader reader, PHPVersion apiLevel, boolean aspTagsAsPhp, boolean useShortTags, Object resource, BuildType type) throws IOException { this.resource = resource; if (this.resource != null) { problemReporter = new BuildProblemReporter(this.resource, type); } this.useASPTags = aspTagsAsPhp; this.apiLevel = apiLevel; this.lexer = getLexerInstance(reader, apiLevel, aspTagsAsPhp, useShortTags); this.parser = getParserInstance(apiLevel, this.lexer); this.reportedErrors = new ArrayList<ASTError>(); } /** * Clear the errors in the AST */ public void clearErrors() { if (!reportedErrors.isEmpty()){ // Create a new list, just in case there is some other // thread that is traversing the previous list at the moment. reportedErrors = new ArrayList<ASTError>(); } } /** * Returns true in case errors where reported for this AST.<br> * [XXX: Aptana Mod] * @return True, in case this AST has errors; False, otherwise. */ public boolean hasErrors() { return !reportedErrors.isEmpty(); } /** * Write the errors into the resource markers and remove the problem reporter. */ public void flushErrors() { if (problemReporter != null) { problemReporter.flush(); problemReporter = null; clearErrors(); } } /** * Returns a list of the reported ASTErrors.<br> * These errors are different then the ones held in the AST as tree nodes. * There can be more reported ASTErrors then then ones exist in the tree. * [XXX: Aptana Mod] * * @return a list of reported ASTErrors. */ public List<ASTError> getErrors() { return reportedErrors; } /** * Returns the IResource that this AST was created for. * * @return An {@link IResource}, or an {@link IUniformResource}. Can be null. */ public Object getResource() { return resource; } /** * Constructs a scanner from a given reader * @param reader * @param phpVersion * @param aspTagsAsPhp * @return * @throws IOException */ private AstLexer getLexerInstance(Reader reader, PHPVersion phpVersion, boolean aspTagsAsPhp, boolean useShortTags) throws IOException { if (PHPVersion.PHP4 == phpVersion) { final AstLexer lexer4 = getLexer4(reader); lexer4.setUseAspTagsAsPhp(aspTagsAsPhp); lexer4.setUseShortTags(useShortTags); return lexer4; } else if (PHPVersion.PHP5 == phpVersion) { final AstLexer lexer5 = getLexer5(reader); lexer5.setUseAspTagsAsPhp(aspTagsAsPhp); lexer5.setUseShortTags(useShortTags); return lexer5; } else if (PHPVersion.PHP5_3 == phpVersion) { final AstLexer lexer53 = getLexer53(reader); lexer53.setUseAspTagsAsPhp(aspTagsAsPhp); lexer53.setUseShortTags(useShortTags); return lexer53; } else if (PHPVersion.PHP5_4 == phpVersion) { final AstLexer lexer54 = getLexer54(reader); lexer54.setUseAspTagsAsPhp(aspTagsAsPhp); lexer54.setUseShortTags(useShortTags); return lexer54; } else { throw new IllegalArgumentException(CoreMessages .getString("ASTParser_1") //$NON-NLS-1$ + phpVersion); } } private AstLexer getLexer54(Reader reader) throws IOException { final org2.eclipse.php.internal.core.ast.scanner.php54.PhpAstLexer phpAstLexer5 = new org2.eclipse.php.internal.core.ast.scanner.php54.PhpAstLexer( reader); phpAstLexer5.setAST(this); return phpAstLexer5; } private AstLexer getLexer53(Reader reader) throws IOException { final org2.eclipse.php.internal.core.ast.scanner.php53.PhpAstLexer phpAstLexer5 = new org2.eclipse.php.internal.core.ast.scanner.php53.PhpAstLexer( reader); phpAstLexer5.setAST(this); return phpAstLexer5; } private AstLexer getLexer5(Reader reader) throws IOException { final org2.eclipse.php.internal.core.ast.scanner.php5.PhpAstLexer phpAstLexer5 = new org2.eclipse.php.internal.core.ast.scanner.php5.PhpAstLexer( reader); phpAstLexer5.setAST(this); return phpAstLexer5; } private AstLexer getLexer4(Reader reader) throws IOException { final org2.eclipse.php.internal.core.ast.scanner.php4.PhpAstLexer phpAstLexer4 = new org2.eclipse.php.internal.core.ast.scanner.php4.PhpAstLexer( reader); phpAstLexer4.setAST(this); return phpAstLexer4; } private AbstractASTParser getParserInstance(PHPVersion phpVersion, Scanner lexer) { AbstractASTParser parser; if (PHPVersion.PHP4 == phpVersion) { parser = new org2.eclipse.php.internal.core.ast.scanner.php4.PhpAstParser( lexer); } else if (PHPVersion.PHP5 == phpVersion) { parser = new org2.eclipse.php.internal.core.ast.scanner.php5.PhpAstParser( lexer); } else if (PHPVersion.PHP5_3 == phpVersion) { parser = new org2.eclipse.php.internal.core.ast.scanner.php53.PhpAstParser( lexer); } else if (PHPVersion.PHP5_4 == phpVersion) { parser = new org2.eclipse.php.internal.core.ast.scanner.php54.PhpAstParser( lexer); } else { throw new IllegalArgumentException(CoreMessages.getString("ASTParser_1") + phpVersion); //$NON-NLS-1$ } parser.setAST(this); if (problemReporter != null) { parser.setProblemReporter(problemReporter); } return parser; } /** * Returns the modification count for this AST. The modification count is a * non-negative value that increases (by 1 or perhaps by more) as this AST * or its nodes are changed. The initial value is unspecified. * <p> * The following things count as modifying an AST: * <ul> * <li>creating a new node owned by this AST,</li> * <li>adding a child to a node owned by this AST,</li> * <li>removing a child from a node owned by this AST,</li> * <li>setting a non-node attribute of a node owned by this AST.</li> * </ul> * </p> * Operations which do not entail creating or modifying existing nodes do * not increase the modification count. * <p> * N.B. This method may be called several times in the course of a single * client operation. The only promise is that the modification count * increases monotonically as the AST or its nodes change; there is no * promise that a modifying operation increases the count by exactly 1. * </p> * * @return the current value (non-negative) of the modification counter of * this AST */ public long modificationCount() { return this.modificationCount; } /** * Indicates that this AST is about to be modified. * <p> * The following things count as modifying an AST: * <ul> * <li>creating a new node owned by this AST</li> * <li>adding a child to a node owned by this AST</li> * <li>removing a child from a node owned by this AST</li> * <li>setting a non-node attribute of a node owned by this AST</li>. * </ul> * </p> * <p> * N.B. This method may be called several times in the course of a single * client operation. * </p> */ void modifying() { // when this method is called during lazy init, events are disabled // and the modification count will not be increased if (this.disableEvents > 0) { return; } // increase the modification count this.modificationCount++; } /** * Disable events. This method is thread-safe for AST readers. * * @see #reenableEvents() * @since 3.0 */ final void disableEvents() { synchronized (this.internalASTLock) { // guard against concurrent access by another reader this.disableEvents++; } // while disableEvents > 0 no events will be reported, and mod count // will stay fixed } /** * Reenable events. This method is thread-safe for AST readers. * * @see #disableEvents() * @since 3.0 */ final void reenableEvents() { synchronized (this.internalASTLock) { // guard against concurrent access by another reader this.disableEvents--; } } /** * Reports that the given node is about to lose a child. * * @param node * the node about to be modified * @param child * the node about to be removed * @param property * the child or child list property descriptor * @since 3.0 */ void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) { // IMPORTANT: this method is called by readers during lazy init synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE DEL]"); return; } else { disableEvents(); } } try { this.eventHandler.preRemoveChildEvent(node, child, property); // N.B. even if event handler blows up, the AST is not // corrupted since node has not been changed yet } finally { reenableEvents(); } } /** * Reports that the given node jsut lost a child. * * @param node * the node that was modified * @param child * the child node that was removed * @param property * the child or child list property descriptor * @since 3.0 */ void postRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) { // IMPORTANT: this method is called by readers during lazy init synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE DEL]"); return; } else { disableEvents(); } } try { this.eventHandler.postRemoveChildEvent(node, child, property); // N.B. even if event handler blows up, the AST is not // corrupted since node has not been changed yet } finally { reenableEvents(); } } /** * Reports that the given node is about have a child replaced. * * @param node * the node about to be modified * @param child * the child node about to be removed * @param newChild * the replacement child * @param property * the child or child list property descriptor * @since 3.0 */ void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) { // IMPORTANT: this method is called by readers during lazy init synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE REP]"); return; } else { disableEvents(); } } try { this.eventHandler.preReplaceChildEvent(node, child, newChild, property); // N.B. even if event handler blows up, the AST is not // corrupted since node has not been changed yet } finally { reenableEvents(); } } /** * Reports that the given node has just had a child replaced. * * @param node * the node modified * @param child * the child removed * @param newChild * the replacement child * @param property * the child or child list property descriptor * @since 3.0 */ void postReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) { // IMPORTANT: this method is called by readers during lazy init synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE REP]"); return; } else { disableEvents(); } } try { this.eventHandler.postReplaceChildEvent(node, child, newChild, property); // N.B. even if event handler blows up, the AST is not // corrupted since node has not been changed yet } finally { reenableEvents(); } } /** * Reports that the given node is about to gain a child. * * @param node * the node that to be modified * @param child * the node that to be added as a child * @param property * the child or child list property descriptor * @since 3.0 */ void preAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) { // IMPORTANT: this method is called by readers during lazy init synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE ADD]"); return; } else { disableEvents(); } } try { this.eventHandler.preAddChildEvent(node, child, property); // N.B. even if event handler blows up, the AST is not // corrupted since node has already been changed } finally { reenableEvents(); } } /** * Reports that the given node has just gained a child. * * @param node * the node that was modified * @param child * the node that was added as a child * @param property * the child or child list property descriptor * @since 3.0 */ void postAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) { // IMPORTANT: this method is called by readers during lazy init synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE ADD]"); return; } else { disableEvents(); } } try { this.eventHandler.postAddChildEvent(node, child, property); // N.B. even if event handler blows up, the AST is not // corrupted since node has already been changed } finally { reenableEvents(); } } /** * Reports that the given node is about to change the value of a non-child * property. * * @param node * the node to be modified * @param property * the property descriptor * @since 3.0 */ void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) { // IMPORTANT: this method is called by readers during lazy init synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE CHANGE]"); return; } else { disableEvents(); } } try { this.eventHandler.preValueChangeEvent(node, property); // N.B. even if event handler blows up, the AST is not // corrupted since node has already been changed } finally { reenableEvents(); } } /** * Reports that the given node has just changed the value of a non-child * property. * * @param node * the node that was modified * @param property * the property descriptor * @since 3.0 */ void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) { // IMPORTANT: this method is called by readers during lazy init synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE CHANGE]"); return; } else { disableEvents(); } } try { this.eventHandler.postValueChangeEvent(node, property); // N.B. even if event handler blows up, the AST is not // corrupted since node has already been changed } finally { reenableEvents(); } } /** * Reports that the given node is about to be cloned. * * @param node * the node to be cloned * @since 3.0 */ void preCloneNodeEvent(ASTNode node) { synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE CLONE]"); return; } else { disableEvents(); } } try { this.eventHandler.preCloneNodeEvent(node); // N.B. even if event handler blows up, the AST is not // corrupted since node has already been changed } finally { reenableEvents(); } } /** * Reports that the given node has just been cloned. * * @param node * the node that was cloned * @param clone * the clone of <code>node</code> * @since 3.0 */ void postCloneNodeEvent(ASTNode node, ASTNode clone) { synchronized (this.internalASTLock) { // guard against concurrent access by a reader doing lazy init if (this.disableEvents > 0) { // doing lazy init OR already processing an event // System.out.println("[BOUNCE CLONE]"); return; } else { disableEvents(); } } try { this.eventHandler.postCloneNodeEvent(node, clone); // N.B. even if event handler blows up, the AST is not // corrupted since node has already been changed } finally { reenableEvents(); } } // Aptana mod //public BindingResolver getBindingResolver() { // return this.resolver; //} /** * Returns the event handler for this AST. * * @return the event handler for this AST * @since 3.0 */ NodeEventHandler getEventHandler() { return this.eventHandler; } /** * Sets the event handler for this AST. * * @param eventHandler * the event handler for this AST * @since 3.0 */ void setEventHandler(NodeEventHandler eventHandler) { if (this.eventHandler == null) { throw new IllegalArgumentException(); } this.eventHandler = eventHandler; } /** * Returns default node flags of new nodes of this AST. * * @return the default node flags of new nodes of this AST * @since 3.0 */ int getDefaultNodeFlag() { return this.defaultNodeFlag; } /** * Sets default node flags of new nodes of this AST. * * @param flag * node flags of new nodes of this AST * @since 3.0 */ void setDefaultNodeFlag(int flag) { this.defaultNodeFlag = flag; } /** * Set <code>originalModificationCount</code> to the current modification * count * * @since 3.0 */ void setOriginalModificationCount(long count) { this.originalModificationCount = count; } /** * Returns the type binding for a "well known" type. * <p> * Note that bindings are generally unavailable unless requested when the * AST is being built. * </p> * <p> * The following type names are supported: * <ul> * <li><code>"boolean"</code></li> * <li><code>"byte"</code></li> * <li><code>"char"</code></li> * <li><code>"double"</code></li> * <li><code>"float"</code></li> * <li><code>"int"</code></li> * <li><code>"long"</code></li> * <li><code>"short"</code></li> * <li><code>"void"</code></li> * </ul> * </p> * * @param name * the name of a well known type * @return the corresponding type binding, or <code>null</code> if the named * type is not considered well known or if no binding can be found * for it */ public ITypeBinding resolveWellKnownType(String name) { // if (name == null) { // return null; // } // return getBindingResolver().resolveWellKnownType(name); // Aptana mod return null; } /** * Sets the binding resolver for this AST. * * @param resolver * the new binding resolver for this AST */ // Aptana mod // void setBindingResolver(BindingResolver resolver) { // if (resolver == null) { // throw new IllegalArgumentException(); // } // this.resolver = resolver; // } /** * Checks that this AST operation is not used when building level JLS2 ASTs. * * @exception UnsupportedOperationException * @since 3.0 */ void unsupportedIn2() { if (this.apiLevel == PHPVersion.PHP4) { throw new UnsupportedOperationException( "Operation not supported in JLS2 AST"); //$NON-NLS-1$ } } /** * Checks that this AST operation is only used when building level JLS2 * ASTs. * * @exception UnsupportedOperationException * @since 3.0 */ void supportedOnlyIn2() { if (this.apiLevel != PHPVersion.PHP4) { throw new UnsupportedOperationException( "Operation not supported in JLS2 AST"); //$NON-NLS-1$ } } /** * new Class[] {AST.class} * * @since 3.0 */ private static final Class[] AST_CLASS = new Class[] { AST.class }; /** * new Object[] {this} * * @since 3.0 */ private final Object[] THIS_AST = new Object[] { this }; /* * Must not collide with a value for IProgram constants */ static final int RESOLVED_BINDINGS = 0x80000000; /** * Tag bit value. This represents internal state of the tree. */ private int bits; /** * Creates an unparented node of the given node class (non-abstract subclass * of {@link ASTNode}). * * @param nodeClass * AST node class * @return a new unparented node owned by this AST * @exception IllegalArgumentException * if <code>nodeClass</code> is <code>null</code> or is not a * concrete node type class * @since 3.0 */ public ASTNode createInstance(Class nodeClass) { if (nodeClass == null) { throw new IllegalArgumentException(); } try { // invoke constructor with signature Foo(AST) Constructor c = nodeClass.getDeclaredConstructor(AST_CLASS); Object result = c.newInstance(this.THIS_AST); return (ASTNode) result; } catch (NoSuchMethodException e) { // all AST node classes have a Foo(AST) constructor // therefore nodeClass is not legit throw new IllegalArgumentException(); } catch (InstantiationException e) { // all concrete AST node classes can be instantiated // therefore nodeClass is not legit throw new IllegalArgumentException(); } catch (IllegalAccessException e) { // all AST node classes have an accessible Foo(AST) constructor // therefore nodeClass is not legit throw new IllegalArgumentException(); } catch (InvocationTargetException e) { // concrete AST node classes do not die in the constructor // therefore nodeClass is not legit throw new IllegalArgumentException(); } } /** * Creates an unparented node of the given node type. This convenience * method is equivalent to: * * <pre> * createInstance(ASTNode.nodeClassForType(nodeType)) * </pre> * * @param nodeType * AST node type, one of the node type constants declared on * {@link ASTNode} * @return a new unparented node owned by this AST * @exception IllegalArgumentException * if <code>nodeType</code> is not a legal AST node type * @since 3.0 */ public ASTNode createInstance(int nodeType) { // nodeClassForType throws IllegalArgumentException if nodeType is bogus Class nodeClass = ASTNode.nodeClassForType(nodeType); return createInstance(nodeClass); } // =============================== TYPES =========================== /** * Enables the recording of changes to the given compilation unit and its * descendents. The compilation unit must have been created by * <code>ASTParser</code> and still be in its original state. Once recording * is on, arbitrary changes to the subtree rooted at the compilation unit * are recorded internally. Once the modification has been completed, call * <code>rewrite</code> to get an object representing the corresponding * edits to the original source code string. * * @exception IllegalArgumentException * if this compilation unit is marked as unmodifiable, or if * this compilation unit has already been tampered with, or * if recording has already been enabled, or if * <code>root</code> is not owned by this AST * @see Program#recordModifications() * @since 3.0 */ void recordModifications(Program root) { if (this.modificationCount != this.originalModificationCount) { throw new IllegalArgumentException("AST is already modified"); //$NON-NLS-1$ } else if (this.rewriter != null) { throw new IllegalArgumentException( "AST modifications are already recorded"); //$NON-NLS-1$ } else if ((root.getFlags() & ASTNode.PROTECT) != 0) { throw new IllegalArgumentException("Root node is unmodifiable"); //$NON-NLS-1$ } else if (root.getAST() != this) { throw new IllegalArgumentException( "Root node is not owned by this ast"); //$NON-NLS-1$ } this.rewriter = new InternalASTRewrite(root); this.setEventHandler(this.rewriter); } /** * Converts all modifications recorded into an object representing the * corresponding text edits to the given document containing the original * source code for the compilation unit that gave rise to this AST. * * @param document * original document containing source code for the compilation * unit * @param options * the table of formatter options (key type: <code>String</code>; * value type: <code>String</code>); or <code>null</code> to use * the standard global options {@link PHPCore#getOptions() * PHPCore.getOptions()}. * @return text edit object describing the changes to the document * corresponding to the recorded AST modifications * @exception IllegalArgumentException * if the document passed is <code>null</code> or does not * correspond to this AST * @exception IllegalStateException * if <code>recordModifications</code> was not called to * enable recording * @see Program#rewrite(IDocument, Map) * @since 3.0 */ TextEdit rewrite(IDocument document, Map options) { if (document == null) { throw new IllegalArgumentException(); } if (this.rewriter == null) { throw new IllegalStateException( "Modifications record is not enabled"); //$NON-NLS-1$ } return this.rewriter.rewriteAST(document, options); } /** * Returns true if the ast tree was created with bindings, false otherwise * * @return true if the ast tree was created with bindings, false otherwise * @since 3.3 */ public boolean hasResolvedBindings() { return (this.bits & RESOLVED_BINDINGS) != 0; } /** * Returns true if the ast tree was created with statements recovery, false * otherwise * * @return true if the ast tree was created with statements recovery, false * otherwise * @since 3.3 */ /* * public boolean hasStatementsRecovery() { return (this.bits & * IProgram.ENABLE_STATEMENTS_RECOVERY) != 0; } */ /** * Returns true if the ast tree was created with bindings recovery, false * otherwise * * @return true if the ast tree was created with bindings recovery, false * otherwise * @since 3.3 */ /* * public boolean hasBindingsRecovery() { return (this.bits & * IProgram.ENABLE_BINDINGS_RECOVERY) != 0; } */ void setFlag(int newValue) { this.bits |= newValue; } /** * @return The lexer used by this AST */ public AstLexer lexer() { return lexer; } /** * @return The parser used by this AST */ public lr_parser parser() { return parser; } /** * @return The API level used by this AST */ public PHPVersion apiLevel() { return apiLevel; } /** * @return true if this AST "permits" ASP tags */ public boolean useASPTags() { return useASPTags; } /** * @return true if this AST "permits" ASP tags * @throws IOException */ public void setSource(Reader reader) throws IOException { if (reader == null) { throw new IllegalArgumentException(); } this.lexer.yyreset(reader); this.lexer.resetCommentList(); this.parser.setScanner(this.lexer); } /** * Creates a new {@link ArrayAccess}. * * @return a new ArrayAccess. */ public ArrayAccess newArrayAccess() { ArrayAccess arrayAccess = new ArrayAccess(this); return arrayAccess; } /** * Creates a new {@link ArrayAccess}. * * @param variableName * @param index * @param arrayType * @return a new ArrayAccess */ public ArrayAccess newArrayAccess(VariableBase variableName, Expression index, int arrayType) { ArrayAccess arrayAccess = new ArrayAccess(this); arrayAccess.setName(variableName); arrayAccess.setIndex(index); arrayAccess.setArrayType(arrayType); return arrayAccess; } /** * Creates a new {@link ArrayAccess}. Default array type is VARIABLE_ARRAY * * @param variableName * @param index * @return a new ArrayAccess */ public ArrayAccess newArrayAccess(VariableBase variableName, Expression index) { ArrayAccess arrayAccess = new ArrayAccess(this); arrayAccess.setName(variableName); arrayAccess.setIndex(index); arrayAccess.setArrayType(ArrayAccess.VARIABLE_ARRAY); return arrayAccess; } /** * Creates a new {@link ArrayCreation}. * * @return a new ArrayCreation. */ public ArrayCreation newArrayCreation() { ArrayCreation arrayCreation = new ArrayCreation(this); return arrayCreation; } /** * Creates a new {@link ArrayCreation}. * * @param elements * - List of {@link ArrayElement} * @return a new ArrayCreation. */ public ArrayCreation newArrayCreation(List<ArrayElement> elements) { ArrayCreation arrayCreation = new ArrayCreation(this); arrayCreation.elements().addAll(elements); return arrayCreation; } /** * Creates a new {@link ArrayElement}. * * @return a new ArrayElement. */ public ArrayElement newArrayElement() { ArrayElement arrayElement = new ArrayElement(this); return arrayElement; } /** * Creates a new {@link ArrayElement}. * * @param key * - an {@link Expression} rapresenting the element key * @param value * - an {@link Expression} rapresenting the element value * @return a new ArrayElement. */ public ArrayElement newArrayElement(Expression key, Expression value) { ArrayElement arrayElement = new ArrayElement(this); arrayElement.setKey(key); arrayElement.setValue(value); return arrayElement; } /** * Creates a new {@link Assignment}. * * @return A new Assignment. */ public Assignment newAssignment() { Assignment assignment = new Assignment(this); return assignment; } /** * Creates a new {@link Assignment}. * * @param leftHandSide * A {@link VariableBase} * @param operator * The assignment operator * @param rightHandSide * An {@link Expression} * @return A new Assignment. */ public Assignment newAssignment(VariableBase leftHandSide, int operator, Expression rightHandSide) { Assignment assignment = new Assignment(this); assignment.setLeftHandSide(leftHandSide); assignment.setOperator(operator); assignment.setRightHandSide(rightHandSide); return assignment; } /** * Creates a new {@link ASTError}. * * @return A new ASTError. */ public ASTError newASTError() { ASTError astError = new ASTError(this); return astError; } /** * Creates a new {@link BackTickExpression}. * * @return A new BackTickExpression. */ public BackTickExpression newBackTickExpression() { BackTickExpression backTickExpression = new BackTickExpression(this); return backTickExpression; } /** * Creates a new {@link BackTickExpression}. * * @param expressions * - List of {@link Expression} * @return A new BackTickExpression. */ public BackTickExpression newBackTickExpression(List<Expression> expressions) { BackTickExpression backTickExpression = new BackTickExpression(this); backTickExpression.expressions().addAll(expressions); return backTickExpression; } /** * Creates an unparented block node owned by this AST, for an empty list of * statements. * * @return a new unparented, empty curly block node */ public Block newBlock() { Block block = new Block(this); block.setIsCurly(true); return block; } /** * Creates an unparented block node owned by this AST, for an empty list of * statements. * * @param statements * - List of {@link Statement} * @return a new unparented, empty block node */ public Block newBlock(List<Statement> statements) { Block block = new Block(this); block.statements().addAll(statements); block.setIsCurly(true); return block; } /** * Creates a new {@link BreakStatement}. * * @return A new BreakStatement. */ public BreakStatement newBreakStatement() { BreakStatement breakStatement = new BreakStatement(this); return breakStatement; } /** * Creates a new {@link BreakStatement}. * * @param expression * . * @return A new BreakStatement. */ public BreakStatement newBreakStatement(Expression expression) { BreakStatement breakStatement = new BreakStatement(this); breakStatement.setExpression(expression); return breakStatement; } /** * Creates a new {@link CastExpression}. * * @return A new CastExpression. */ public CastExpression newCastExpression() { CastExpression castExpression = new CastExpression(this); return castExpression; } /** * Creates a new {@link CastExpression}. * * @param expression * @param castType * @return A new CastExpression. */ public CastExpression newCastExpression(Expression expression, int castType) { CastExpression castExpression = new CastExpression(this); castExpression.setExpression(expression); castExpression.setCastingType(castType); return castExpression; } /** * Creates a new {@link CatchClause}. * * @return A new CatchClause. */ public CatchClause newCatchClause() { CatchClause catchClause = new CatchClause(this); return catchClause; } /** * Creates a new {@link CatchClause}. * * @param className * @param variable * @param statement * @return A new CatchClause. */ public CatchClause newCatchClause(Identifier className, Variable variable, Block statement) { CatchClause catchClause = new CatchClause(this); catchClause.setClassName(className); catchClause.setVariable(variable); catchClause.setBody(statement); return catchClause; } /** * Creates a new {@link ConstantDeclaration}. * * @return A new ClassConstantDeclaration. */ public ConstantDeclaration newClassConstantDeclaration() { ConstantDeclaration classConstantDeclaration = new ConstantDeclaration( this); return classConstantDeclaration; } /** * Creates a new {@link ConstantDeclaration}. * * @param names * @param initializers * @return A new ClassConstantDeclaration. */ public ConstantDeclaration newClassConstantDeclaration( List<Identifier> names, List<Expression> initializers) { ConstantDeclaration classConstantDeclaration = new ConstantDeclaration( this); classConstantDeclaration.initializers().addAll(initializers); classConstantDeclaration.names().addAll(names); return classConstantDeclaration; } /** * Creates a new {@link ClassDeclaration}. * * @return A new ClassDeclaration. */ public ClassDeclaration newClassDeclaration() { ClassDeclaration classDeclaration = new ClassDeclaration(this); return classDeclaration; } /** * Creates a new {@link ClassDeclaration}. * * @param modifier * @param className * @param superClass * @param interfaces * @param body * @return A new ClassDeclaration. */ public ClassDeclaration newClassDeclaration(int modifier, String className, String superClass, List<Identifier> interfaces, Block body) { ClassDeclaration classDeclaration = new ClassDeclaration(this); classDeclaration.setModifier(modifier); classDeclaration.setName(newIdentifier(className)); if (superClass != null) { classDeclaration.setSuperClass(newIdentifier(superClass)); } else { classDeclaration.setSuperClass(null); } classDeclaration.interfaces().addAll(interfaces); classDeclaration.setBody(body); return classDeclaration; } /** * Creates a new {@link ClassInstanceCreation}. * * @return A new ClassInstanceCreation. */ public ClassInstanceCreation newClassInstanceCreation() { ClassInstanceCreation classInstanceCreation = new ClassInstanceCreation( this); return classInstanceCreation; } /** * Creates a new {@link ClassInstanceCreation}. * * @param className * @param ctorParams * @return A new ClassInstanceCreation. */ public ClassInstanceCreation newClassInstanceCreation(ClassName className, List<Expression> ctorParams) { ClassInstanceCreation classInstanceCreation = new ClassInstanceCreation( this); classInstanceCreation.setClassName(className); classInstanceCreation.ctorParams().addAll(ctorParams); return classInstanceCreation; } /** * Creates a new {@link ClassName}. * * @return A new ClassName. */ public ClassName newClassName() { ClassName className = new ClassName(this); return className; } /** * Creates a new {@link ClassName}. * * @param name * @return A new ClassName. */ public ClassName newClassName(Expression name) { ClassName className = new ClassName(this); className.setClassName(name); return className; } /** * Creates a new {@link CloneExpression}. * * @return A new CloneExpression. */ public CloneExpression newCloneExpression() { CloneExpression cloneExpression = new CloneExpression(this); return cloneExpression; } /** * Creates a new {@link CloneExpression}. * * @param expr * @return A new CloneExpression. */ public CloneExpression newCloneExpression(Expression expr) { CloneExpression cloneExpression = new CloneExpression(this); cloneExpression.setExpression(expr); return cloneExpression; } /** * Creates a new {@link Comment}. * * @return A new Comment. */ public Comment newComment() { Comment comment = new Comment(this); return comment; } /** * Creates a new {@link Comment}. * * @param commentType * @return A new Comment. */ public Comment newComment(int commentType) { Comment comment = new Comment(this); comment.setCommentType(commentType); return comment; } /** * Creates a new {@link ConditionalExpression}. * * @return A new ConditionalExpression. */ public ConditionalExpression newConditionalExpression() { ConditionalExpression conditionalExpression = new ConditionalExpression( this); return conditionalExpression; } /** * Creates a new {@link ConditionalExpression}. * * @param condition * @param ifTrue * @param ifFalse * @return A new ConditionalExpression. */ public ConditionalExpression newConditionalExpression(Expression condition, Expression ifTrue, Expression ifFalse) { ConditionalExpression conditionalExpression = new ConditionalExpression( this); conditionalExpression.setCondition(condition); conditionalExpression.setIfTrue(ifTrue); conditionalExpression.setIfFalse(ifFalse); return conditionalExpression; } /** * Creates a new {@link ContinueStatement}. * * @return A new ContinueStatement. */ public ContinueStatement newContinueStatement() { ContinueStatement continueStatement = new ContinueStatement(this); return continueStatement; } /** * Creates a new {@link ContinueStatement}. * * @param expr * @return A new ContinueStatement. */ public ContinueStatement newContinueStatement(Expression expr) { ContinueStatement continueStatement = new ContinueStatement(this); continueStatement.setExpression(expr); return continueStatement; } /** * Creates a new {@link DeclareStatement}. * * @param directiveNames * @param directiveValues * @param body * @return A new DeclareStatement. */ public DeclareStatement newDeclareStatement( List<Identifier> directiveNames, List<Expression> directiveValues, Statement body) { DeclareStatement declareStatement = new DeclareStatement(this); declareStatement.directiveNames().addAll(directiveNames); declareStatement.directiveValues().addAll(directiveValues); declareStatement.setBody(body); return declareStatement; } /** * Creates a new {@link DoStatement}. * * @return A new DoStatement. */ public DoStatement newDoStatement() { DoStatement doStatement = new DoStatement(this); return doStatement; } /** * Creates a new {@link DoStatement}. * * @param condition * @param body * @return A new DoStatement. */ public DoStatement newDoStatement(Expression condition, Statement body) { DoStatement doStatement = new DoStatement(this); doStatement.setCondition(condition); doStatement.setBody(body); return doStatement; } /** * Creates a new {@link EchoStatement}. * * @return A new EchoStatement. */ public EchoStatement newEchoStatement() { EchoStatement echoStatement = new EchoStatement(this); return echoStatement; } /** * Creates a new {@link EchoStatement}. * * @param expressions * @return A new EchoStatement. */ public EchoStatement newEchoStatement(List<Expression> expressions) { EchoStatement echoStatement = new EchoStatement(this); echoStatement.expressions().addAll(expressions); return echoStatement; } /** * Creates a new {@link EchoStatement} with a given {@link Expression}. * * @param expression * An {@link Expression} to set into the returned * {@link EchoStatement}. * @return A new EchoStatement with the given Expression. */ public EchoStatement newEchoStatement(Expression expression) { EchoStatement echoStatement = new EchoStatement(this); echoStatement.expressions().add(expression); return echoStatement; } /** * Creates a new {@link EmptyStatement}. * * @return A new EmptyStatement. */ public EmptyStatement newEmptyStatement() { EmptyStatement emptyStatement = new EmptyStatement(this); return emptyStatement; } /** * Creates a new {@link ExpressionStatement}. * * @return A new ExpressionStatement. */ public ExpressionStatement newExpressionStatement() { ExpressionStatement expressionStatement = new ExpressionStatement(this); return expressionStatement; } /** * Creates a new {@link ExpressionStatement} with a given {@link Expression} * as an expression. * * @param identifier * The {@link Expression} that is the expression of the * statement. * @return A new ExpressionStatement */ public ExpressionStatement newExpressionStatement(Expression expression) { ExpressionStatement statement = newExpressionStatement(); statement.setExpression(expression); return statement; } /** * Creates a new {@link FieldAccess}. * * @return A new FieldAccess. */ public FieldAccess newFieldAccess() { FieldAccess fieldAccess = new FieldAccess(this); return fieldAccess; } /** * Creates a new {@link FieldAccess}. * * @param dispatcher * @param field * @return A new FieldAccess. */ public FieldAccess newFieldAccess(VariableBase dispatcher, Variable field) { FieldAccess fieldAccess = new FieldAccess(this); fieldAccess.setDispatcher(dispatcher); fieldAccess.setField(field); return fieldAccess; } /** * Creates a new {@link FieldsDeclaration}. * * @return A new FieldsDeclaration. */ public FieldsDeclaration newFieldsDeclaration() { FieldsDeclaration fieldsDeclaration = new FieldsDeclaration(this); return fieldsDeclaration; } /** * Creates a new {@link FieldsDeclaration}. * * @param modifier * @param variablesAndDefaults * @return A new FieldsDeclaration. */ public FieldsDeclaration newFieldsDeclaration(int modifier, List<SingleFieldDeclaration> variablesAndDefaults) { FieldsDeclaration fieldsDeclaration = new FieldsDeclaration(this); fieldsDeclaration.setModifier(modifier); List<SingleFieldDeclaration> fields = fieldsDeclaration.fields(); fields.addAll(variablesAndDefaults); return fieldsDeclaration; } /** * Creates a new {@link ForEachStatement}. * * @return A new ForEachStatement. */ public ForEachStatement newForEachStatement() { ForEachStatement forEachStatement = new ForEachStatement(this); return forEachStatement; } /** * Creates a new {@link ForEachStatement}. * * @param expression * @param key * @param value * @param statement * @return A new ForEachStatement. */ public ForEachStatement newForEachStatement(Expression expression, Expression key, Expression value, Statement statement) { ForEachStatement forEachStatement = new ForEachStatement(this); forEachStatement.setExpression(expression); forEachStatement.setKey(key); forEachStatement.setValue(value); forEachStatement.setStatement(statement); return forEachStatement; } /** * Creates a new {@link FormalParameter}. * * @return A new FormalParameter. */ public FormalParameter newFormalParameter() { FormalParameter formalParameter = new FormalParameter(this); return formalParameter; } /** * Creates a new {@link FormalParameter}. * * @param type * @param parameterName * @param defaultValue * @param isMandatory * The mandatory field is only effective when the API level is * AST.PHP4 * @return A new FormalParameter. */ public FormalParameter newFormalParameter(Identifier type, Expression parameterName, Expression defaultValue, boolean isMandatory) { FormalParameter formalParameter = new FormalParameter(this); formalParameter.setParameterType(type); formalParameter.setParameterName(parameterName); formalParameter.setDefaultValue(defaultValue); if (apiLevel() == PHPVersion.PHP4) { formalParameter.setIsMandatory(isMandatory); } return formalParameter; } /** * Creates a new {@link ForStatement}. * * @return A new ForStatement. */ public ForStatement newForStatement() { ForStatement forStatement = new ForStatement(this); return forStatement; } /** * Creates a new {@link ForStatement}. * * @param initializers * @param conditions * @param updaters * @param body * @return A new ForStatement. */ public ForStatement newForStatement(List<Expression> initializers, List<Expression> conditions, List<Expression> updaters, Statement body) { ForStatement forStatement = new ForStatement(this); forStatement.initializers().addAll(initializers); forStatement.updaters().addAll(updaters); forStatement.conditions().addAll(conditions); forStatement.setBody(body); return forStatement; } /** * Creates a new {@link FunctionDeclaration}. * * @return A new FunctionDeclaration. */ public FunctionDeclaration newFunctionDeclaration() { FunctionDeclaration functionDeclaration = new FunctionDeclaration(this); return functionDeclaration; } /** * Creates a new {@link FunctionDeclaration}. * * @param functionName * @param formalParameters * @param body * @param isReference * @return A new FunctionDeclaration. */ public FunctionDeclaration newFunctionDeclaration(Identifier functionName, List<FormalParameter> formalParameters, Block body, final boolean isReference) { FunctionDeclaration functionDeclaration = new FunctionDeclaration(this); functionDeclaration.setFunctionName(functionName); functionDeclaration.formalParameters().addAll(formalParameters); functionDeclaration.setBody(body); functionDeclaration.setIsReference(isReference); return functionDeclaration; } /** * Creates a new {@link FunctionInvocation}. * * @return A new FunctionInvocation. */ public FunctionInvocation newFunctionInvocation() { FunctionInvocation functionInvocation = new FunctionInvocation(this); return functionInvocation; } /** * Creates a new {@link FunctionInvocation}. * * @param functionName * @param parameters * (can be null to indicate no parameters) * @return A new FunctionInvocation. */ public FunctionInvocation newFunctionInvocation(FunctionName functionName, List<Expression> parameters) { FunctionInvocation functionInvocation = new FunctionInvocation(this); functionInvocation.setFunctionName(functionName); if (parameters != null) { functionInvocation.parameters().addAll(parameters); } return functionInvocation; } /** * Creates a new {@link FunctionName}. * * @return A new FunctionName. */ public FunctionName newFunctionName() { FunctionName functionName = new FunctionName(this); return functionName; } /** * Creates a new {@link FunctionName}. * * @param functionName * @return A new FunctionName. */ public FunctionName newFunctionName(Expression name) { FunctionName functionName = new FunctionName(this); functionName.setName(name); return functionName; } /** * Creates a new {@link FieldsDeclaration}. * * @return A new FieldsDeclaration. */ public GlobalStatement newGlobalStatement() { GlobalStatement globalStatement = new GlobalStatement(this); return globalStatement; } /** * Creates a new {@link FieldsDeclaration}. * * @param variables * @return A new FieldsDeclaration. */ public GlobalStatement newGlobalStatement(List<Variable> variables) { GlobalStatement globalStatement = new GlobalStatement(this); globalStatement.variables().addAll(variables); return globalStatement; } /** * Creates a new {@link Identifier}. * * @return A new Identifier. */ public Identifier newIdentifier() { Identifier identifier = new Identifier(this); return identifier; } /** * Creates and returns a new unparented simple name node for the given * identifier. The identifier should be a legal PHP identifier. * * @param identifier * the identifier * @return a new unparented simple name node * @exception IllegalArgumentException * if the identifier is invalid */ public Identifier newIdentifier(String identifier) { if (identifier == null) { throw new IllegalArgumentException(); } Identifier result = new Identifier(this); result.setName(identifier); return result; } /** * Creates a new {@link IfStatement}. * * @return A new IfStatement. */ public IfStatement newIfStatement() { IfStatement ifStatement = new IfStatement(this); return ifStatement; } /** * Creates a new {@link IfStatement}. * * @param condition * @param trueStatement * @param falseStatement * @return A new IfStatement. */ public IfStatement newIfStatement(Expression condition, Statement trueStatement, Statement falseStatement) { IfStatement ifStatement = new IfStatement(this); ifStatement.setCondition(condition); ifStatement.setTrueStatement(trueStatement); ifStatement.setFalseStatement(falseStatement); return ifStatement; } /** * Creates a new {@link IgnoreError}. * * @return A new IgnoreError. */ public IgnoreError newIgnoreError() { IgnoreError ignoreError = new IgnoreError(this); return ignoreError; } /** * Creates a new {@link IgnoreError}. * * @param expression * @return A new IgnoreError. */ public IgnoreError newIgnoreError(Expression expression) { IgnoreError ignoreError = new IgnoreError(this); ignoreError.setExpression(expression); return ignoreError; } /** * Creates a new {@link Include}. * * @return A new Include. */ public Include newInclude() { Include include = new Include(this); return include; } /** * Creates a new {@link Include}. * * @param expression * @param type * @return A new Include. */ public Include newInclude(Expression expr, int type) { Include include = new Include(this); include.setExpression(expr); include.setIncludetype(type); return include; } /** * Creates a new {@link InfixExpression}. * * @return A new InfixExpression. */ public InfixExpression newInfixExpression() { InfixExpression infixExpression = new InfixExpression(this); return infixExpression; } /** * Creates a new {@link InfixExpression}. * * @param left * @param operator * @param right * @return A new InfixExpression. */ public InfixExpression newInfixExpression(Expression left, int operator, Expression right) { InfixExpression infixExpression = new InfixExpression(this); infixExpression.setLeft(left); infixExpression.setOperator(operator); infixExpression.setRight(right); return infixExpression; } /** * Creates a new {@link InLineHtml}. * * @return A new InLineHtml. */ public InLineHtml newInLineHtml() { InLineHtml inLineHtml = new InLineHtml(this); return inLineHtml; } /** * Creates a new {@link InstanceOfExpression}. * * @return A new InstanceOfExpression. */ public InstanceOfExpression newInstanceOfExpression() { InstanceOfExpression instanceOfExpression = new InstanceOfExpression( this); return instanceOfExpression; } /** * Creates a new {@link InstanceOfExpression}. * * @param expr * @param className * @return A new InstanceOfExpression. */ public InstanceOfExpression newInstanceOfExpression(Expression expr, ClassName className) { InstanceOfExpression instanceOfExpression = new InstanceOfExpression( this); instanceOfExpression.setClassName(className); instanceOfExpression.setExpression(expr); return instanceOfExpression; } /** * Creates a new {@link InterfaceDeclaration}. * * @return A new InterfaceDeclaration. */ public InterfaceDeclaration newInterfaceDeclaration() { InterfaceDeclaration interfaceDeclaration = new InterfaceDeclaration( this); return interfaceDeclaration; } /** * Creates a new {@link InterfaceDeclaration}. * * @param interfaceName * @param interfaces * @param body * @return A new InterfaceDeclaration. */ public InterfaceDeclaration newInterfaceDeclaration( Identifier interfaceName, List<Identifier> interfaces, Block body) { InterfaceDeclaration interfaceDeclaration = new InterfaceDeclaration( this); interfaceDeclaration.setName(interfaceName); interfaceDeclaration.interfaces().addAll(interfaces); interfaceDeclaration.setBody(body); return interfaceDeclaration; } /** * Creates a new {@link ListVariable}. * * @return A new ListVariable. */ public ListVariable newListVariable() { ListVariable listVariable = new ListVariable(this); return listVariable; } /** * Creates a new {@link ListVariable}. * * @param variables * @return A new ListVariable. */ public ListVariable newListVariable(List<VariableBase> variables) { ListVariable listVariable = new ListVariable(this); listVariable.variables().addAll(variables); return listVariable; } /** * Creates a new {@link MethodDeclaration}. * * @return A new MethodDeclaration. */ public MethodDeclaration newMethodDeclaration() { MethodDeclaration methodDeclaration = new MethodDeclaration(this); return methodDeclaration; } /** * Creates a new {@link MethodDeclaration}. * * @param modifier * @param function * @return A new MethodDeclaration. */ public MethodDeclaration newMethodDeclaration(int modifier, FunctionDeclaration function) { MethodDeclaration methodDeclaration = new MethodDeclaration(this); methodDeclaration.setModifier(modifier); methodDeclaration.setFunction(function); return methodDeclaration; } /** * Creates a new {@link MethodInvocation}. * * @return A new MethodInvocation. */ public MethodInvocation newMethodInvocation() { MethodInvocation methodInvocation = new MethodInvocation(this); return methodInvocation; } /** * Creates a new {@link MethodInvocation}. * * @param dispatcher * @param method * * @return A new MethodInvocation. */ public MethodInvocation newMethodInvocation(VariableBase dispatcher, FunctionInvocation method) { MethodInvocation methodInvocation = new MethodInvocation(this); methodInvocation.setDispatcher(dispatcher); methodInvocation.setMethod(method); return methodInvocation; } /** * Creates a new {@link ParenthesisExpression}. * * @return A new ParenthesisExpression. */ public ParenthesisExpression newParenthesisExpression() { ParenthesisExpression parenthesisExpression = new ParenthesisExpression( this); return parenthesisExpression; } /** * Creates a new {@link ParenthesisExpression}. * * @param expression * @return A new ParenthesisExpression. */ public ParenthesisExpression newParenthesisExpression(Expression expression) { ParenthesisExpression parenthesisExpression = new ParenthesisExpression( this); parenthesisExpression.setExpression(expression); return parenthesisExpression; } /** * Creates a new {@link PostfixExpression}. * * @return A new PostfixExpression. */ public PostfixExpression newPostfixExpression() { PostfixExpression postfixExpression = new PostfixExpression(this); return postfixExpression; } /** * Creates a new {@link PostfixExpression}. * * @param variable * @param operator * @return A new PostfixExpression. */ public PostfixExpression newPostfixExpression(VariableBase variable, int operator) { PostfixExpression postfixExpression = new PostfixExpression(this); postfixExpression.setVariable(variable); postfixExpression.setOperator(operator); return postfixExpression; } /** * Creates a new {@link PrefixExpression}. * * @return A new PrefixExpression. */ public PrefixExpression newPrefixExpression() { PrefixExpression prefixExpression = new PrefixExpression(this); return prefixExpression; } /** * Creates a new {@link PrefixExpression}. * * @param variable * @param operator * @return A new PrefixExpression. */ public PrefixExpression newPrefixExpression(VariableBase variable, int operator) { PrefixExpression prefixExpression = new PrefixExpression(this); prefixExpression.setVariable(variable); prefixExpression.setOperator(operator); return prefixExpression; } /** * Creates a new {@link Program}. * * @return A new Program. */ public Program newProgram() { Program program = new Program(this); return program; } /** * Creates a new {@link Program}. * * @return A new Program. */ public Program newProgram(List<Statement> statements, List<Comment> commentList) { Program program = new Program(this); program.statements().addAll(statements); program.comments().addAll(commentList); return program; } /** * Creates a new {@link Quote}. * * @return A new Quote. */ public Quote newQuote() { Quote quote = new Quote(this); return quote; } /** * Creates a new {@link Quote}. * * @param expressions * @param type * @return A new Quote. */ public Quote newQuote(List<Expression> expressions, int type) { Quote quote = new Quote(this); quote.expressions().addAll(expressions); quote.setQuoteType(type); return quote; } /** * Creates a new {@link Reference}. * * @return A new Reference. */ public Reference newReference() { Reference reference = new Reference(this); return reference; } /** * Creates a new {@link Reference}. * * @param expression * @return A new Reference. */ public Reference newReference(Expression expression) { Reference reference = new Reference(this); reference.setExpression(expression); return reference; } /** * Creates a new {@link ReflectionVariable}. * * @return A new ReflectionVariable. */ public ReflectionVariable newReflectionVariable() { ReflectionVariable reflectionVariable = new ReflectionVariable(this); return reflectionVariable; } /** * Creates a new {@link ReflectionVariable}. * * @param expression * @return A new ReflectionVariable. */ public ReflectionVariable newReflectionVariable(Expression expression) { ReflectionVariable reflectionVariable = new ReflectionVariable(this); reflectionVariable.setName(expression); return reflectionVariable; } /** * Creates a new {@link ReturnStatement}. * * @return A new ReturnStatement. */ public ReturnStatement newReturnStatement() { ReturnStatement returnStatement = new ReturnStatement(this); return returnStatement; } /** * Creates a new {@link ReturnStatement}. * * @param expression * @return A new ReturnStatement. */ public ReturnStatement newReturnStatement(Expression expression) { ReturnStatement returnStatement = new ReturnStatement(this); returnStatement.setExpression(expression); return returnStatement; } /** * Creates a new {@link Scalar}. * * @return A new Scalar. */ public Scalar newScalar() { Scalar scalar = new Scalar(this); return scalar; } /** * Creates a new scalar with a given type. * * @param string * The scalar's value. * @param scalarType * The scalar's type (e.g. Scalar.TYPE_STRING, Scalar.TYPE_INT * etc.). * @return A new {@link Scalar}. */ public Scalar newScalar(String string, int scalarType) { Scalar scalar = newScalar(string); scalar.setScalarType(scalarType); return scalar; } /** * Creates a new scalar with a default Scalar.TYPE_INT type. * * @param string * The scalar's value. * @return A new {@link Scalar}. */ public Scalar newScalar(String string) { Scalar scalar = new Scalar(this); scalar.setStringValue(string); return scalar; } /** * Creates a new {@link SingleFieldDeclaration}. * * @return A new SingleFieldDeclaration. */ public SingleFieldDeclaration newSingleFieldDeclaration() { SingleFieldDeclaration singleFieldDeclaration = new SingleFieldDeclaration( this); return singleFieldDeclaration; } /** * Creates a new {@link SingleFieldDeclaration}. * * @param name * @param value * @return A new SingleFieldDeclaration. */ public SingleFieldDeclaration newSingleFieldDeclaration(Variable name, Expression value) { SingleFieldDeclaration singleFieldDeclaration = new SingleFieldDeclaration( this); singleFieldDeclaration.setName(name); singleFieldDeclaration.setValue(value); return singleFieldDeclaration; } /** * Creates a new {@link StaticConstantAccess}. * * @return A new StaticConstantAccess. */ public StaticConstantAccess newStaticConstantAccess() { StaticConstantAccess staticConstantAccess = new StaticConstantAccess( this); return staticConstantAccess; } /** * Creates a new {@link StaticConstantAccess}. * * @param className * @param constant * @return A new StaticConstantAccess. */ public StaticConstantAccess newStaticConstantAccess(Identifier className, Identifier constant) { StaticConstantAccess staticConstantAccess = new StaticConstantAccess( this); staticConstantAccess.setClassName(className); staticConstantAccess.setConstant(constant); return staticConstantAccess; } /** * Creates a new {@link StaticFieldAccess}. * * @return A new StaticFieldAccess. */ public StaticFieldAccess newStaticFieldAccess() { StaticFieldAccess staticFieldAccess = new StaticFieldAccess(this); return staticFieldAccess; } /** * Creates a new {@link StaticFieldAccess}. * * @param className * @param field * @return A new StaticFieldAccess. */ public StaticFieldAccess newStaticFieldAccess(Identifier className, Variable field) { StaticFieldAccess staticFieldAccess = new StaticFieldAccess(this); staticFieldAccess.setClassName(className); staticFieldAccess.setField(field); return staticFieldAccess; } /** * Creates a new {@link StaticMethodInvocation}. * * @return A new StaticMethodInvocation. */ public StaticMethodInvocation newStaticMethodInvocation() { StaticMethodInvocation staticMethodInvocation = new StaticMethodInvocation( this); return staticMethodInvocation; } /** * Creates a new {@link StaticMethodInvocation}. * * @param className * @param method * @return A new StaticMethodInvocation. */ public StaticMethodInvocation newStaticMethodInvocation( Identifier className, FunctionInvocation method) { StaticMethodInvocation staticMethodInvocation = new StaticMethodInvocation( this); staticMethodInvocation.setClassName(className); staticMethodInvocation.setMethod(method); return staticMethodInvocation; } /** * Creates a new {@link StaticStatement}. * * @return A new StaticStatement. */ public StaticStatement newStaticStatement() { StaticStatement staticStatement = new StaticStatement(this); return staticStatement; } /** * Creates a new {@link StaticStatement}. * * @param expressions * @return A new StaticStatement. */ public StaticStatement newStaticStatement(List<Expression> expressions) { StaticStatement staticStatement = new StaticStatement(this); staticStatement.expressions().addAll(expressions); return staticStatement; } /** * Creates a new {@link SwitchCase}. * * @return A new SwitchCase. */ public SwitchCase newSwitchCase() { SwitchCase switchCase = new SwitchCase(this); return switchCase; } /** * Creates a new {@link SwitchCase}. * * @param value * @param actions * @param isDefault * @return A new SwitchCase. */ public SwitchCase newSwitchCase(Expression value, List<Statement> actions, boolean isDefault) { SwitchCase switchCase = new SwitchCase(this); switchCase.setValue(value); switchCase.actions().addAll(actions); switchCase.setIsDefault(isDefault); return switchCase; } /** * Creates a new {@link SwitchStatement}. * * @return A new SwitchStatement. */ public SwitchStatement newSwitchStatement() { SwitchStatement switchStatement = new SwitchStatement(this); return switchStatement; } /** * Creates a new {@link SwitchStatement}. * * @param expression * @param body * @return A new SwitchStatement. */ public SwitchStatement newSwitchStatement(Expression expression, Block body) { SwitchStatement switchStatement = new SwitchStatement(this); switchStatement.setExpression(expression); switchStatement.setBody(body); return switchStatement; } /** * Creates a new {@link ThrowStatement}. * * @return A new ThrowStatement. */ public ThrowStatement newThrowStatement() { ThrowStatement throwStatement = new ThrowStatement(this); return throwStatement; } /** * Creates a new {@link ThrowStatement}. * * @param expression * @return A new ThrowStatement. */ public ThrowStatement newThrowStatement(Expression expression) { ThrowStatement throwStatement = new ThrowStatement(this); throwStatement.setExpression(expression); return throwStatement; } /** * Creates a new {@link TryStatement}. * * @return A new TryStatement. */ public TryStatement newTryStatement() { TryStatement tryStatement = new TryStatement(this); return tryStatement; } /** * Creates a new {@link TryStatement}. * * @param tryStatement * @param catchClauses * @return A new TryStatement. */ public TryStatement newTryStatement(Block block, List<CatchClause> catchClauses) { TryStatement tryStatement = new TryStatement(this); tryStatement.setBody(block); tryStatement.catchClauses().addAll(catchClauses); return tryStatement; } /** * Creates a new {@link UnaryOperation}. * * @return A new UnaryOperation. */ public UnaryOperation newUnaryOperation() { UnaryOperation unaryOperation = new UnaryOperation(this); return unaryOperation; } /** * Creates a new {@link UnaryOperation}. * * @param expression * @param operator * @return A new UnaryOperation. */ public UnaryOperation newUnaryOperation(Expression expression, int operator) { UnaryOperation unaryOperation = new UnaryOperation(this); unaryOperation.setExpression(expression); unaryOperation.setOperator(operator); return unaryOperation; } /** * Creates a new {@link Variable}. * * The returned Variable is not dollared and does not have any name * {@link Expression}. * * @return A new {@link Variable}. */ public Variable newVariable() { Variable variable = new Variable(this); return variable; } /** * Creates a new {@link Variable} with a given name expression. * * @param name * A name {@link Expression} * @param isDollared * Indicate that this variable is dollared. * @return A new {@link Variable}. */ public Variable newVariable(Expression name, boolean isDollared) { Variable variable = newVariable(); variable.setIsDollared(isDollared); variable.setName(name); return variable; } /** * Creates a new dollared {@link Variable} with a given name . * * @param name * A name {@link String} * @return A new {@link Variable}. */ public Variable newVariable(String name) { Variable variable = newVariable(); variable.setIsDollared(true); variable.setName(newIdentifier(name)); return variable; } /** * Creates a new {@link WhileStatement}. * * @return A new WhileStatement. */ public WhileStatement newWhileStatement() { WhileStatement whileStatement = new WhileStatement(this); return whileStatement; } /** * Creates a new {@link WhileStatement}. * * @param condition * @param body * @return A new WhileStatement. */ public WhileStatement newWhileStatement(Expression condition, Statement body) { WhileStatement whileStatement = new WhileStatement(this); whileStatement.setCondition(condition); whileStatement.setBody(body); return whileStatement; } /** * Creates a new {@link NamespaceName}. * * @param name * @param isglobal * - Whether the namespace has a '\' prefix * @param iscurrent * - Whether the namespace has a 'namespace' prefix * @return A new NamespaceName. */ public NamespaceName newNamespaceName( final Collection<Identifier> segments, final boolean isglobal, final boolean iscurrent) { NamespaceName namespaceName = new NamespaceName(this); namespaceName.segments().addAll(segments); namespaceName.setGlobal(isglobal); namespaceName.setCurrent(iscurrent); return namespaceName; } /** * Creates a new {@link NamespaceDeclaration}. * * @param name * @param body * @return A new NamespaceDeclaration. */ public NamespaceDeclaration newNamespaceDeclaration(NamespaceName name, Block body) { NamespaceDeclaration namespaceDeclaration = new NamespaceDeclaration( this); namespaceDeclaration.setName(name); namespaceDeclaration.setBody(body); return namespaceDeclaration; } /** * Creates a new {@link UseStatementPart}. * * @param name * @param alias * @return A new UseStatementPart. */ public UseStatementPart newUseStatementPart(NamespaceName name, Identifier alias) { UseStatementPart usePart = new UseStatementPart(this); usePart.setName(name); usePart.setAlias(alias); return usePart; } /** * Creates a new {@link UseStatement}. * * @param parts * @return A new UseStatement. */ public UseStatement newUseStatement(Collection<UseStatementPart> parts) { UseStatement useStatement = new UseStatement(this); useStatement.parts().addAll(parts); return useStatement; } /** * Creates a new {@link GotoLabel}. * * @param label * @return A new GotoLabel. */ public GotoLabel newGotoLabel(Identifier label) { GotoLabel gotoLabel = new GotoLabel(this); gotoLabel.setName(label); return gotoLabel; } /** * Creates a new {@link GotoStatement}. * * @param label * @return A new GotoStatement. */ public GotoStatement newGotoStatement(Identifier label) { GotoStatement gotoStatement = new GotoStatement(this); gotoStatement.setLabel(label); return gotoStatement; } /** * Creates a new {@link LambdaFunctionDeclaration}. * * @param label * @return A new LambdaFunctionDeclaration. */ public LambdaFunctionDeclaration newLambdaFunctionDeclaration( final Collection<FormalParameter> formalParameters, final Collection<Variable> lexicalVars, final Block body, final boolean isReference, final boolean isStatic) { LambdaFunctionDeclaration lfDeclaration = new LambdaFunctionDeclaration( this); lfDeclaration.setBody(body); lfDeclaration.setIsReference(isReference); lfDeclaration.setStatic(isStatic); lfDeclaration.formalParameters().addAll(formalParameters); lfDeclaration.lexicalVariables().addAll(lexicalVars); return lfDeclaration; } /*************************php5.4 starts***************************/ public ChainingInstanceCall newChainingInstanceCall( PHPArrayDereferenceList arrayDereferenceList, List<VariableBase> chainingMethodOrProperty) { ChainingInstanceCall lfDeclaration = new ChainingInstanceCall( this,arrayDereferenceList, chainingMethodOrProperty); return lfDeclaration; } public DereferenceNode newDereferenceNode(Expression indexName) { DereferenceNode lfDeclaration = new DereferenceNode(this); lfDeclaration.setName(indexName); return lfDeclaration; } public FullyQualifiedTraitMethodReference newFullyQualifiedTraitMethodReference(NamespaceName className, Identifier functionName) { FullyQualifiedTraitMethodReference lfDeclaration = new FullyQualifiedTraitMethodReference(this); lfDeclaration.setClassName(className); lfDeclaration.setFunctionName(functionName); return lfDeclaration; } public PHPArrayDereferenceList newPHPArrayDereferenceList(List<DereferenceNode> dereferences) { PHPArrayDereferenceList lfDeclaration = new PHPArrayDereferenceList(this,dereferences); return lfDeclaration; } public TraitAlias newTraitAlias(Expression traitMethod, int modifier, Identifier functionName) { TraitAlias lfDeclaration = new TraitAlias(this); lfDeclaration.setModifier(modifier); lfDeclaration.setTraitMethod(traitMethod); lfDeclaration.setFunctionName(functionName); return lfDeclaration; } public TraitAliasStatement newTraitAliasStatement(TraitAlias alias) { TraitAliasStatement lfDeclaration = new TraitAliasStatement(this); lfDeclaration.setAlias(alias); return lfDeclaration; } /** * Creates a new {@link TraitDeclaration}. * * @return A new TraitDeclaration. */ public TraitDeclaration newTraitDeclaration() { TraitDeclaration lfDeclaration = new TraitDeclaration(this); return lfDeclaration; } /** * Creates a new {@link TraitDeclaration}. * * @param modifier * @param className * @param superClass * @param interfaces * @param body * @return A new TraitDeclaration. */ public TraitDeclaration newTraitDeclaration(int modifier, String className, String superClass, List<Identifier> interfaces, Block body) { TraitDeclaration traitDeclaration = new TraitDeclaration(this); traitDeclaration.setModifier(modifier); traitDeclaration.setName(newIdentifier(className)); if (superClass != null) { traitDeclaration.setSuperClass(newIdentifier(superClass)); } else { traitDeclaration.setSuperClass(null); } traitDeclaration.interfaces().addAll(interfaces); traitDeclaration.setBody(body); return traitDeclaration; } public TraitPrecedence newTraitPrecedence(FullyQualifiedTraitMethodReference methodReference, List<NamespaceName> trList) { TraitPrecedence lfDeclaration = new TraitPrecedence(this); lfDeclaration.setMethodReference(methodReference); lfDeclaration.setTrList(trList); return lfDeclaration; } public TraitPrecedenceStatement newTraitPrecedenceStatement(TraitPrecedence precedence) { TraitPrecedenceStatement lfDeclaration = new TraitPrecedenceStatement(this); lfDeclaration.setPrecedence(precedence); return lfDeclaration; } public TraitUseStatement newTraitUseStatement(List<NamespaceName> traitList, List<TraitStatement> tsList) { TraitUseStatement lfDeclaration = new TraitUseStatement(this); lfDeclaration.setTraitList(traitList); lfDeclaration.setTsList(tsList); return lfDeclaration; } /*************************php5.4 ends***************************/ public void setInsertUseStatement(boolean isInsertUseStatement) { // TODO Auto-generated method stub this.rewriter.setInsertUseStatement(isInsertUseStatement); } }