1 package net.sourceforge.phpdt.internal.compiler.ast;
 
   3 import java.util.ArrayList;
 
   6 import net.sourceforge.phpdt.internal.compiler.ast.declarations.VariableUsage;
 
   7 import net.sourceforge.phpdt.internal.compiler.parser.Outlineable;
 
   8 import net.sourceforge.phpdt.internal.compiler.parser.OutlineableWithChildren;
 
   9 import net.sourceforge.phpdt.internal.ui.PHPUiImages;
 
  10 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
  12 import org.eclipse.core.runtime.CoreException;
 
  13 import org.eclipse.jface.resource.ImageDescriptor;
 
  14 import org.eclipse.jface.text.Position;
 
  16 import test.PHPParserSuperclass;
 
  19  * A Method declaration.
 
  20  * @author Matthieu Casanova
 
  22 public final class MethodDeclaration extends Statement implements OutlineableWithChildren {
 
  24   /** The name of the method. */
 
  25   public final String name;
 
  26   private final ArrayList arguments;
 
  29   public Statement[] statements;
 
  30   private final int bodyStart;
 
  31   private int bodyEnd = -1;
 
  32   /** Tell if the method is a class constructor. */
 
  33   public boolean isConstructor;
 
  35   /** The parent object. */
 
  36   private Object parent;
 
  37   /** The outlineable children (those will be in the node array too. */
 
  38   private final ArrayList children = new ArrayList();
 
  40   /** Tell if the method returns a reference. */
 
  41   private final boolean reference;
 
  43   private final Position position;
 
  45   public MethodDeclaration(final Object parent,
 
  47                            final ArrayList arguments,
 
  48                            final boolean reference,
 
  49                            final int sourceStart,
 
  53     super(sourceStart, sourceEnd);
 
  55     this.arguments = arguments;
 
  57     this.reference = reference;
 
  58     this.bodyStart = bodyStart;
 
  59     this.bodyEnd = bodyEnd;
 
  60     position = new Position(sourceStart, sourceEnd);
 
  64    * Return method into String, with a number of tabs
 
  65    * @param tab the number of tabs
 
  66    * @return the String containing the method
 
  68   public String toString(final int tab) {
 
  69     final StringBuffer buff = new StringBuffer(tabString(tab));
 
  70     buff.append(toStringHeader());
 
  71     buff.append(toStringStatements(tab + 1));
 
  72     return buff.toString();
 
  75   private String toStringHeader() {
 
  76     return "function " + toString();
 
  80    * Return the statements of the method into Strings
 
  81    * @param tab the number of tabs
 
  82    * @return the String containing the statements
 
  84   private String toStringStatements(final int tab) {
 
  85     final StringBuffer buff = new StringBuffer(" {"); //$NON-NLS-1$
 
  86     if (statements != null) {
 
  87       for (int i = 0; i < statements.length; i++) {
 
  88         buff.append("\n").append(statements[i].toString(tab)); //$NON-NLS-1$
 
  89         if (!(statements[i] instanceof Block)) {
 
  90           buff.append(";"); //$NON-NLS-1$
 
  94     buff.append("\n").append(tabString(tab == 0 ? 0 : tab - 1)).append("}"); //$NON-NLS-2$ //$NON-NLS-1$
 
  95     return buff.toString();
 
  99    * Get the image of a class.
 
 100    * @return the image that represents a php class
 
 102   public ImageDescriptor getImage() {
 
 103     return PHPUiImages.DESC_FUN;
 
 106   public void setParent(final Object parent) {
 
 107     this.parent = parent;
 
 110   public Object getParent() {
 
 114   public boolean add(final Outlineable o) {
 
 115     return children.add(o);
 
 118   public Outlineable get(final int index) {
 
 119     return (Outlineable) children.get(index);
 
 123     return children.size();
 
 126   public String toString() {
 
 127     final StringBuffer buff = new StringBuffer();
 
 129       buff.append("&");//$NON-NLS-1$
 
 131     buff.append(name).append("(");//$NON-NLS-1$
 
 133     if (arguments != null) {
 
 134       for (int i = 0; i < arguments.size(); i++) {
 
 135         final VariableDeclaration o =  (VariableDeclaration) arguments.get(i);
 
 136         buff.append(o.toStringExpression());
 
 137         if (i != (arguments.size() - 1)) {
 
 138           buff.append(", "); //$NON-NLS-1$
 
 142     buff.append(")"); //$NON-NLS-1$
 
 143     return buff.toString();
 
 146   public Position getPosition() {
 
 150   public List getList() {
 
 154   /** no outside variables. */
 
 155   public void getOutsideVariable(final List list) {}
 
 157   public void getModifiedVariable(final List list) {}
 
 159   public void getUsedVariable(final List list) {}
 
 162    * Get global variables (not parameters).
 
 164   private void getGlobalVariable(final List list) {
 
 165     if (statements != null) {
 
 166       for (int i = 0; i < statements.length; i++) {
 
 167         statements[i].getOutsideVariable(list);
 
 172   private void getParameters(final List list) {
 
 173     if (arguments != null) {
 
 174       for (int i = 0; i < arguments.size(); i++) {
 
 175         final VariableDeclaration variable = (VariableDeclaration) arguments.get(i);
 
 176         list.add(new VariableUsage(variable.name(), variable.sourceStart));
 
 182    * get the modified variables.
 
 184   private void getAssignedVariableInCode(final List list) {
 
 185     if (statements != null) {
 
 186       for (int i = 0; i < statements.length; i++) {
 
 187         statements[i].getModifiedVariable(list);
 
 193    * Get the variables used.
 
 195   private void getUsedVariableInCode(final List list) {
 
 196     if (statements != null) {
 
 197       for (int i = 0; i < statements.length; i++) {
 
 198         statements[i].getUsedVariable(list);
 
 203   private static boolean isVariableDeclaredBefore(final List list, final VariableUsage var) {
 
 204     final String name = var.getName();
 
 205     final int pos = var.getStartOffset();
 
 206     for (int i = 0; i < list.size(); i++) {
 
 207       final VariableUsage variableUsage = (VariableUsage) list.get(i);
 
 208       if (variableUsage.getName().equals(name) && variableUsage.getStartOffset() < pos) {
 
 215   /** This method will analyze the code. */
 
 216   public void analyzeCode() {
 
 217     if (statements != null) {
 
 218       for (int i = 0; i < statements.length; i++) {
 
 219         statements[i].analyzeCode();
 
 224     final List globalsVars = new ArrayList();
 
 225     getGlobalVariable(globalsVars);
 
 226     final List modifiedVars = new ArrayList();
 
 227     getAssignedVariableInCode(modifiedVars);
 
 228     final List parameters = new ArrayList(arguments.size());
 
 229     getParameters(parameters);
 
 231     final List declaredVars = new ArrayList(globalsVars.size() + modifiedVars.size());
 
 232     declaredVars.addAll(globalsVars);
 
 233     declaredVars.addAll(modifiedVars);
 
 234     declaredVars.addAll(parameters);
 
 236     final List usedVars = new ArrayList();
 
 237     getUsedVariableInCode(usedVars);
 
 238     final List readOrWriteVars = new ArrayList(modifiedVars.size() + usedVars.size());
 
 239     readOrWriteVars.addAll(modifiedVars);
 
 240     readOrWriteVars.addAll(usedVars);
 
 242     //look for used variables that were not declared before
 
 243     findUnusedParameters(readOrWriteVars, parameters);
 
 244     findUnknownUsedVars(usedVars, declaredVars);
 
 248    * This method will add a warning on all unused parameters.
 
 249    * @param vars the used variable list
 
 250    * @param parameters the declared variable list
 
 252   private static void findUnusedParameters(final List vars, final List parameters) {
 
 253     for (int i = 0; i < parameters.size(); i++) {
 
 254       final VariableUsage param = (VariableUsage) parameters.get(i);
 
 255       if (!isVariableInList(param.getName(), vars)) {
 
 257           PHPParserSuperclass.setMarker(
 
 258                   "warning, the parameter " + param.getName() + " seems to be never used in your method",
 
 259                   param.getStartOffset(),
 
 260                   param.getStartOffset() + param.getName().length(),
 
 261                   PHPParserSuperclass.WARNING,
 
 263         } catch (CoreException e) {
 
 264           PHPeclipsePlugin.log(e);
 
 270   private static boolean isVariableInList(final String name, final List list) {
 
 271     for (int i = 0; i < list.size(); i++) {
 
 272       if (((VariableUsage) list.get(i)).getName().equals(name)) {
 
 280    * This method will add a warning on all used variables in a method that aren't declared before.
 
 281    * @param usedVars the used variable list
 
 282    * @param declaredVars the declared variable list
 
 284   private static void findUnknownUsedVars(final List usedVars, final List declaredVars) {
 
 285     for (int i = 0; i < usedVars.size(); i++) {
 
 286       final VariableUsage variableUsage = (VariableUsage) usedVars.get(i);
 
 287       if ("this".equals(variableUsage.getName())) continue; // this is a special variable
 
 288       if (!isVariableDeclaredBefore(declaredVars, variableUsage)) {
 
 290           PHPParserSuperclass.setMarker(
 
 291                   "warning, usage of a variable that seems to be unassigned yet : " + variableUsage.getName(),
 
 292                   variableUsage.getStartOffset(),
 
 293                   variableUsage.getStartOffset() + variableUsage.getName().length(),
 
 294                   PHPParserSuperclass.WARNING,
 
 296         } catch (CoreException e) {
 
 297           PHPeclipsePlugin.log(e);