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,
51 final int sourceEnd) {
52 super(sourceStart, sourceEnd);
54 this.arguments = arguments;
56 this.reference = reference;
57 position = new Position(sourceStart, sourceEnd);
61 * Return method into String, with a number of tabs
62 * @param tab the number of tabs
63 * @return the String containing the method
65 public String toString(final int tab) {
66 final StringBuffer buff = new StringBuffer(tabString(tab));
67 buff.append(toStringHeader());
68 buff.append(toStringStatements(tab + 1));
69 return buff.toString();
72 public String toStringHeader() {
73 return "function " + toString();
77 * Return the statements of the method into Strings
78 * @param tab the number of tabs
79 * @return the String containing the statements
81 public String toStringStatements(final int tab) {
82 final StringBuffer buff = new StringBuffer(" {"); //$NON-NLS-1$
83 if (statements != null) {
84 for (int i = 0; i < statements.length; i++) {
85 buff.append("\n").append(statements[i].toString(tab)); //$NON-NLS-1$
86 if (!(statements[i] instanceof Block)) {
87 buff.append(";"); //$NON-NLS-1$
91 buff.append("\n").append(tabString(tab == 0 ? 0 : tab - 1)).append("}"); //$NON-NLS-2$ //$NON-NLS-1$
92 return buff.toString();
96 * Get the image of a class.
97 * @return the image that represents a php class
99 public ImageDescriptor getImage() {
100 return PHPUiImages.DESC_FUN;
103 public void setParent(final Object parent) {
104 this.parent = parent;
107 public Object getParent() {
111 public boolean add(final Outlineable o) {
112 return children.add(o);
115 public Outlineable get(final int index) {
116 return (Outlineable) children.get(index);
120 return children.size();
123 public String toString() {
124 final StringBuffer buff = new StringBuffer();
126 buff.append("&");//$NON-NLS-1$
128 buff.append(name).append("(");//$NON-NLS-1$
130 if (arguments != null) {
131 final Enumeration values = arguments.elements();
133 while (values.hasMoreElements()) {
134 final VariableDeclaration o = (VariableDeclaration) values.nextElement();
135 buff.append(o.toStringExpression());
136 if (i != (arguments.size() - 1)) {
137 buff.append(", "); //$NON-NLS-1$
142 buff.append(")"); //$NON-NLS-1$
143 return buff.toString();
146 public Position getPosition() {
150 public List getList() {
155 * Get the variables from outside (parameters, globals ...)
156 * @return the variables from outside
158 public List getOutsideVariable() {
159 final ArrayList list = new ArrayList();
160 if (arguments != null) {
161 final Enumeration vars = arguments.keys();
162 while (vars.hasMoreElements()) {
163 list.add(new VariableUsage((String) vars.nextElement(), getSourceStart()));
167 if (statements != null) {
168 for (int i = 0; i < statements.length; i++) {
169 list.addAll(statements[i].getOutsideVariable());
176 * get the modified variables.
177 * @return the variables from we change value
179 public List getModifiedVariable() {
180 final ArrayList list = new ArrayList();
181 if (statements != null) {
182 for (int i = 0; i < statements.length; i++) {
183 list.addAll(statements[i].getModifiedVariable());
190 * Get the variables used.
191 * @return the variables used
193 public List getUsedVariable() {
194 final ArrayList list = new ArrayList();
195 if (statements != null) {
196 for (int i = 0; i < statements.length; i++) {
197 list.addAll(statements[i].getUsedVariable());
203 private boolean isVariableDeclaredBefore(List list, VariableUsage var) {
204 final String name = var.getName();
205 final int pos = var.getStartOffset();
206 for (int i = 0; i < list.size(); i++) {
207 VariableUsage variableUsage = (VariableUsage) list.get(i);
208 if (variableUsage.getName().equals(name) && variableUsage.getStartOffset() < pos) {
215 private void dumpList(List list, String name) {
216 StringBuffer buff = new StringBuffer(name).append("\n");
217 for (int i = 0; i < list.size(); i++) {
218 buff.append(list.get(i).toString()).append("\n");
220 if (PHPeclipsePlugin.DEBUG) {
221 PHPeclipsePlugin.log(1, buff.toString());
226 * This method will analyze the code.
228 public void analyzeCode() {
229 final List outsideVars = getOutsideVariable();
230 final List modifiedVars = getModifiedVariable();
232 final List declaredVars = new ArrayList(outsideVars.size() + modifiedVars.size());
233 declaredVars.addAll(outsideVars);
234 declaredVars.addAll(modifiedVars);
236 final List usedVars = getUsedVariable();
238 /* dumpList(outsideVars, "outside");
239 dumpList(modifiedVars, "modified");
240 dumpList(usedVars, "used"); */
243 //look for used variables that were not declared before
244 findUnknownUsedVars(usedVars, declaredVars);
248 * This method will add a warning on all used variables in a method that aren't declared before.
249 * @param usedVars the used variable list
250 * @param declaredVars the declared variable list
252 private void findUnknownUsedVars(final List usedVars, final List declaredVars) {
253 for (int i = 0; i < usedVars.size(); i++) {
254 VariableUsage variableUsage = (VariableUsage) usedVars.get(i);
255 if (!isVariableDeclaredBefore(declaredVars, variableUsage)) {
257 PHPParserSuperclass.setMarker("warning, usage of an unknown variable : " + variableUsage.getName(),
258 variableUsage.getStartOffset(),
259 variableUsage.getStartOffset() + variableUsage.getName().length(),
260 PHPParserSuperclass.WARNING,
262 } catch (CoreException e) {
263 PHPeclipsePlugin.log(e);