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 class MethodDeclaration extends Statement implements OutlineableWithChildren {
24 /** The name of the method. */
26 public ArrayList arguments;
29 public Statement[] statements;
31 public 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 ArrayList children = new ArrayList();
40 /** Tell if the method returns a reference. */
41 public boolean reference;
43 private 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 public 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 public 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 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) {
158 public void getModifiedVariable(final List list) {
161 public void getUsedVariable(final List list) {
165 * Get global variables (not parameters).
167 public void getGlobalVariable(final List list) {
168 if (statements != null) {
169 for (int i = 0; i < statements.length; i++) {
170 statements[i].getOutsideVariable(list);
175 private void getParameters(final List list) {
176 if (arguments != null) {
177 for (int i = 0; i < arguments.size(); i++) {
178 VariableDeclaration variable = (VariableDeclaration) arguments.get(i);
179 list.add(new VariableUsage(variable.name(), variable.sourceStart));
185 * get the modified variables.
187 private void getAssignedVariableInCode(final List list) {
188 if (statements != null) {
189 for (int i = 0; i < statements.length; i++) {
190 statements[i].getModifiedVariable(list);
196 * Get the variables used.
198 private void getUsedVariableInCode(final List list) {
199 if (statements != null) {
200 for (int i = 0; i < statements.length; i++) {
201 statements[i].getUsedVariable(list);
206 private boolean isVariableDeclaredBefore(final List list, final VariableUsage var) {
207 final String name = var.getName();
208 final int pos = var.getStartOffset();
209 for (int i = 0; i < list.size(); i++) {
210 final VariableUsage variableUsage = (VariableUsage) list.get(i);
211 if (variableUsage.getName().equals(name) && variableUsage.getStartOffset() < pos) {
218 /** This method will analyze the code. */
219 public void analyzeCode() {
220 if (statements != null) {
221 for (int i = 0; i < statements.length; i++) {
222 statements[i].analyzeCode();
227 final List globalsVars = new ArrayList();
228 getGlobalVariable(globalsVars);
229 final List modifiedVars = new ArrayList();
230 getAssignedVariableInCode(modifiedVars);
231 final List parameters = new ArrayList();
232 getParameters(parameters);
234 final List declaredVars = new ArrayList(globalsVars.size() + modifiedVars.size());
235 declaredVars.addAll(globalsVars);
236 declaredVars.addAll(modifiedVars);
237 declaredVars.addAll(parameters);
239 final List usedVars = new ArrayList();
240 getUsedVariableInCode(usedVars);
241 final List readOrWriteVars = new ArrayList(modifiedVars.size() + usedVars.size());
242 readOrWriteVars.addAll(modifiedVars);
243 readOrWriteVars.addAll(usedVars);
245 //look for used variables that were not declared before
246 findUnusedParameters(readOrWriteVars, parameters);
247 findUnknownUsedVars(usedVars, declaredVars);
251 * This method will add a warning on all unused parameters.
252 * @param vars the used variable list
253 * @param parameters the declared variable list
255 private void findUnusedParameters(final List vars, final List parameters) {
256 for (int i = 0; i < parameters.size(); i++) {
257 final VariableUsage param = ((VariableUsage) parameters.get(i));
258 if (!isVariableInList(param.getName(), vars)) {
260 PHPParserSuperclass.setMarker(
261 "warning, the parameter " + param.getName() + " seems to be never used in your method",
262 param.getStartOffset(),
263 param.getStartOffset() + param.getName().length(),
264 PHPParserSuperclass.WARNING,
266 } catch (CoreException e) {
267 PHPeclipsePlugin.log(e);
273 private boolean isVariableInList(final String name, final List list) {
274 for (int i = 0; i < list.size(); i++) {
275 if (((VariableUsage) list.get(i)).getName().equals(name)) {
283 * This method will add a warning on all used variables in a method that aren't declared before.
284 * @param usedVars the used variable list
285 * @param declaredVars the declared variable list
287 private void findUnknownUsedVars(final List usedVars, final List declaredVars) {
288 for (int i = 0; i < usedVars.size(); i++) {
289 final VariableUsage variableUsage = (VariableUsage) usedVars.get(i);
290 if (variableUsage.getName().equals("this")) continue; // this is a special variable
291 if (!isVariableDeclaredBefore(declaredVars, variableUsage)) {
293 PHPParserSuperclass.setMarker(
294 "warning, usage of a variable that seems to be unassigned yet : " + variableUsage.getName(),
295 variableUsage.getStartOffset(),
296 variableUsage.getStartOffset() + variableUsage.getName().length(),
297 PHPParserSuperclass.WARNING,
299 } catch (CoreException e) {
300 PHPeclipsePlugin.log(e);