/******************************************************************************* * Copyright (c) 2000, 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 *******************************************************************************/ package org.eclipse.jdt.core.dom; import java.util.Iterator; import java.util.List; /** * 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 org.eclipse.jdt.core.dom.ASTNode#subtreeMatch(ASTMatcher, Object) * @since 2.0 */ public class ASTMatcher { /** * Indicates whether doc tags should be matched. * * @since 3.0 */ 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 * @see #match(Javadoc,Object) * @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) */ public final boolean safeSubtreeListMatch(List list1, List 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.subtreeMatch(this, n2)) { return false; } } return true; } /** * 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(AnnotationTypeDeclaration node, Object other) { if (!(other instanceof AnnotationTypeDeclaration)) { return false; } AnnotationTypeDeclaration o= (AnnotationTypeDeclaration)other; // node type added in JLS3 - ignore old JLS2-style modifiers return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) && safeSubtreeListMatch(node.modifiers(), o.modifiers()) && safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations())); } /** * 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(AnnotationTypeMemberDeclaration node, Object other) { if (!(other instanceof AnnotationTypeMemberDeclaration)) { return false; } AnnotationTypeMemberDeclaration o= (AnnotationTypeMemberDeclaration)other; // node type added in JLS3 - ignore old JLS2-style modifiers return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) && safeSubtreeListMatch(node.modifiers(), o.modifiers()) && safeSubtreeMatch(node.getType(), o.getType()) && safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeMatch(node.getDefault(), o.getDefault())); } /** * 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> */ public boolean match(AnonymousClassDeclaration node, Object other) { if (!(other instanceof AnonymousClassDeclaration)) { return false; } AnonymousClassDeclaration o= (AnonymousClassDeclaration)other; return safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations()); } /** * 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> */ public boolean match(ArrayAccess node, Object other) { if (!(other instanceof ArrayAccess)) { return false; } ArrayAccess o= (ArrayAccess)other; return (safeSubtreeMatch(node.getArray(), o.getArray()) && safeSubtreeMatch(node.getIndex(), o.getIndex())); } /** * Returns whether the given node and the other object 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> */ public boolean match(ArrayCreation node, Object other) { if (!(other instanceof ArrayCreation)) { return false; } ArrayCreation o= (ArrayCreation)other; return (safeSubtreeMatch(node.getType(), o.getType()) && safeSubtreeListMatch(node.dimensions(), o.dimensions()) && safeSubtreeMatch(node.getInitializer(), o.getInitializer())); } /** * 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> */ public boolean match(ArrayInitializer node, Object other) { if (!(other instanceof ArrayInitializer)) { return false; } ArrayInitializer o= (ArrayInitializer)other; return safeSubtreeListMatch(node.expressions(), o.expressions()); } /** * 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> */ public boolean match(ArrayType node, Object other) { if (!(other instanceof ArrayType)) { return false; } ArrayType o= (ArrayType)other; return safeSubtreeMatch(node.getComponentType(), o.getComponentType()); } /** * 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> */ public boolean match(AssertStatement node, Object other) { if (!(other instanceof AssertStatement)) { return false; } AssertStatement o= (AssertStatement)other; return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeMatch(node.getMessage(), o.getMessage())); } /** * 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> */ public boolean match(Assignment node, Object other) { if (!(other instanceof Assignment)) { return false; } Assignment o= (Assignment)other; return (node.getOperator().equals(o.getOperator()) && safeSubtreeMatch(node.getLeftHandSide(), o.getLeftHandSide()) && safeSubtreeMatch(node.getRightHandSide(), o.getRightHandSide())); } /** * 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> */ public boolean match(Block node, Object other) { if (!(other instanceof Block)) { return false; } Block o= (Block)other; return safeSubtreeListMatch(node.statements(), o.statements()); } /** * 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. Subclasses may override this method as needed. * </p> * <p> * Note: {@link LineComment} and {@link BlockComment} nodes are not considered part of main * structure of the AST. This method will only be called if a client goes out of their way to * visit this kind of node explicitly. * </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.0 */ public boolean match(BlockComment node, Object other) { if (!(other instanceof BlockComment)) { return false; } return true; } /** * 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> */ public boolean match(BooleanLiteral node, Object other) { if (!(other instanceof BooleanLiteral)) { return false; } BooleanLiteral o= (BooleanLiteral)other; return node.booleanValue() == o.booleanValue(); } /** * 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> */ public boolean match(BreakStatement node, Object other) { if (!(other instanceof BreakStatement)) { return false; } BreakStatement o= (BreakStatement)other; return safeSubtreeMatch(node.getLabel(), o.getLabel()); } /** * 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> */ public boolean match(CastExpression node, Object other) { if (!(other instanceof CastExpression)) { return false; } CastExpression o= (CastExpression)other; return (safeSubtreeMatch(node.getType(), o.getType()) && safeSubtreeMatch(node.getExpression(), o.getExpression())); } /** * 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> */ public boolean match(CatchClause node, Object other) { if (!(other instanceof CatchClause)) { return false; } CatchClause o= (CatchClause)other; return (safeSubtreeMatch(node.getException(), o.getException()) && safeSubtreeMatch(node.getBody(), o.getBody())); } /** * 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> */ public boolean match(CharacterLiteral node, Object other) { if (!(other instanceof CharacterLiteral)) { return false; } CharacterLiteral o= (CharacterLiteral)other; return safeEquals(node.getEscapedValue(), o.getEscapedValue()); } /** * 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> */ public boolean match(ClassInstanceCreation node, Object other) { if (!(other instanceof ClassInstanceCreation)) { return false; } ClassInstanceCreation o= (ClassInstanceCreation)other; int level= node.getAST().apiLevel; if (level == AST.JLS2_INTERNAL) { if (!safeSubtreeMatch(node.internalGetName(), o.internalGetName())) { return false; } } if (level >= AST.JLS3) { if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) { return false; } if (!safeSubtreeMatch(node.getType(), o.getType())) { return false; } } return safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeListMatch(node.arguments(), o.arguments()) && safeSubtreeMatch( node.getAnonymousClassDeclaration(), o.getAnonymousClassDeclaration()); } /** * 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> */ public boolean match(CompilationUnit node, Object other) { if (!(other instanceof CompilationUnit)) { return false; } CompilationUnit o= (CompilationUnit)other; return (safeSubtreeMatch(node.getPackage(), o.getPackage()) && safeSubtreeListMatch(node.imports(), o.imports()) && safeSubtreeListMatch(node.types(), o.types())); } /** * 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> */ public boolean match(ConditionalExpression node, Object other) { if (!(other instanceof ConditionalExpression)) { return false; } ConditionalExpression o= (ConditionalExpression)other; return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeMatch(node.getThenExpression(), o.getThenExpression()) && safeSubtreeMatch(node.getElseExpression(), o.getElseExpression())); } /** * 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> */ public boolean match(ConstructorInvocation node, Object other) { if (!(other instanceof ConstructorInvocation)) { return false; } ConstructorInvocation o= (ConstructorInvocation)other; if (node.getAST().apiLevel >= AST.JLS3) { if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) { return false; } } return safeSubtreeListMatch(node.arguments(), o.arguments()); } /** * 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> */ public boolean match(ContinueStatement node, Object other) { if (!(other instanceof ContinueStatement)) { return false; } ContinueStatement o= (ContinueStatement)other; return safeSubtreeMatch(node.getLabel(), o.getLabel()); } /** * 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> */ public boolean match(DoStatement node, Object other) { if (!(other instanceof DoStatement)) { return false; } DoStatement o= (DoStatement)other; return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeMatch(node.getBody(), o.getBody())); } /** * 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> */ public boolean match(EmptyStatement node, Object other) { if (!(other instanceof EmptyStatement)) { return false; } return true; } /** * 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(EnhancedForStatement node, Object other) { if (!(other instanceof EnhancedForStatement)) { return false; } EnhancedForStatement o= (EnhancedForStatement)other; return (safeSubtreeMatch(node.getParameter(), o.getParameter()) && safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeMatch(node.getBody(), o.getBody())); } /** * 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(EnumConstantDeclaration node, Object other) { if (!(other instanceof EnumConstantDeclaration)) { return false; } EnumConstantDeclaration o= (EnumConstantDeclaration)other; return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) && safeSubtreeListMatch(node.modifiers(), o.modifiers()) && safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeListMatch(node.arguments(), o.arguments()) && safeSubtreeMatch( node.getAnonymousClassDeclaration(), o.getAnonymousClassDeclaration())); } /** * 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(EnumDeclaration node, Object other) { if (!(other instanceof EnumDeclaration)) { return false; } EnumDeclaration o= (EnumDeclaration)other; return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) && safeSubtreeListMatch(node.modifiers(), o.modifiers()) && safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeListMatch(node.superInterfaceTypes(), o.superInterfaceTypes()) && safeSubtreeListMatch(node.enumConstants(), o.enumConstants()) && safeSubtreeListMatch( node.bodyDeclarations(), o.bodyDeclarations())); } /** * 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> */ public boolean match(ExpressionStatement node, Object other) { if (!(other instanceof ExpressionStatement)) { return false; } ExpressionStatement o= (ExpressionStatement)other; return safeSubtreeMatch(node.getExpression(), o.getExpression()); } /** * 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> */ public boolean match(FieldAccess node, Object other) { if (!(other instanceof FieldAccess)) { return false; } FieldAccess o= (FieldAccess)other; return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeMatch(node.getName(), o.getName())); } /** * 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> */ public boolean match(FieldDeclaration node, Object other) { if (!(other instanceof FieldDeclaration)) { return false; } FieldDeclaration o= (FieldDeclaration)other; int level= node.getAST().apiLevel; if (level == AST.JLS2_INTERNAL) { if (node.getModifiers() != o.getModifiers()) { return false; } } if (level >= AST.JLS3) { if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) { return false; } } return safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) && safeSubtreeMatch(node.getType(), o.getType()) && safeSubtreeListMatch(node.fragments(), o.fragments()); } /** * 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> */ public boolean match(ForStatement node, Object other) { if (!(other instanceof ForStatement)) { return false; } ForStatement o= (ForStatement)other; return (safeSubtreeListMatch(node.initializers(), o.initializers()) && safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeListMatch(node.updaters(), o.updaters()) && safeSubtreeMatch(node.getBody(), o.getBody())); } /** * 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> */ public boolean match(IfStatement node, Object other) { if (!(other instanceof IfStatement)) { return false; } IfStatement o= (IfStatement)other; return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeMatch(node.getThenStatement(), o.getThenStatement()) && safeSubtreeMatch(node.getElseStatement(), o.getElseStatement())); } /** * 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> */ public boolean match(ImportDeclaration node, Object other) { if (!(other instanceof ImportDeclaration)) { return false; } ImportDeclaration o= (ImportDeclaration)other; if (node.getAST().apiLevel >= AST.JLS3) { if (node.isStatic() != o.isStatic()) { return false; } } return (safeSubtreeMatch(node.getName(), o.getName()) && node.isOnDemand() == o.isOnDemand()); } /** * 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> */ public boolean match(InfixExpression node, Object other) { if (!(other instanceof InfixExpression)) { return false; } InfixExpression o= (InfixExpression)other; // be careful not to trigger lazy creation of extended operand lists if (node.hasExtendedOperands() && o.hasExtendedOperands()) { if (!safeSubtreeListMatch(node.extendedOperands(), o.extendedOperands())) { return false; } } if (node.hasExtendedOperands() != o.hasExtendedOperands()) { return false; } return (node.getOperator().equals(o.getOperator()) && safeSubtreeMatch(node.getLeftOperand(), o.getLeftOperand()) && safeSubtreeMatch(node.getRightOperand(), o.getRightOperand())); } /** * 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> */ public boolean match(InstanceofExpression node, Object other) { if (!(other instanceof InstanceofExpression)) { return false; } InstanceofExpression o= (InstanceofExpression)other; return (safeSubtreeMatch(node.getLeftOperand(), o.getLeftOperand()) && safeSubtreeMatch(node.getRightOperand(), o.getRightOperand())); } /** * 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> */ public boolean match(Initializer node, Object other) { if (!(other instanceof Initializer)) { return false; } Initializer o= (Initializer)other; int level= node.getAST().apiLevel; if (level == AST.JLS2_INTERNAL) { if (node.getModifiers() != o.getModifiers()) { return false; } } if (level >= AST.JLS3) { if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) { return false; } } return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) && safeSubtreeMatch(node.getBody(), o.getBody())); } /** * Returns whether the given node and the other object match. * <p> * Unlike other node types, the behavior of the default implementation is controlled by a * constructor-supplied parameter {@link #ASTMatcher(boolean) ASTMatcher(boolean)} which is * <code>false</code> if not specified. When this parameter is <code>true</code>, the * implementation tests whether the other object is also a <code>Javadoc</code> with * structurally isomorphic child subtrees; the comment string (<code>Javadoc.getComment()</code> * ) is ignored. Conversely, when the parameter is <code>false</code>, the implementation tests * whether the other object is also a <code>Javadoc</code> with exactly the same comment string; * the tag elements ({@link Javadoc#tags() Javadoc.tags} are ignored. Subclasses may * reimplement. * </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> * @see #ASTMatcher() * @see #ASTMatcher(boolean) */ public boolean match(Javadoc node, Object other) { if (!(other instanceof Javadoc)) { return false; } Javadoc o= (Javadoc)other; if (this.matchDocTags) { return safeSubtreeListMatch(node.tags(), o.tags()); } else { return compareDeprecatedComment(node, o); } } /** * Return whether the deprecated comment strings of the given java doc are equals. * <p> * Note the only purpose of this method is to hide deprecated warnings. * * @deprecated mark deprecated to hide deprecated usage */ private boolean compareDeprecatedComment(Javadoc first, Javadoc second) { if (first.getAST().apiLevel == AST.JLS2_INTERNAL) { return safeEquals(first.getComment(), second.getComment()); } else { return true; } } /** * 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> */ public boolean match(LabeledStatement node, Object other) { if (!(other instanceof LabeledStatement)) { return false; } LabeledStatement o= (LabeledStatement)other; return (safeSubtreeMatch(node.getLabel(), o.getLabel()) && safeSubtreeMatch(node.getBody(), o.getBody())); } /** * 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. Subclasses may override this method as needed. * </p> * <p> * Note: {@link LineComment} and {@link BlockComment} nodes are not considered part of main * structure of the AST. This method will only be called if a client goes out of their way to * visit this kind of node explicitly. * </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.0 */ public boolean match(LineComment node, Object other) { if (!(other instanceof LineComment)) { return false; } return true; } /** * 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(MarkerAnnotation node, Object other) { if (!(other instanceof MarkerAnnotation)) { return false; } MarkerAnnotation o= (MarkerAnnotation)other; return safeSubtreeMatch(node.getTypeName(), o.getTypeName()); } /** * 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.0 */ public boolean match(MemberRef node, Object other) { if (!(other instanceof MemberRef)) { return false; } MemberRef o= (MemberRef)other; return (safeSubtreeMatch(node.getQualifier(), o.getQualifier()) && safeSubtreeMatch(node.getName(), o.getName())); } /** * 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(MemberValuePair node, Object other) { if (!(other instanceof MemberValuePair)) { return false; } MemberValuePair o= (MemberValuePair)other; return (safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeMatch(node.getValue(), o.getValue())); } /** * 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.0 */ public boolean match(MethodRef node, Object other) { if (!(other instanceof MethodRef)) { return false; } MethodRef o= (MethodRef)other; return (safeSubtreeMatch(node.getQualifier(), o.getQualifier()) && safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeListMatch(node.parameters(), o.parameters())); } /** * 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.0 */ public boolean match(MethodRefParameter node, Object other) { if (!(other instanceof MethodRefParameter)) { return false; } MethodRefParameter o= (MethodRefParameter)other; int level= node.getAST().apiLevel; if (level >= AST.JLS3) { if (node.isVarargs() != o.isVarargs()) { return false; } } return (safeSubtreeMatch(node.getType(), o.getType()) && safeSubtreeMatch(node.getName(), o.getName())); } /** * 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> * <p> * Note that extra array dimensions are compared since they are an important part of the method * declaration. * </p> * <p> * Note that the method return types are compared even for constructor declarations. * </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> */ public boolean match(MethodDeclaration node, Object other) { if (!(other instanceof MethodDeclaration)) { return false; } MethodDeclaration o= (MethodDeclaration)other; int level= node.getAST().apiLevel; if (level == AST.JLS2_INTERNAL) { if (node.getModifiers() != o.getModifiers()) { return false; } if (!safeSubtreeMatch(node.internalGetReturnType(), o.internalGetReturnType())) { return false; } } if (level >= AST.JLS3) { if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) { return false; } if (!safeSubtreeMatch(node.getReturnType2(), o.getReturnType2())) { return false; } // n.b. compare type parameters even for constructors if (!safeSubtreeListMatch(node.typeParameters(), o.typeParameters())) { return false; } } return ((node.isConstructor() == o.isConstructor()) && safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) && safeSubtreeMatch(node.getName(), o.getName()) // n.b. compare return type even for constructors && safeSubtreeListMatch(node.parameters(), o.parameters()) && node.getExtraDimensions() == o.getExtraDimensions() && safeSubtreeListMatch(node.thrownExceptions(), o.thrownExceptions()) && safeSubtreeMatch(node.getBody(), o.getBody())); } /** * 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> */ public boolean match(MethodInvocation node, Object other) { if (!(other instanceof MethodInvocation)) { return false; } MethodInvocation o= (MethodInvocation)other; if (node.getAST().apiLevel >= AST.JLS3) { if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) { return false; } } return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeListMatch(node.arguments(), o.arguments())); } /** * 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(Modifier node, Object other) { if (!(other instanceof Modifier)) { return false; } Modifier o= (Modifier)other; return (node.getKeyword() == o.getKeyword()); } /** * 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(NormalAnnotation node, Object other) { if (!(other instanceof NormalAnnotation)) { return false; } NormalAnnotation o= (NormalAnnotation)other; return (safeSubtreeMatch(node.getTypeName(), o.getTypeName()) && safeSubtreeListMatch(node.values(), o.values())); } /** * 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> */ public boolean match(NullLiteral node, Object other) { if (!(other instanceof NullLiteral)) { return false; } return true; } /** * 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> */ public boolean match(NumberLiteral node, Object other) { if (!(other instanceof NumberLiteral)) { return false; } NumberLiteral o= (NumberLiteral)other; return safeEquals(node.getToken(), o.getToken()); } /** * 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> */ public boolean match(PackageDeclaration node, Object other) { if (!(other instanceof PackageDeclaration)) { return false; } PackageDeclaration o= (PackageDeclaration)other; if (node.getAST().apiLevel >= AST.JLS3) { if (!safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())) { return false; } if (!safeSubtreeListMatch(node.annotations(), o.annotations())) { return false; } } return safeSubtreeMatch(node.getName(), o.getName()); } /** * 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(ParameterizedType node, Object other) { if (!(other instanceof ParameterizedType)) { return false; } ParameterizedType o= (ParameterizedType)other; return safeSubtreeMatch(node.getType(), o.getType()) && safeSubtreeListMatch(node.typeArguments(), o.typeArguments()); } /** * 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> */ public boolean match(ParenthesizedExpression node, Object other) { if (!(other instanceof ParenthesizedExpression)) { return false; } ParenthesizedExpression o= (ParenthesizedExpression)other; return safeSubtreeMatch(node.getExpression(), o.getExpression()); } /** * 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> */ public boolean match(PostfixExpression node, Object other) { if (!(other instanceof PostfixExpression)) { return false; } PostfixExpression o= (PostfixExpression)other; return (node.getOperator().equals(o.getOperator()) && safeSubtreeMatch(node.getOperand(), o.getOperand())); } /** * 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> */ public boolean match(PrefixExpression node, Object other) { if (!(other instanceof PrefixExpression)) { return false; } PrefixExpression o= (PrefixExpression)other; return (node.getOperator().equals(o.getOperator()) && safeSubtreeMatch(node.getOperand(), o.getOperand())); } /** * 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> */ public boolean match(PrimitiveType node, Object other) { if (!(other instanceof PrimitiveType)) { return false; } PrimitiveType o= (PrimitiveType)other; return (node.getPrimitiveTypeCode() == o.getPrimitiveTypeCode()); } /** * 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> */ public boolean match(QualifiedName node, Object other) { if (!(other instanceof QualifiedName)) { return false; } QualifiedName o= (QualifiedName)other; return (safeSubtreeMatch(node.getQualifier(), o.getQualifier()) && safeSubtreeMatch(node.getName(), o.getName())); } /** * 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(QualifiedType node, Object other) { if (!(other instanceof QualifiedType)) { return false; } QualifiedType o= (QualifiedType)other; return (safeSubtreeMatch(node.getQualifier(), o.getQualifier()) && safeSubtreeMatch(node.getName(), o.getName())); } /** * 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> */ public boolean match(ReturnStatement node, Object other) { if (!(other instanceof ReturnStatement)) { return false; } ReturnStatement o= (ReturnStatement)other; return safeSubtreeMatch(node.getExpression(), o.getExpression()); } /** * 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> */ public boolean match(SimpleName node, Object other) { if (!(other instanceof SimpleName)) { return false; } SimpleName o= (SimpleName)other; return node.getIdentifier().equals(o.getIdentifier()); } /** * 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> */ public boolean match(SimpleType node, Object other) { if (!(other instanceof SimpleType)) { return false; } SimpleType o= (SimpleType)other; return safeSubtreeMatch(node.getName(), o.getName()); } /** * 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(SingleMemberAnnotation node, Object other) { if (!(other instanceof SingleMemberAnnotation)) { return false; } SingleMemberAnnotation o= (SingleMemberAnnotation)other; return (safeSubtreeMatch(node.getTypeName(), o.getTypeName()) && safeSubtreeMatch(node.getValue(), o.getValue())); } /** * 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> * <p> * Note that extra array dimensions and the variable arity flag are compared since they are both * important parts of the declaration. * </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> */ public boolean match(SingleVariableDeclaration node, Object other) { if (!(other instanceof SingleVariableDeclaration)) { return false; } SingleVariableDeclaration o= (SingleVariableDeclaration)other; int level= node.getAST().apiLevel; if (level == AST.JLS2_INTERNAL) { if (node.getModifiers() != o.getModifiers()) { return false; } } if (level >= AST.JLS3) { if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) { return false; } if (node.isVarargs() != o.isVarargs()) { return false; } } return safeSubtreeMatch(node.getType(), o.getType()) && safeSubtreeMatch(node.getName(), o.getName()) && node.getExtraDimensions() == o.getExtraDimensions() && safeSubtreeMatch(node.getInitializer(), o.getInitializer()); } /** * 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> */ public boolean match(StringLiteral node, Object other) { if (!(other instanceof StringLiteral)) { return false; } StringLiteral o= (StringLiteral)other; return safeEquals(node.getEscapedValue(), o.getEscapedValue()); } /** * 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> */ public boolean match(SuperConstructorInvocation node, Object other) { if (!(other instanceof SuperConstructorInvocation)) { return false; } SuperConstructorInvocation o= (SuperConstructorInvocation)other; if (node.getAST().apiLevel >= AST.JLS3) { if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) { return false; } } return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeListMatch(node.arguments(), o.arguments())); } /** * 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> */ public boolean match(SuperFieldAccess node, Object other) { if (!(other instanceof SuperFieldAccess)) { return false; } SuperFieldAccess o= (SuperFieldAccess)other; return (safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeMatch(node.getQualifier(), o.getQualifier())); } /** * 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> */ public boolean match(SuperMethodInvocation node, Object other) { if (!(other instanceof SuperMethodInvocation)) { return false; } SuperMethodInvocation o= (SuperMethodInvocation)other; if (node.getAST().apiLevel >= AST.JLS3) { if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) { return false; } } return (safeSubtreeMatch(node.getQualifier(), o.getQualifier()) && safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeListMatch(node.arguments(), o.arguments())); } /** * 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> */ public boolean match(SwitchCase node, Object other) { if (!(other instanceof SwitchCase)) { return false; } SwitchCase o= (SwitchCase)other; return safeSubtreeMatch(node.getExpression(), o.getExpression()); } /** * 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> */ public boolean match(SwitchStatement node, Object other) { if (!(other instanceof SwitchStatement)) { return false; } SwitchStatement o= (SwitchStatement)other; return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeListMatch(node.statements(), o.statements())); } /** * 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> */ public boolean match(SynchronizedStatement node, Object other) { if (!(other instanceof SynchronizedStatement)) { return false; } SynchronizedStatement o= (SynchronizedStatement)other; return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeMatch(node.getBody(), o.getBody())); } /** * 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.0 */ public boolean match(TagElement node, Object other) { if (!(other instanceof TagElement)) { return false; } TagElement o= (TagElement)other; return (safeEquals(node.getTagName(), o.getTagName()) && safeSubtreeListMatch(node.fragments(), o.fragments())); } /** * 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.0 */ public boolean match(TextElement node, Object other) { if (!(other instanceof TextElement)) { return false; } TextElement o= (TextElement)other; return safeEquals(node.getText(), o.getText()); } /** * 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> */ public boolean match(ThisExpression node, Object other) { if (!(other instanceof ThisExpression)) { return false; } ThisExpression o= (ThisExpression)other; return safeSubtreeMatch(node.getQualifier(), o.getQualifier()); } /** * 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> */ public boolean match(ThrowStatement node, Object other) { if (!(other instanceof ThrowStatement)) { return false; } ThrowStatement o= (ThrowStatement)other; return safeSubtreeMatch(node.getExpression(), o.getExpression()); } /** * 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> */ public boolean match(TryStatement node, Object other) { if (!(other instanceof TryStatement)) { return false; } TryStatement o= (TryStatement)other; return (safeSubtreeMatch(node.getBody(), o.getBody()) && safeSubtreeListMatch(node.catchClauses(), o.catchClauses()) && safeSubtreeMatch(node.getFinally(), o.getFinally())); } /** * 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> */ public boolean match(TypeDeclaration node, Object other) { if (!(other instanceof TypeDeclaration)) { return false; } TypeDeclaration o= (TypeDeclaration)other; int level= node.getAST().apiLevel; if (level == AST.JLS2_INTERNAL) { if (node.getModifiers() != o.getModifiers()) { return false; } if (!safeSubtreeMatch(node.internalGetSuperclass(), o.internalGetSuperclass())) { return false; } if (!safeSubtreeListMatch(node.internalSuperInterfaces(), o.internalSuperInterfaces())) { return false; } } if (level >= AST.JLS3) { if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) { return false; } if (!safeSubtreeListMatch(node.typeParameters(), o.typeParameters())) { return false; } if (!safeSubtreeMatch(node.getSuperclassType(), o.getSuperclassType())) { return false; } if (!safeSubtreeListMatch(node.superInterfaceTypes(), o.superInterfaceTypes())) { return false; } } return ((node.isInterface() == o.isInterface()) && safeSubtreeMatch(node.getJavadoc(), o.getJavadoc()) && safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations())); } /** * 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> */ public boolean match(TypeDeclarationStatement node, Object other) { if (!(other instanceof TypeDeclarationStatement)) { return false; } TypeDeclarationStatement o= (TypeDeclarationStatement)other; return safeSubtreeMatch(node.getDeclaration(), o.getDeclaration()); } /** * 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> */ public boolean match(TypeLiteral node, Object other) { if (!(other instanceof TypeLiteral)) { return false; } TypeLiteral o= (TypeLiteral)other; return safeSubtreeMatch(node.getType(), o.getType()); } /** * 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(TypeParameter node, Object other) { if (!(other instanceof TypeParameter)) { return false; } TypeParameter o= (TypeParameter)other; return safeSubtreeMatch(node.getName(), o.getName()) && safeSubtreeListMatch(node.typeBounds(), o.typeBounds()); } /** * 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> */ public boolean match(VariableDeclarationExpression node, Object other) { if (!(other instanceof VariableDeclarationExpression)) { return false; } VariableDeclarationExpression o= (VariableDeclarationExpression)other; int level= node.getAST().apiLevel; if (level == AST.JLS2_INTERNAL) { if (node.getModifiers() != o.getModifiers()) { return false; } } if (level >= AST.JLS3) { if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) { return false; } } return safeSubtreeMatch(node.getType(), o.getType()) && safeSubtreeListMatch(node.fragments(), o.fragments()); } /** * 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> * <p> * Note that extra array dimensions are compared since they are an important part of the type of * the variable. * </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> */ public boolean match(VariableDeclarationFragment node, Object other) { if (!(other instanceof VariableDeclarationFragment)) { return false; } VariableDeclarationFragment o= (VariableDeclarationFragment)other; return safeSubtreeMatch(node.getName(), o.getName()) && node.getExtraDimensions() == o.getExtraDimensions() && safeSubtreeMatch(node.getInitializer(), o.getInitializer()); } /** * 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> */ public boolean match(VariableDeclarationStatement node, Object other) { if (!(other instanceof VariableDeclarationStatement)) { return false; } VariableDeclarationStatement o= (VariableDeclarationStatement)other; int level= node.getAST().apiLevel; if (level == AST.JLS2_INTERNAL) { if (node.getModifiers() != o.getModifiers()) { return false; } } if (level >= AST.JLS3) { if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) { return false; } } return safeSubtreeMatch(node.getType(), o.getType()) && safeSubtreeListMatch(node.fragments(), o.fragments()); } /** * 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> */ public boolean match(WhileStatement node, Object other) { if (!(other instanceof WhileStatement)) { return false; } WhileStatement o= (WhileStatement)other; return (safeSubtreeMatch(node.getExpression(), o.getExpression()) && safeSubtreeMatch(node.getBody(), o.getBody())); } /** * 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(WildcardType node, Object other) { if (!(other instanceof WildcardType)) { return false; } WildcardType o= (WildcardType)other; return node.isUpperBound() == o.isUpperBound() && safeSubtreeMatch(node.getBound(), o.getBound()); } }