/******************************************************************************* * 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.search; import java.util.List; import org2.eclipse.php.internal.core.ast.nodes.*; /** * A global variable occurrences finder. * * @author shalom */ public class GlobalVariableOccurrencesFinder extends AbstractOccurrencesFinder { public static final String ID = "GlobalVariableOccurrencesFinder"; //$NON-NLS-1$ private String globalName; private boolean isGlobalScope; /** * @param root * the AST root * @param node * the selected node (must be an {@link Identifier} or * {@link Scalar} instance) * @return returns a message if there is a problem */ public String initialize(Program root, ASTNode node) { fASTRoot = root; isGlobalScope = true; if (node.getType() == ASTNode.SCALAR) { // We have a scalar inside a GLOBALS array. // For example: $GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b']; globalName = ((Scalar) node).getStringValue(); if (globalName.length() > 2 && isQuated(globalName)) { globalName = globalName.substring(1, globalName.length() - 1); } return null; } if (node.getType() == ASTNode.IDENTIFIER) { globalName = ((Identifier) node).getName(); return null; } fDescription = "OccurrencesFinder_occurrence_description"; //$NON-NLS-1$ return fDescription; } /* * (non-Javadoc) * * @see * org2.eclipse.php.internal.ui.search.AbstractOccurrencesFinder#findOccurrences * () */ protected void findOccurrences() { fDescription = Messages.format(BASE_DESCRIPTION, '$' + globalName); fASTRoot.accept(this); } /** * class declaration */ public boolean visit(ClassDeclaration classDeclaration) { setGlobalScope(false); return true; } public void endVisit(ClassDeclaration classDeclaration) { setGlobalScope(true); } /** * change the name of the function */ public boolean visit(FunctionDeclaration functionDeclaration) { setGlobalScope(false); return true; } public void endVisit(FunctionDeclaration functionDeclaration) { setGlobalScope(true); } public boolean visit(InterfaceDeclaration interfaceDeclaration) { setGlobalScope(false); return true; } public void endVisit(InterfaceDeclaration interfaceDeclaration) { setGlobalScope(true); } public boolean visit(FieldsDeclaration fieldDeclaration) { setGlobalScope(false); return true; } public void endVisit(FieldsDeclaration fieldsDeclaration) { setGlobalScope(true); } /** * Visit $a on global references: $a = 5; */ public boolean visit(Variable variable) { if (!(variable.getParent() instanceof StaticDispatch) && variable.isDollared() && variable.getName().getType() == ASTNode.IDENTIFIER) { Identifier identifier = (Identifier) variable.getName(); if (isGlobalScope && globalName.equals(identifier.getName())) { addOccurrence(variable); } } return true; } /** * Make sure we mark the occurrences when selecting a scalar inside a * GLOBALS array access. */ public boolean visit(Scalar scalar) { String stringValue = scalar.getStringValue(); if (stringValue.length() > 2 && isQuated(stringValue)) { stringValue = stringValue.substring(1, stringValue.length() - 1); } if (globalName.equals(stringValue)) { ASTNode parent = scalar.getParent(); if (parent.getType() == ASTNode.ARRAY_ACCESS) { Expression variableName = ((ArrayAccess) parent).getName(); if (variableName.getType() == ASTNode.VARIABLE) { final Variable var = (Variable) variableName; Expression varName = var.getName(); if (var.isDollared() && varName.getType() == ASTNode.IDENTIFIER) { final String name = ((Identifier) varName).getName(); if ("GLOBALS".equals(name) || "_GLOBALS".equals(name)) { //$NON-NLS-1$ //$NON-NLS-2$ addOccurrence(scalar); } } } } } return true; } /** * Visit $a on global references (on function/methods) : ...global $a;$a = * 5;... */ public boolean visit(GlobalStatement globalStatement) { final List<Variable> variables = globalStatement.variables(); for (final Variable variable : variables) { if (variable.isDollared()) { Identifier identifier = (Identifier) variable.getName(); if (globalName.equals(identifier.getName())) { addOccurrence(variable); setGlobalScope(true); } } } return true; } /** * Visit $GLOBALS['variableName'] occurrences */ public boolean visit(ArrayAccess arrayAccess) { // check the case of $GLOBALS['var'] final Expression variableName = arrayAccess.getName(); if (variableName.getType() == ASTNode.VARIABLE) { final Variable var = (Variable) variableName; Expression varName = var.getName(); if (var.isDollared() && varName.getType() == ASTNode.IDENTIFIER) { final Identifier id = (Identifier) varName; if (id.getName().equals("GLOBALS")) { //$NON-NLS-1$ final Expression index = arrayAccess.getIndex(); if (index != null && index.getType() == ASTNode.SCALAR) { Scalar scalar = (Scalar) index; final String stringValue = scalar.getStringValue(); if (stringValue.length() > 2 && isQuated(stringValue)) { if (globalName.equals(stringValue.substring(1, stringValue.length() - 1))) { addOccurrence(scalar); } } } } } } return true; } private boolean isQuated(String stringValue) { char first = stringValue.charAt(0); char last = stringValue.charAt(stringValue.length() - 1); return (first == '\'' && last == '\'' || first == '\"' && last == '\"'); } private void addOccurrence(ASTNode node) { int readWriteType = getOccurrenceType(node); String desc = fDescription; if (readWriteType == IOccurrencesFinder.F_WRITE_OCCURRENCE) { desc = Messages.format(BASE_WRITE_DESCRIPTION, '$' + globalName); } fResult.add(new OccurrenceLocation(node.getStart(), node.getLength(), readWriteType, desc)); } /* * (non-Javadoc) * * @see org2.eclipse.php.internal.ui.search.AbstractOccurrencesFinder# * getOccurrenceReadWriteType * (org2.eclipse.php.internal.core.ast.nodes.ASTNode) */ protected int getOccurrenceType(ASTNode node) { if (node.getType() == ASTNode.VARIABLE) { Variable variable = (Variable) node; ASTNode parent = variable.getParent(); int parentType = parent.getType(); if (parentType == ASTNode.ASSIGNMENT) { Assignment assignment = (Assignment) parent; if (assignment.getLeftHandSide() == node) { return IOccurrencesFinder.F_WRITE_OCCURRENCE; } } else if (parentType == ASTNode.POSTFIX_EXPRESSION || parentType == ASTNode.PREFIX_EXPRESSION || parentType == ASTNode.CATCH_CLAUSE) { return IOccurrencesFinder.F_WRITE_OCCURRENCE; } else if (parentType == ASTNode.FOR_EACH_STATEMENT) { if (variable.getLocationInParent() != ForEachStatement.EXPRESSION_PROPERTY) { return IOccurrencesFinder.F_WRITE_OCCURRENCE; } } } return IOccurrencesFinder.F_READ_OCCURRENCE; } /* * (non-Javadoc) * * @see * org2.eclipse.php.internal.ui.search.IOccurrencesFinder#getElementName() */ public String getElementName() { return globalName; } /* * (non-Javadoc) * * @see org2.eclipse.php.internal.ui.search.IOccurrencesFinder#getID() */ public String getID() { return ID; } /** * @param isGlobalScope * the isGlobalScope to set */ public void setGlobalScope(boolean isGlobalScope) { this.isGlobalScope = isGlobalScope; } }