/*******************************************************************************
* 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.match;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import org2.eclipse.php.internal.core.ast.nodes.ASTError;
import org2.eclipse.php.internal.core.ast.nodes.ASTNode;
import org2.eclipse.php.internal.core.ast.nodes.ArrayAccess;
import org2.eclipse.php.internal.core.ast.nodes.ArrayCreation;
import org2.eclipse.php.internal.core.ast.nodes.ArrayElement;
import org2.eclipse.php.internal.core.ast.nodes.Assignment;
import org2.eclipse.php.internal.core.ast.nodes.BackTickExpression;
import org2.eclipse.php.internal.core.ast.nodes.Block;
import org2.eclipse.php.internal.core.ast.nodes.BreakStatement;
import org2.eclipse.php.internal.core.ast.nodes.CastExpression;
import org2.eclipse.php.internal.core.ast.nodes.CatchClause;
import org2.eclipse.php.internal.core.ast.nodes.ChainingInstanceCall;
import org2.eclipse.php.internal.core.ast.nodes.ClassDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.ClassInstanceCreation;
import org2.eclipse.php.internal.core.ast.nodes.ClassName;
import org2.eclipse.php.internal.core.ast.nodes.CloneExpression;
import org2.eclipse.php.internal.core.ast.nodes.Comment;
import org2.eclipse.php.internal.core.ast.nodes.ConditionalExpression;
import org2.eclipse.php.internal.core.ast.nodes.ConstantDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.ContinueStatement;
import org2.eclipse.php.internal.core.ast.nodes.DeclareStatement;
import org2.eclipse.php.internal.core.ast.nodes.DereferenceNode;
import org2.eclipse.php.internal.core.ast.nodes.DoStatement;
import org2.eclipse.php.internal.core.ast.nodes.EchoStatement;
import org2.eclipse.php.internal.core.ast.nodes.EmptyStatement;
import org2.eclipse.php.internal.core.ast.nodes.Expression;
import org2.eclipse.php.internal.core.ast.nodes.ExpressionStatement;
import org2.eclipse.php.internal.core.ast.nodes.FieldAccess;
import org2.eclipse.php.internal.core.ast.nodes.FieldsDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.ForEachStatement;
import org2.eclipse.php.internal.core.ast.nodes.ForStatement;
import org2.eclipse.php.internal.core.ast.nodes.FormalParameter;
import org2.eclipse.php.internal.core.ast.nodes.FullyQualifiedTraitMethodReference;
import org2.eclipse.php.internal.core.ast.nodes.FunctionDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.FunctionInvocation;
import org2.eclipse.php.internal.core.ast.nodes.FunctionName;
import org2.eclipse.php.internal.core.ast.nodes.GlobalStatement;
import org2.eclipse.php.internal.core.ast.nodes.GotoLabel;
import org2.eclipse.php.internal.core.ast.nodes.GotoStatement;
import org2.eclipse.php.internal.core.ast.nodes.Identifier;
import org2.eclipse.php.internal.core.ast.nodes.IfStatement;
import org2.eclipse.php.internal.core.ast.nodes.IgnoreError;
import org2.eclipse.php.internal.core.ast.nodes.InLineHtml;
import org2.eclipse.php.internal.core.ast.nodes.Include;
import org2.eclipse.php.internal.core.ast.nodes.InfixExpression;
import org2.eclipse.php.internal.core.ast.nodes.InstanceOfExpression;
import org2.eclipse.php.internal.core.ast.nodes.InterfaceDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.LambdaFunctionDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.ListVariable;
import org2.eclipse.php.internal.core.ast.nodes.MethodDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.MethodInvocation;
import org2.eclipse.php.internal.core.ast.nodes.NamespaceDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.NamespaceName;
import org2.eclipse.php.internal.core.ast.nodes.PHPArrayDereferenceList;
import org2.eclipse.php.internal.core.ast.nodes.ParenthesisExpression;
import org2.eclipse.php.internal.core.ast.nodes.PostfixExpression;
import org2.eclipse.php.internal.core.ast.nodes.PrefixExpression;
import org2.eclipse.php.internal.core.ast.nodes.Program;
import org2.eclipse.php.internal.core.ast.nodes.Quote;
import org2.eclipse.php.internal.core.ast.nodes.Reference;
import org2.eclipse.php.internal.core.ast.nodes.ReflectionVariable;
import org2.eclipse.php.internal.core.ast.nodes.ReturnStatement;
import org2.eclipse.php.internal.core.ast.nodes.Scalar;
import org2.eclipse.php.internal.core.ast.nodes.SingleFieldDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.Statement;
import org2.eclipse.php.internal.core.ast.nodes.StaticConstantAccess;
import org2.eclipse.php.internal.core.ast.nodes.StaticFieldAccess;
import org2.eclipse.php.internal.core.ast.nodes.StaticMethodInvocation;
import org2.eclipse.php.internal.core.ast.nodes.StaticStatement;
import org2.eclipse.php.internal.core.ast.nodes.SwitchCase;
import org2.eclipse.php.internal.core.ast.nodes.SwitchStatement;
import org2.eclipse.php.internal.core.ast.nodes.ThrowStatement;
import org2.eclipse.php.internal.core.ast.nodes.TraitAlias;
import org2.eclipse.php.internal.core.ast.nodes.TraitPrecedence;
import org2.eclipse.php.internal.core.ast.nodes.TraitStatement;
import org2.eclipse.php.internal.core.ast.nodes.TraitUseStatement;
import org2.eclipse.php.internal.core.ast.nodes.TryStatement;
import org2.eclipse.php.internal.core.ast.nodes.TypeDeclaration;
import org2.eclipse.php.internal.core.ast.nodes.UnaryOperation;
import org2.eclipse.php.internal.core.ast.nodes.UseStatement;
import org2.eclipse.php.internal.core.ast.nodes.UseStatementPart;
import org2.eclipse.php.internal.core.ast.nodes.Variable;
import org2.eclipse.php.internal.core.ast.nodes.WhileStatement;
import com.aptana.core.util.ObjectUtil;
/**
* Concrete superclass and default implementation of an AST subtree matcher.
* <p>
* For example, to compute whether two ASTs subtrees are structurally
* isomorphic, use <code>n1.subtreeMatch(new ASTMatcher(), n2)</code> where
* <code>n1</code> and <code>n2</code> are the AST root nodes of the subtrees.
* </p>
* <p>
* For each different concrete AST node type <i>T</i> there is a
* <code>public boolean match(<i>T</i> node, Object other)</code> method that
* matches the given node against another object (typically another AST node,
* although this is not essential). The default implementations provided by this
* class tests whether the other object is a node of the same type with
* structurally isomorphic child subtrees. For nodes with list-valued
* properties, the child nodes within the list are compared in order. For nodes
* with multiple properties, the child nodes are compared in the order that most
* closely corresponds to the lexical reading order of the source program. For
* instance, for a type declaration node, the child ordering is: name,
* superclass, superinterfaces, and body declarations.
* </p>
* <p>
* Subclasses may override (extend or reimplement) some or all of the
* <code>match</code> methods in order to define more specialized subtree
* matchers.
* </p>
*
* @see ASTNode#subtreeMatch(ASTMatcher, Object)
* @since 2.0
*/
@SuppressWarnings("deprecation")
public class ASTMatcher {
/**
* Indicates whether doc tags should be matched.
*
* @since 3.0
*/
@SuppressWarnings("unused")
private boolean matchDocTags;
/**
* Creates a new AST matcher instance.
* <p>
* For backwards compatibility, the matcher ignores tag elements below doc
* comments by default. Use {@link #ASTMatcher(boolean) ASTMatcher(true)}
* for a matcher that compares doc tags by default.
* </p>
*/
public ASTMatcher() {
this(false);
}
/**
* Creates a new AST matcher instance.
*
* @param matchDocTags
* <code>true</code> if doc comment tags are to be compared by
* default, and <code>false</code> otherwise
* @since 3.0
*/
public ASTMatcher(boolean matchDocTags) {
this.matchDocTags = matchDocTags;
}
/**
* Returns whether the given lists of AST nodes match pair wise according to
* <code>ASTNode.subtreeMatch</code>.
* <p>
* Note that this is a convenience method, useful for writing recursive
* subtree matchers.
* </p>
*
* @param list1
* the first list of AST nodes (element type:
* <code>ASTNode</code>)
* @param list2
* the second list of AST nodes (element type:
* <code>ASTNode</code>)
* @return <code>true</code> if the lists have the same number of elements
* and match pair-wise according to
* <code>ASTNode.subtreeMatch</code>
* @see ASTNode#subtreeMatch(ASTMatcher matcher, Object other)
*/
@SuppressWarnings("rawtypes")
public final boolean safeSubtreeListMatch(Collection list1, Collection list2) {
int size1 = list1.size();
int size2 = list2.size();
if (size1 != size2) {
return false;
}
for (Iterator it1 = list1.iterator(), it2 = list2.iterator(); it1
.hasNext();) {
ASTNode n1 = (ASTNode) it1.next();
ASTNode n2 = (ASTNode) it2.next();
if (n1 == null && n2 == null) {
continue;
}
if (n1 == null || n2 == null) {
return false;
}
if (!n1.subtreeMatch(this, n2)) {
return false;
}
}
return true;
}
/**
* Returns whether the given lists of AST nodes match pair wise according to
* <code>ASTNode.subtreeMatch</code>.
* <p>
* Note that this is a convenience method, useful for writing recursive
* subtree matchers.
* </p>
*
* @param list1
* the first array of AST expressions (element type:
* <code>ASTNode</code>)
* @param list2
* the second array of AST expressions (element type:
* <code>ASTNode</code>)
* @return <code>true</code> if the arrays have the same number of elements
* and match pair-wise according to
* <code>ASTNode.subtreeMatch</code>
* @see ASTNode#subtreeMatch(ASTMatcher matcher, Object other)
*/
public final boolean safeSubtreeListMatch(Expression[] list1,
Expression[] list2) {
return safeSubtreeListMatch(Arrays.asList(list1), Arrays.asList(list2));
}
/**
* Returns whether the given lists of AST nodes match pair wise according to
* <code>ASTNode.subtreeMatch</code>.
* <p>
* Note that this is a convenience method, useful for writing recursive
* subtree matchers.
* </p>
*
* @param list1
* the first array of AST statements (element type:
* <code>ASTNode</code>)
* @param list2
* the second array of AST statements (element type:
* <code>ASTNode</code>)
* @return <code>true</code> if the arrays have the same number of elements
* and match pair-wise according to
* <code>ASTNode.subtreeMatch</code>
* @see ASTNode#subtreeMatch(ASTMatcher matcher, Object other)
*/
public final boolean safeSubtreeListMatch(Statement[] list1,
Statement[] list2) {
return safeSubtreeListMatch(Arrays.asList(list1), Arrays.asList(list2));
}
/**
* Returns whether the given lists of AST nodes match pair wise according to
* <code>ASTNode.subtreeMatch</code>.
* <p>
* Note that this is a convenience method, useful for writing recursive
* subtree matchers.
* </p>
*
* @param list1
* the first array of AST nodes (element type:
* <code>ASTNode</code>)
* @param list2
* the second array of AST nodes (element type:
* <code>ASTNode</code>)
* @return <code>true</code> if the arrays have the same number of elements
* and match pair-wise according to
* <code>ASTNode.subtreeMatch</code>
* @see ASTNode#subtreeMatch(ASTMatcher matcher, Object other)
*/
public final boolean safeSubtreeListMatch(ASTNode[] list1, ASTNode[] list2) {
return safeSubtreeListMatch(Arrays.asList(list1), Arrays.asList(list2));
}
/**
* Returns whether the given nodes match according to
* <code>AST.subtreeMatch</code>. Returns <code>false</code> if one or the
* other of the nodes are <code>null</code>. Returns <code>true</code> if
* both nodes are <code>null</code>.
* <p>
* Note that this is a convenience method, useful for writing recursive
* subtree matchers.
* </p>
*
* @param node1
* the first AST node, or <code>null</code>; must be an instance
* of <code>ASTNode</code>
* @param node2
* the second AST node, or <code>null</code>; must be an instance
* of <code>ASTNode</code>
* @return <code>true</code> if the nodes match according to
* <code>AST.subtreeMatch</code> or both are <code>null</code>, and
* <code>false</code> otherwise
* @see ASTNode#subtreeMatch(ASTMatcher, Object)
*/
public final boolean safeSubtreeMatch(Object node1, Object node2) {
if (node1 == null && node2 == null) {
return true;
}
if (node1 == null || node2 == null) {
return false;
}
// N.B. call subtreeMatch even node1==node2!=null
return ((ASTNode) node1).subtreeMatch(this, node2);
}
/**
* Returns whether the given objects are equal according to
* <code>equals</code>. Returns <code>false</code> if either node is
* <code>null</code>.
*
* @param o1
* the first object, or <code>null</code>
* @param o2
* the second object, or <code>null</code>
* @return <code>true</code> if the nodes are equal according to
* <code>equals</code> or both <code>null</code>, and
* <code>false</code> otherwise
*/
public static boolean safeEquals(Object o1, Object o2) {
if (o1 == o2) {
return true;
}
if (o1 == null || o2 == null) {
return false;
}
return o1.equals(o2);
}
/**
* Returns whether the given node and the other object match.
* <p>
* The default implementation provided by this class tests whether the other
* object is a node of the same type with structurally isomorphic child
* subtrees. Subclasses may override this method as needed.
* </p>
*
* @param node
* the node
* @param other
* the other object, or <code>null</code>
* @return <code>true</code> if the subtree matches, or <code>false</code>
* if they do not match or the other object has a different node
* type or is <code>null</code>
* @since 3.1
*/
public boolean match(ArrayAccess node, Object other) {
if (!(other instanceof ArrayAccess)) {
return false;
}
ArrayAccess o = (ArrayAccess) other;
return (safeSubtreeMatch(node.getName(), o.getName())
&& safeSubtreeMatch(node.getIndex(), o.getIndex()) && safeEquals(
node.getArrayType(), o.getArrayType()));
}
public boolean match(ArrayCreation node, Object other) {
if (!(other instanceof ArrayCreation)) {
return false;
}
ArrayCreation o = (ArrayCreation) other;
return safeSubtreeListMatch(node.elements(), o.elements());
}
public boolean match(ArrayElement node, Object other) {
if (!(other instanceof ArrayElement)) {
return false;
}
ArrayElement o = (ArrayElement) other;
return (safeSubtreeMatch(node.getKey(), o.getKey()) && safeSubtreeMatch(
node.getValue(), o.getValue()));
}
public boolean match(Assignment node, Object other) {
if (!(other instanceof Assignment)) {
return false;
}
Assignment o = (Assignment) other;
return (safeEquals(node.getOperator(), o.getOperator())
&& safeSubtreeMatch(node.getRightHandSide(),
o.getRightHandSide()) && safeSubtreeMatch(
node.getLeftHandSide(), o.getLeftHandSide()));
}
public boolean match(ASTError node, Object other) {
// always return false since there is no comparison between 2 errors
return false;
}
public boolean match(BackTickExpression node, Object other) {
if (!(other instanceof BackTickExpression)) {
return false;
}
BackTickExpression o = (BackTickExpression) other;
return safeSubtreeListMatch(node.expressions(), o.expressions());
}
public boolean match(Block node, Object other) {
if (!(other instanceof Block)) {
return false;
}
Block o = (Block) other;
return (safeEquals(node.isCurly(), o.isCurly()) && safeSubtreeListMatch(
node.statements(), o.statements()));
}
public boolean match(BreakStatement node, Object other) {
if (!(other instanceof BreakStatement)) {
return false;
}
BreakStatement o = (BreakStatement) other;
return safeSubtreeMatch(node.getExpression(), o.getExpression());
}
public boolean match(CastExpression node, Object other) {
if (!(other instanceof CastExpression)) {
return false;
}
CastExpression o = (CastExpression) other;
return (safeEquals(node.getCastingType(), o.getCastingType()) && safeSubtreeMatch(
node.getExpression(), o.getExpression()));
}
public boolean match(CatchClause node, Object other) {
if (!(other instanceof CatchClause)) {
return false;
}
CatchClause o = (CatchClause) other;
return (safeSubtreeMatch(node.getClassName(), o.getClassName())
&& safeSubtreeMatch(node.getVariable(), o.getVariable()) && safeSubtreeMatch(
node.getBody(), o.getBody()));
}
public boolean match(ConstantDeclaration node, Object other) {
if (!(other instanceof ConstantDeclaration)) {
return false;
}
ConstantDeclaration o = (ConstantDeclaration) other;
return (safeSubtreeListMatch(node.initializers(), o.initializers()) && safeSubtreeListMatch(
node.names(), o.names()));
}
public boolean match(ClassDeclaration node, Object other) {
if (!(other instanceof ClassDeclaration)) {
return false;
}
ClassDeclaration o = (ClassDeclaration) other;
return (safeEquals(node.getModifier(), o.getModifier())
&& safeSubtreeMatch(node.getSuperClass(), o.getSuperClass()) && match(
(TypeDeclaration) node, (TypeDeclaration) o));
}
private boolean match(TypeDeclaration node, Object other) {
if (!(other instanceof TypeDeclaration)) {
return false;
}
TypeDeclaration o = (TypeDeclaration) other;
return (safeSubtreeMatch(node.getName(), o.getName())
&& safeSubtreeMatch(node.getBody(), o.getBody()) && safeSubtreeListMatch(
node.interfaces(), o.interfaces()));
}
public boolean match(ClassInstanceCreation node, Object other) {
if (!(other instanceof ClassInstanceCreation)) {
return false;
}
ClassInstanceCreation o = (ClassInstanceCreation) other;
return (safeSubtreeMatch(node.getClassName(), o.getClassName()) && safeSubtreeListMatch(
node.ctorParams(), o.ctorParams()));
}
public boolean match(ClassName node, Object other) {
if (!(other instanceof ClassName)) {
return false;
}
ClassName o = (ClassName) other;
return safeSubtreeMatch(node.getName(), o.getName());
}
public boolean match(CloneExpression node, Object other) {
if (!(other instanceof CloneExpression)) {
return false;
}
CloneExpression o = (CloneExpression) other;
return safeSubtreeMatch(node.getExpression(), o.getExpression());
}
// TODO - will implement in the future
public boolean match(Comment node, Object other) {
return true;
}
public boolean match(ConditionalExpression node, Object other) {
if (!(other instanceof ConditionalExpression)) {
return false;
}
ConditionalExpression o = (ConditionalExpression) other;
return (safeSubtreeMatch(node.getCondition(), o.getCondition())
&& safeSubtreeMatch(node.getIfTrue(), o.getIfTrue()) && safeSubtreeMatch(
node.getIfFalse(), o.getIfFalse()));
}
public boolean match(ContinueStatement node, Object other) {
if (!(other instanceof ContinueStatement)) {
return false;
}
ContinueStatement o = (ContinueStatement) other;
return safeSubtreeMatch(node.getExpression(), o.getExpression());
}
public boolean match(DeclareStatement node, Object other) {
if (!(other instanceof DeclareStatement)) {
return false;
}
DeclareStatement o = (DeclareStatement) other;
return (safeSubtreeMatch(node.getBody(), o.getBody())
&& safeSubtreeListMatch(node.directiveNames(),
o.directiveNames()) && safeSubtreeListMatch(
node.directiveValues(), o.directiveValues()));
}
public boolean match(DoStatement node, Object other) {
if (!(other instanceof DoStatement)) {
return false;
}
DoStatement o = (DoStatement) other;
return (safeSubtreeMatch(node.getCondition(), o.getCondition()) && safeSubtreeMatch(
node.getBody(), o.getBody()));
}
public boolean match(EchoStatement node, Object other) {
if (!(other instanceof EchoStatement)) {
return false;
}
EchoStatement o = (EchoStatement) other;
return safeSubtreeListMatch(node.expressions(), o.expressions());
}
public boolean match(EmptyStatement node, Object other) {
if (!(other instanceof EmptyStatement)) {
return false;
}
// 2 empty statements are equal by definition
return true;
}
public boolean match(ExpressionStatement node, Object other) {
if (!(other instanceof ExpressionStatement)) {
return false;
}
ExpressionStatement o = (ExpressionStatement) other;
return safeSubtreeMatch(node.getExpression(), o.getExpression());
}
public boolean match(FieldAccess node, Object other) {
if (!(other instanceof FieldAccess)) {
return false;
}
FieldAccess o = (FieldAccess) other;
return (safeSubtreeMatch(node.getDispatcher(), o.getDispatcher()) && safeSubtreeMatch(
node.getField(), o.getField()));
}
public boolean match(FieldsDeclaration node, Object other) {
if (!(other instanceof FieldsDeclaration)) {
return false;
}
FieldsDeclaration o = (FieldsDeclaration) other;
return (safeEquals(node.getModifier(), o.getModifier())
&& safeSubtreeListMatch(node.getInitialValues(),
o.getInitialValues()) && safeSubtreeListMatch(
node.getVariableNames(), o.getVariableNames()));
}
public boolean match(ForEachStatement node, Object other) {
if (!(other instanceof ForEachStatement)) {
return false;
}
ForEachStatement o = (ForEachStatement) other;
return (safeSubtreeMatch(node.getExpression(), o.getExpression())
&& safeSubtreeMatch(node.getKey(), o.getKey())
&& safeSubtreeMatch(node.getValue(), o.getValue()) && safeSubtreeMatch(
node.getStatement(), o.getStatement()));
}
public boolean match(FormalParameter node, Object other) {
if (!(other instanceof FormalParameter)) {
return false;
}
FormalParameter o = (FormalParameter) other;
return (safeEquals(node.isMandatory(), o.isMandatory())
&& safeSubtreeMatch(node.getParameterType(),
o.getParameterType())
&& safeSubtreeMatch(node.getParameterName(),
o.getParameterName()) && safeSubtreeMatch(
node.getDefaultValue(), o.getDefaultValue()));
}
public boolean match(ForStatement node, Object other) {
if (!(other instanceof ForStatement)) {
return false;
}
ForStatement o = (ForStatement) other;
return (safeSubtreeMatch(node.getBody(), o.getBody())
&& safeSubtreeListMatch(node.initializers(), o.initializers())
&& safeSubtreeListMatch(node.conditions(), o.conditions()) && safeSubtreeListMatch(
node.updaters(), o.updaters()));
}
public boolean match(FunctionDeclaration node, Object other) {
if (!(other instanceof FunctionDeclaration)) {
return false;
}
FunctionDeclaration o = (FunctionDeclaration) other;
return (safeEquals(node.isReference(), o.isReference())
&& safeSubtreeMatch(node.getBody(), o.getBody())
&& safeSubtreeMatch(node.getFunctionName(), o.getFunctionName()) && safeSubtreeListMatch(
node.formalParameters(), o.formalParameters()));
}
public boolean match(FunctionInvocation node, Object other) {
if (!(other instanceof FunctionInvocation)) {
return false;
}
FunctionInvocation o = (FunctionInvocation) other;
// Aptana Mod - Added a matching for the PHPArrayDereferenceList
return (safeSubtreeMatch(node.getFunctionName(), o.getFunctionName())
&& safeSubtreeListMatch(node.parameters(), o.parameters()) && safeSubtreeMatch(
node.getArrayDereferenceList(), o.getArrayDereferenceList()));
}
public boolean match(FunctionName node, Object other) {
if (!(other instanceof FunctionName)) {
return false;
}
FunctionName o = (FunctionName) other;
return safeSubtreeMatch(node.getName(), o.getName());
}
public boolean match(GlobalStatement node, Object other) {
if (!(other instanceof GlobalStatement)) {
return false;
}
GlobalStatement o = (GlobalStatement) other;
return safeSubtreeListMatch(node.variables(), o.variables());
}
public boolean match(Identifier node, Object other) {
if (!(other instanceof Identifier)) {
return false;
}
Identifier o = (Identifier) other;
return safeEquals(node.getName(), o.getName());
}
public boolean match(IfStatement node, Object other) {
if (!(other instanceof IfStatement)) {
return false;
}
IfStatement o = (IfStatement) other;
return (safeSubtreeMatch(node.getCondition(), o.getCondition())
&& safeSubtreeMatch(node.getTrueStatement(),
o.getTrueStatement()) && safeSubtreeMatch(
node.getFalseStatement(), o.getFalseStatement()));
}
public boolean match(IgnoreError node, Object other) {
if (!(other instanceof IgnoreError)) {
return false;
}
IgnoreError o = (IgnoreError) other;
return safeSubtreeMatch(node.getExpression(), o.getExpression());
}
public boolean match(Include node, Object other) {
if (!(other instanceof Include)) {
return false;
}
Include o = (Include) other;
return (safeEquals(node.getIncludeType(), o.getIncludeType()) && safeSubtreeMatch(
node.getExpression(), o.getExpression()));
}
public boolean match(InfixExpression node, Object other) {
if (!(other instanceof InfixExpression)) {
return false;
}
InfixExpression o = (InfixExpression) other;
return (safeEquals(node.getOperator(), o.getOperator())
&& safeSubtreeMatch(node.getRight(), o.getRight()) && safeSubtreeMatch(
node.getLeft(), o.getLeft()));
}
// TODO - need to check the contents of the html
public boolean match(InLineHtml node, Object other) {
if (!(other instanceof InLineHtml)) {
return false;
}
@SuppressWarnings("unused")
InLineHtml o = (InLineHtml) other;
return false;
}
public boolean match(InstanceOfExpression node, Object other) {
if (!(other instanceof InstanceOfExpression)) {
return false;
}
InstanceOfExpression o = (InstanceOfExpression) other;
return (safeSubtreeMatch(node.getClassName(), o.getClassName()) && safeSubtreeMatch(
node.getExpression(), o.getExpression()));
}
public boolean match(InterfaceDeclaration node, Object other) {
if (!(other instanceof InterfaceDeclaration)) {
return false;
}
InterfaceDeclaration o = (InterfaceDeclaration) other;
return match((TypeDeclaration) node, (TypeDeclaration) o);
}
public boolean match(ListVariable node, Object other) {
if (!(other instanceof ListVariable)) {
return false;
}
ListVariable o = (ListVariable) other;
return safeSubtreeListMatch(node.variables(), o.variables());
}
public boolean match(MethodDeclaration node, Object other) {
if (!(other instanceof MethodDeclaration)) {
return false;
}
MethodDeclaration o = (MethodDeclaration) other;
return (safeEquals(node.getModifier(), o.getModifier()) && safeSubtreeMatch(
node.getFunction(), o.getFunction()));
}
public boolean match(MethodInvocation node, Object other) {
if (!(other instanceof MethodInvocation)) {
return false;
}
MethodInvocation o = (MethodInvocation) other;
return (safeSubtreeMatch(node.getDispatcher(), o.getDispatcher()) && safeSubtreeMatch(
node.getMethod(), o.getMethod()));
}
public boolean match(ParenthesisExpression node, Object other) {
if (!(other instanceof ParenthesisExpression)) {
return false;
}
ParenthesisExpression o = (ParenthesisExpression) other;
return safeSubtreeMatch(node.getExpression(), o.getExpression());
}
public boolean match(PostfixExpression node, Object other) {
if (!(other instanceof PostfixExpression)) {
return false;
}
PostfixExpression o = (PostfixExpression) other;
return (safeEquals(node.getOperator(), o.getOperator()) && safeSubtreeMatch(
node.getVariable(), o.getVariable()));
}
public boolean match(PrefixExpression node, Object other) {
if (!(other instanceof PrefixExpression)) {
return false;
}
PrefixExpression o = (PrefixExpression) other;
return (safeEquals(node.getOperator(), o.getOperator()) && safeSubtreeMatch(
node.getVariable(), o.getVariable()));
}
public boolean match(Program node, Object other, boolean matchComments) {
if (!(other instanceof Program)) {
return false;
}
Program o = (Program) other;
boolean statementsMatch = safeSubtreeListMatch(node.statements(), o.statements());
if (!matchComments) {
return statementsMatch;
}
return statementsMatch && safeSubtreeListMatch(node.comments(), (o.comments()));
}
public boolean match(Quote node, Object other) {
if (!(other instanceof Quote)) {
return false;
}
Quote o = (Quote) other;
return (safeEquals(node.getQuoteType(), o.getQuoteType()) && safeSubtreeListMatch(
node.expressions(), o.expressions()));
}
public boolean match(Reference node, Object other) {
if (!(other instanceof Reference)) {
return false;
}
Reference o = (Reference) other;
return safeSubtreeMatch(node.getExpression(), o.getExpression());
}
public boolean match(ReflectionVariable node, Object other) {
if (!(other instanceof ReflectionVariable)) {
return false;
}
ReflectionVariable o = (ReflectionVariable) other;
return (match((Variable) node, (Variable) o));
}
public boolean match(ReturnStatement node, Object other) {
if (!(other instanceof ReturnStatement)) {
return false;
}
ReturnStatement o = (ReturnStatement) other;
return safeSubtreeMatch(node.getExpression(), o.getExpression());
}
public boolean match(Scalar node, Object other) {
if (!(other instanceof Scalar)) {
return false;
}
Scalar o = (Scalar) other;
return (safeEquals(node.getStringValue(), o.getStringValue()) && safeEquals(
node.getScalarType(), o.getScalarType()));
}
public boolean match(SingleFieldDeclaration node, Object other) {
if (!(other instanceof SingleFieldDeclaration)) {
return false;
}
SingleFieldDeclaration o = (SingleFieldDeclaration) other;
return (safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeMatch(
node.getValue(), o.getValue()));
}
public boolean match(StaticConstantAccess node, Object other) {
if (!(other instanceof StaticConstantAccess)) {
return false;
}
StaticConstantAccess o = (StaticConstantAccess) other;
return (safeSubtreeMatch(node.getClassName(), o.getClassName()) && safeSubtreeMatch(
node.getConstant(), o.getConstant()));
}
public boolean match(StaticFieldAccess node, Object other) {
if (!(other instanceof StaticFieldAccess)) {
return false;
}
StaticFieldAccess o = (StaticFieldAccess) other;
return (safeSubtreeMatch(node.getClassName(), o.getClassName()) && safeSubtreeMatch(
node.getField(), o.getField()));
}
public boolean match(StaticMethodInvocation node, Object other) {
if (!(other instanceof StaticMethodInvocation)) {
return false;
}
StaticMethodInvocation o = (StaticMethodInvocation) other;
return (safeSubtreeMatch(node.getClassName(), o.getClassName()) && safeSubtreeMatch(
node.getMethod(), o.getMethod()));
}
public boolean match(StaticStatement node, Object other) {
if (!(other instanceof StaticStatement)) {
return false;
}
StaticStatement o = (StaticStatement) other;
return safeSubtreeListMatch(node.getExpressions(), o.getExpressions());
}
public boolean match(SwitchCase node, Object other) {
if (!(other instanceof SwitchCase)) {
return false;
}
SwitchCase o = (SwitchCase) other;
return (safeEquals(node.isDefault(), o.isDefault())
&& safeSubtreeMatch(node.getValue(), o.getValue()) && safeSubtreeListMatch(
node.getActions(), o.getActions()));
}
public boolean match(SwitchStatement node, Object other) {
if (!(other instanceof SwitchStatement)) {
return false;
}
SwitchStatement o = (SwitchStatement) other;
return (safeSubtreeMatch(node.getExpr(), o.getExpr()) && safeSubtreeMatch(
node.getStatement(), o.getStatement()));
}
public boolean match(ThrowStatement node, Object other) {
if (!(other instanceof ThrowStatement)) {
return false;
}
ThrowStatement o = (ThrowStatement) other;
// return false;
// Aptana Mod
return (safeSubtreeMatch(node.getExpression(), o.getExpression()));
}
public boolean match(TryStatement node, Object other) {
if (!(other instanceof TryStatement)) {
return false;
}
TryStatement o = (TryStatement) other;
return (safeSubtreeMatch(node.getTryStatement(), o.getTryStatement()) && safeSubtreeListMatch(
node.getCatchClauses(), o.getCatchClauses()));
}
public boolean match(UnaryOperation node, Object other) {
if (!(other instanceof UnaryOperation)) {
return false;
}
UnaryOperation o = (UnaryOperation) other;
return (safeEquals(node.getOperator(), o.getOperator()) && safeSubtreeMatch(
node.getExpr(), o.getExpr()));
}
public boolean match(Variable node, Object other) {
if (!(other instanceof Variable)) {
return false;
}
Variable o = (Variable) other;
return (safeSubtreeMatch(node.getVariableName(), o.getVariableName()) && safeEquals(
node.isDollared(), o.isDollared()));
}
public boolean match(WhileStatement node, Object other) {
if (!(other instanceof WhileStatement)) {
return false;
}
WhileStatement o = (WhileStatement) other;
return (safeSubtreeMatch(node.getCondition(), o.getCondition()) && safeSubtreeMatch(
node.getAction(), o.getAction()));
}
public boolean match(NamespaceDeclaration node, Object other) {
if (!(other instanceof NamespaceDeclaration)) {
return false;
}
NamespaceDeclaration o = (NamespaceDeclaration) other;
return safeSubtreeMatch(node.getName(), o.getName())
&& safeSubtreeMatch(node.getBody(), o.getBody());
}
public boolean match(NamespaceName node, Object other) {
if (!(other instanceof NamespaceName)) {
return false;
}
NamespaceName o = (NamespaceName) other;
return safeEquals(node.isGlobal(), o.isGlobal())
&& safeEquals(node.isCurrent(), o.isCurrent())
&& safeSubtreeListMatch(node.segments(), o.segments());
}
public boolean match(UseStatementPart node, Object other) {
if (!(other instanceof UseStatementPart)) {
return false;
}
UseStatementPart o = (UseStatementPart) other;
return safeSubtreeMatch(node.getName(), o.getName())
&& safeSubtreeMatch(node.getAlias(), o.getAlias());
}
public boolean match(UseStatement node, Object other) {
if (!(other instanceof UseStatement)) {
return false;
}
UseStatement o = (UseStatement) other;
return safeSubtreeListMatch(node.parts(), o.parts());
}
public boolean match(GotoLabel node, Object other) {
if (!(other instanceof GotoLabel)) {
return false;
}
GotoLabel o = (GotoLabel) other;
return safeSubtreeMatch(node.getName(), o.getName());
}
public boolean match(GotoStatement node, Object other) {
if (!(other instanceof GotoStatement)) {
return false;
}
GotoStatement o = (GotoStatement) other;
return safeSubtreeMatch(node.getLabel(), o.getLabel());
}
public boolean match(LambdaFunctionDeclaration node, Object other) {
if (!(other instanceof LambdaFunctionDeclaration)) {
return false;
}
LambdaFunctionDeclaration o = (LambdaFunctionDeclaration) other;
return (safeEquals(node.isReference(), o.isReference())
&& safeEquals(node.isStatic(), o.isStatic())
&& safeSubtreeMatch(node.getBody(), o.getBody())
&& safeSubtreeListMatch(node.formalParameters(),
o.formalParameters()) && safeSubtreeListMatch(
node.lexicalVariables(), o.lexicalVariables()));
}
public boolean match(PHPArrayDereferenceList node, Object other) {
if (!(other instanceof PHPArrayDereferenceList)) {
return false;
}
PHPArrayDereferenceList o = (PHPArrayDereferenceList) other;
return (safeSubtreeListMatch(node.getDereferences(),
o.getDereferences()));
}
public boolean match(DereferenceNode node, Object other) {
if (!(other instanceof DereferenceNode)) {
return false;
}
DereferenceNode o = (DereferenceNode) other;
return safeSubtreeMatch(node.getName(), o.getName());
}
public boolean match(TraitUseStatement node, Object other) {
if (!(other instanceof TraitUseStatement)) {
return false;
}
TraitUseStatement o = (TraitUseStatement) other;
return (safeSubtreeListMatch(node.getTraitList(), o.getTraitList()))
&& (safeSubtreeListMatch(node.getTsList(), o.getTsList()));
}
public boolean match(TraitStatement node, Object other) {
if (!(other instanceof TraitStatement)) {
return false;
}
TraitStatement o = (TraitStatement) other;
return safeSubtreeMatch(node.getExp(), o.getExp());
}
public boolean match(TraitPrecedence node, Object other) {
if (!(other instanceof TraitPrecedence)) {
return false;
}
TraitPrecedence o = (TraitPrecedence) other;
return (safeSubtreeMatch(node.getMethodReference(),
o.getMethodReference()))
&& (safeSubtreeListMatch(node.getTrList(), o.getTrList()));
}
public boolean match(TraitAlias node, Object other) {
if (!(other instanceof TraitAlias)) {
return false;
}
TraitAlias o = (TraitAlias) other;
return safeSubtreeMatch(node.getTraitMethod(), o.getTraitMethod())
&& node.getModifier() == o.getModifier()
&& ObjectUtil.areEqual(node.getFunctionName(), o.getFunctionName());
}
public boolean match(FullyQualifiedTraitMethodReference node, Object other) {
if (!(other instanceof FullyQualifiedTraitMethodReference)) {
return false;
}
FullyQualifiedTraitMethodReference o = (FullyQualifiedTraitMethodReference) other;
return safeSubtreeMatch(node.getClassName(), o.getClassName())
&& node.getFunctionName().equals(o.getFunctionName());
}
public boolean match(ChainingInstanceCall node, Object other) {
if (!(other instanceof ChainingInstanceCall)) {
return false;
}
ChainingInstanceCall o = (ChainingInstanceCall) other;
return (safeSubtreeMatch(node.getArrayDereferenceList(),
o.getArrayDereferenceList()))
&& (safeSubtreeMatch(node.getChainingMethodOrProperty(),
o.getChainingMethodOrProperty()));
}
}