1 package net.sourceforge.phpdt.internal.compiler.ast;
 
   3 import net.sourceforge.phpdt.internal.compiler.parser.OutlineableWithChildren;
 
   4 import net.sourceforge.phpdt.internal.compiler.parser.Outlineable;
 
   5 import net.sourceforge.phpdt.internal.compiler.ast.declarations.VariableUsage;
 
   6 import net.sourceforge.phpdt.internal.ui.PHPUiImages;
 
   7 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
   8 import org.eclipse.jface.resource.ImageDescriptor;
 
   9 import org.eclipse.jface.text.Position;
 
  10 import org.eclipse.core.runtime.CoreException;
 
  12 import java.util.Hashtable;
 
  13 import java.util.Enumeration;
 
  14 import java.util.ArrayList;
 
  15 import java.util.List;
 
  17 import test.PHPParserSuperclass;
 
  20  * A Method declaration.
 
  21  * @author Matthieu Casanova
 
  23 public class MethodDeclaration extends Statement implements OutlineableWithChildren {
 
  25   /** The name of the method. */
 
  27   public Hashtable arguments;
 
  30   public Statement[] statements;
 
  32   public int bodyEnd = -1;
 
  33   /** Tell if the method is a class constructor. */
 
  34   public boolean isConstructor;
 
  36   /** The parent object. */
 
  37   private Object parent;
 
  38   /** The outlineable children (those will be in the node array too. */
 
  39   private ArrayList children = new ArrayList();
 
  41   /** Tell if the method returns a reference. */
 
  42   public boolean reference;
 
  44   private Position position;
 
  46   public MethodDeclaration(final Object parent,
 
  48                            final Hashtable arguments,
 
  49                            final boolean reference,
 
  50                            final int sourceStart,
 
  54     super(sourceStart, sourceEnd);
 
  56     this.arguments = arguments;
 
  58     this.reference = reference;
 
  59     this.bodyStart = bodyStart;
 
  60     this.bodyEnd = bodyEnd;
 
  61     position = new Position(sourceStart, sourceEnd);
 
  65    * Return method into String, with a number of tabs
 
  66    * @param tab the number of tabs
 
  67    * @return the String containing the method
 
  69   public String toString(final int tab) {
 
  70     final StringBuffer buff = new StringBuffer(tabString(tab));
 
  71     buff.append(toStringHeader());
 
  72     buff.append(toStringStatements(tab + 1));
 
  73     return buff.toString();
 
  76   public String toStringHeader() {
 
  77     return "function " + toString();
 
  81    * Return the statements of the method into Strings
 
  82    * @param tab the number of tabs
 
  83    * @return the String containing the statements
 
  85   public String toStringStatements(final int tab) {
 
  86     final StringBuffer buff = new StringBuffer(" {"); //$NON-NLS-1$
 
  87     if (statements != null) {
 
  88       for (int i = 0; i < statements.length; i++) {
 
  89         buff.append("\n").append(statements[i].toString(tab)); //$NON-NLS-1$
 
  90         if (!(statements[i] instanceof Block)) {
 
  91           buff.append(";"); //$NON-NLS-1$
 
  95     buff.append("\n").append(tabString(tab == 0 ? 0 : tab - 1)).append("}"); //$NON-NLS-2$ //$NON-NLS-1$
 
  96     return buff.toString();
 
 100    * Get the image of a class.
 
 101    * @return the image that represents a php class
 
 103   public ImageDescriptor getImage() {
 
 104     return PHPUiImages.DESC_FUN;
 
 107   public void setParent(final Object parent) {
 
 108     this.parent = parent;
 
 111   public Object getParent() {
 
 115   public boolean add(final Outlineable o) {
 
 116     return children.add(o);
 
 119   public Outlineable get(final int index) {
 
 120     return (Outlineable) children.get(index);
 
 124     return children.size();
 
 127   public String toString() {
 
 128     final StringBuffer buff = new StringBuffer();
 
 130       buff.append("&");//$NON-NLS-1$
 
 132     buff.append(name).append("(");//$NON-NLS-1$
 
 134     if (arguments != null) {
 
 135       final Enumeration values = arguments.elements();
 
 137       while (values.hasMoreElements()) {
 
 138         final VariableDeclaration o = (VariableDeclaration) values.nextElement();
 
 139         buff.append(o.toStringExpression());
 
 140         if (i != (arguments.size() - 1)) {
 
 141           buff.append(", "); //$NON-NLS-1$
 
 146     buff.append(")"); //$NON-NLS-1$
 
 147     return buff.toString();
 
 150   public Position getPosition() {
 
 154   public List getList() {
 
 159    * Get global variables (not parameters)
 
 160    * @return the variables from outside
 
 162   public List getOutsideVariable() {
 
 163     final ArrayList list = new ArrayList();
 
 165     if (statements != null) {
 
 166       for (int i = 0; i < statements.length; i++) {
 
 167         list.addAll(statements[i].getOutsideVariable());
 
 173   private List getParameters(final List list) {
 
 174     if (arguments != null) {
 
 175       final Enumeration vars = arguments.elements();
 
 176       while (vars.hasMoreElements()) {
 
 177         final VariableDeclaration variable = (VariableDeclaration) vars.nextElement();
 
 178         list.add(new VariableUsage(variable.name(), variable.sourceStart));
 
 185    * get the modified variables.
 
 186    * @return the variables from we change value
 
 188   public List getModifiedVariable() {
 
 189     final ArrayList list = new ArrayList();
 
 190     if (statements != null) {
 
 191       for (int i = 0; i < statements.length; i++) {
 
 192         list.addAll(statements[i].getModifiedVariable());
 
 199    * Get the variables used.
 
 200    * @return the variables used
 
 202   public List getUsedVariable() {
 
 203     final ArrayList list = new ArrayList();
 
 204     if (statements != null) {
 
 205       for (int i = 0; i < statements.length; i++) {
 
 206         list.addAll(statements[i].getUsedVariable());
 
 212   private boolean isVariableDeclaredBefore(List list, VariableUsage var) {
 
 213     final String name = var.getName();
 
 214     final int pos = var.getStartOffset();
 
 215     for (int i = 0; i < list.size(); i++) {
 
 216       VariableUsage variableUsage = (VariableUsage) list.get(i);
 
 217       if (variableUsage.getName().equals(name) && variableUsage.getStartOffset() < pos) {
 
 225    * This method will analyze the code.
 
 227   public void analyzeCode() {
 
 228     if (statements != null) {
 
 229       for (int i = 0; i < statements.length; i++) {
 
 230         statements[i].analyzeCode();
 
 235     final List globalsVars = getOutsideVariable();
 
 236     final List modifiedVars = getModifiedVariable();
 
 237     final List parameters = getParameters(new ArrayList());
 
 239     final List declaredVars = new ArrayList(globalsVars.size() + modifiedVars.size());
 
 240     declaredVars.addAll(globalsVars);
 
 241     declaredVars.addAll(modifiedVars);
 
 242     declaredVars.addAll(parameters);
 
 244     final List usedVars = getUsedVariable();
 
 245     final List readOrWriteVars = new ArrayList(modifiedVars.size()+usedVars.size());
 
 246     readOrWriteVars.addAll(modifiedVars);
 
 247     readOrWriteVars.addAll(usedVars);
 
 249     //look for used variables that were not declared before
 
 250     findUnusedParameters(readOrWriteVars,parameters);
 
 251     findUnknownUsedVars(usedVars, declaredVars);
 
 255    * This method will add a warning on all unused parameters.
 
 256    * @param vars the used variable list
 
 257    * @param parameters the declared variable list
 
 259   private void findUnusedParameters(final List vars, final List parameters) {
 
 260     for (int i = 0; i < parameters.size(); i++) {
 
 261       VariableUsage param = ((VariableUsage)parameters.get(i));
 
 262       if (!isVariableInList(param.getName(),vars)) {
 
 264           PHPParserSuperclass.setMarker("warning, the parameter "+param.getName() +" seems to be never used in your method",
 
 265                                         param.getStartOffset(),
 
 266                                         param.getStartOffset() + param.getName().length(),
 
 267                                         PHPParserSuperclass.WARNING,
 
 269         } catch (CoreException e) {
 
 270           PHPeclipsePlugin.log(e);
 
 276   private boolean isVariableInList(final String name, final List list) {
 
 277     for (int i = 0; i < list.size(); i++) {
 
 278       if (((VariableUsage) list.get(i)).getName().equals(name)) {
 
 286    * This method will add a warning on all used variables in a method that aren't declared before.
 
 287    * @param usedVars the used variable list
 
 288    * @param declaredVars the declared variable list
 
 290   private void findUnknownUsedVars(final List usedVars, final List declaredVars) {
 
 291     for (int i = 0; i < usedVars.size(); i++) {
 
 292       VariableUsage variableUsage = (VariableUsage) usedVars.get(i);
 
 293       if (variableUsage.getName().equals("this")) continue; // this is a special variable
 
 294       if (!isVariableDeclaredBefore(declaredVars, variableUsage)) {
 
 296           PHPParserSuperclass.setMarker("warning, usage of a variable that seems to be unassigned yet : " + variableUsage.getName(),
 
 297                                         variableUsage.getStartOffset(),
 
 298                                         variableUsage.getStartOffset() + variableUsage.getName().length(),
 
 299                                         PHPParserSuperclass.WARNING,
 
 301         } catch (CoreException e) {
 
 302           PHPeclipsePlugin.log(e);