/******************************************************************************* * 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 org.eclipse.php.internal.core.corext.dom; import java.util.HashSet; import java.util.Set; import org.eclipse.core.runtime.Assert; import org.eclipse.php.core.ast.nodes.*; import org.eclipse.php.core.ast.visitor.AbstractVisitor; public class LocalVariableIndex extends AbstractVisitor { private int fTopIndex; // in case we are in the program scope // we don't want to descend into function/class/interface scope private static boolean isProgramScope = false; private final Set<String> variablesSet = new HashSet<String>(); /** * Computes the maximum number of local variable declarations in the given * body declaration. * * @param node * the body declaration. Must either be a method declaration or * an initializer. * @return the maximum number of local variables */ public static int perform(ASTNode node) { Assert.isTrue(node != null); switch (node.getType()) { case ASTNode.METHOD_DECLARATION: isProgramScope = false; return internalPerform(((MethodDeclaration) node).getFunction()); case ASTNode.FUNCTION_DECLARATION: isProgramScope = false; return internalPerform((FunctionDeclaration) node); case ASTNode.PROGRAM: isProgramScope = true; return internalPerform((Program) node); default: Assert.isTrue(false); } return -1; } private static int internalPerform(ASTNode node) { LocalVariableIndex counter = new LocalVariableIndex(); node.accept(counter); return counter.fTopIndex; } /** * Insert to the variables Name set each variable that is first encountered * in the flow */ public boolean visit(Variable variable) { Expression name = variable.getName(); if ((variable.isDollared() || ASTNodes.isQuotedDollaredCurlied(variable)) && name.getType() == ASTNode.IDENTIFIER) { String variableName = ((Identifier) name).getName(); if (!variableName.equalsIgnoreCase("this") //$NON-NLS-1$ && !variablesSet.contains(variableName)) { variablesSet.add(variableName); handleVariableBinding(); } } return true; } public boolean visit(FunctionDeclaration function) { return !isProgramScope; } public boolean visit(ClassDeclaration classDeclaration) { return !isProgramScope; } public boolean visit(TraitDeclaration classDeclaration) { return !isProgramScope; } public boolean visit(InterfaceDeclaration interfaceDeclaration) { return !isProgramScope; } private void handleVariableBinding() { // TODO - check if the workaround works properly // fTopIndex = Math.max(fTopIndex, binding.getVariableId()); fTopIndex = variablesSet.size(); } }