/******************************************************************************* * Copyright (c) 2013 Zend Technologies 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: * Zend Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.php.internal.core.compiler.ast.visitor; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.ast.ASTVisitor; import org.eclipse.dltk.ast.declarations.TypeDeclaration; import org.eclipse.dltk.ast.expressions.Expression; import org.eclipse.dltk.ast.statements.Block; import org.eclipse.php.core.compiler.ast.nodes.ClassDeclaration; import org.eclipse.php.core.compiler.ast.nodes.NamespaceDeclaration; /** * AST visitor optimized for finding type declarations in PHP source modules. * * <p> * Types are classes, interfaces and traits. Namespaces are not considered as * types in this implementation although {@link NamespaceDeclaration} extends * {@link TypeDeclaration} in the AST hierarchy. * </p> * * <p> * This visitor is optimized for performance to look not deeper than the * necessary level in the AST tree. It builds on the rule the classes in PHP * cannot be nested. Therefore, there is no sense to look inside a * {@link TypeDeclaration} for finding other {@link TypeDeclaration}s. * </p> * * @author Kaloyan Raev */ public abstract class TypeDeclarationVisitor extends ASTVisitor { /** * Flag that indicates that the visitor is traversing inside a * {@link TypeDeclaration}. */ private boolean insideType = false; /** * The visitor must always look into {@link Block}s. A block wraps * {@link ClassDeclaration} children and it must be traversed in order to * visit class' children. */ @Override public boolean visit(Expression s) throws Exception { return s instanceof Block || super.visit(s); } /** * The visitor must look into a {@link TypeDeclaration}s. If class, * interface or trait (i.e. different than {@link NamespaceDeclaration}) * then raise the {@link #insideType} flag. */ @Override public boolean visit(TypeDeclaration s) throws Exception { if (!(s instanceof NamespaceDeclaration)) { insideType = true; visitType(s); } // return true to make sure endVisit() will be called return true; } /** * Pull the {@link #insideType} flag down when ending visiting class, * interface or trait. */ @Override public boolean endvisit(TypeDeclaration s) throws Exception { if (!(s instanceof NamespaceDeclaration)) { insideType = false; } return false; } /** * Subclasses may implement this method to process the found * {@link TypeDeclaration} nodes. * * @param s * the visited AST node * @throws Exception */ public void visitType(TypeDeclaration s) throws Exception { // do nothing be default } /** * In all other cases the visitor must look deeper into the AST tree only * and if only it is outside of a <code>TypeDecalaration</code>. */ @Override public boolean visitGeneral(ASTNode node) throws Exception { return !insideType; } }