001: // This file is part of KeY - Integrated Deductive Software Design
002: // Copyright (C) 2001-2007 Universitaet Karlsruhe, Germany
003: // Universitaet Koblenz-Landau, Germany
004: // Chalmers University of Technology, Sweden
005: //
006: // The KeY system is protected by the GNU General Public License.
007: // See LICENSE.TXT for details.
008: //
009: //
010:
011: package de.uka.ilkd.key.java.recoderext;
012:
013: import recoder.java.*;
014: import recoder.java.reference.*;
015: import recoder.java.statement.JavaStatement;
016: import recoder.list.ExpressionMutableList;
017:
018: /**
019: * A shortcut-statement for a method body.
020: */
021: public class MethodBodyStatement extends JavaStatement implements
022: TypeReferenceContainer, ExpressionContainer,
023: NamedProgramElement, ReferenceSuffix {
024:
025: /**
026: * the ast parent
027: */
028: private StatementContainer astParent;
029:
030: protected TypeReference bodySource;
031: protected Expression resultVar;
032:
033: private Identifier methodName;
034: private ReferencePrefix methodReferencePrefix;
035: private ExpressionMutableList arguments;
036:
037: /**
038: * Construct a method body shortcut
039: * @param bodySource exact class where the body is declared
040: * @param resultVar the Expression naming the variable to which
041: * the result of the mthod is assigned
042: * @param methRef MethodReference that represents the call
043: */
044:
045: public MethodBodyStatement(TypeReference bodySource,
046: Expression resultVar, MethodReference methRef) {
047: setBodySource(bodySource);
048: this .resultVar = resultVar;
049: setMethodReference(methRef);
050: makeParentRoleValid();
051: }
052:
053: /**
054: * Set the exact Class the denoted method body is from.
055: */
056:
057: public void setBodySource(TypeReference bodySource) {
058: this .bodySource = bodySource;
059: }
060:
061: /**
062: * Get the exact Class the denoted method body is from.
063: * @returns the TypeReference
064: */
065:
066: public TypeReference getBodySource() {
067: return bodySource;
068: }
069:
070: /**
071: * Set the result variable.
072: * @param resultVar the Expression used as result variable
073: */
074:
075: public void setResultVariable(Expression resultVar) {
076: this .resultVar = resultVar;
077: }
078:
079: /**
080: * Get the result variable.
081: * @return the VariableReference
082: */
083:
084: public Expression getResultVariable() {
085: return resultVar;
086: }
087:
088: /**
089: * Set the MethodReference that caused this call.
090: */
091: public void setMethodReference(MethodReference methRef) {
092: this .methodName = methRef.getIdentifier();
093: this .methodReferencePrefix = methRef.getReferencePrefix();
094: this .arguments = methRef.getArguments();
095: }
096:
097: public NonTerminalProgramElement getASTParent() {
098: return astParent;
099: }
100:
101: public StatementContainer getStatementContainer() {
102: return astParent;
103: }
104:
105: public void setStatementContainer(StatementContainer parent) {
106: astParent = parent;
107: }
108:
109: /**
110: * Finds the source element that occurs first in the source.
111: * @return the last source element in the syntactical representation of
112: * this element, may be equals to this element.
113: */
114:
115: public SourceElement getFirstElement() {
116: return getChildAt(0).getFirstElement();
117: }
118:
119: /**
120: * Finds the source element that occurs last in the source.
121: * @return the last source element in the syntactical representation of
122: * this element, may be equals to this element.
123: */
124:
125: public SourceElement getLastElement() {
126: return getChildAt(getChildCount() - 1).getLastElement();
127: }
128:
129: /**
130: * Returns the number of children of this node.
131: * @return an int giving the number of children of this node
132: */
133:
134: public int getChildCount() {
135: int result = 0;
136: if (bodySource != null)
137: result++;
138: if (resultVar != null)
139: result++;
140: if (methodReferencePrefix != null)
141: result++;
142: if (methodName != null)
143: result++;
144: if (arguments != null)
145: result += arguments.size();
146: return result;
147: }
148:
149: /**
150: * Returns the child at the specified index in this node's "virtual"
151: * child array
152: * @param index an index into this node's "virtual" child array
153: * @return the program element at the given position
154: * @exception ArrayIndexOutOfBoundsException if <tt>index</tt> is out
155: * of bounds
156: */
157:
158: public ProgramElement getChildAt(int index) {
159: if (bodySource != null) {
160: if (index == 0)
161: return bodySource;
162: index--;
163: }
164: if (resultVar != null) {
165: if (index == 0)
166: return resultVar;
167: index--;
168: }
169: if (methodReferencePrefix != null) {
170: if (index == 0)
171: return methodReferencePrefix;
172: index--;
173: }
174: if (methodName != null) {
175: if (index == 0)
176: return methodName;
177: index--;
178: }
179: if (arguments != null) {
180: return arguments.getExpression(index);
181: }
182: throw new ArrayIndexOutOfBoundsException();
183: }
184:
185: /**
186: * Get the number of type references in this container.
187: * @return the number of statements.
188: */
189:
190: public int getTypeReferenceCount() {
191: return (bodySource != null) ? 1 : 0;
192: }
193:
194: /**
195: * Return the type reference at the specified index in this node's
196: * "virtual" statement array.
197: * @param index an index for a type reference.
198: * @return the type reference with the given index.
199: * @exception ArrayIndexOutOfBoundsException if <tt>index</tt> is out
200: * of bounds.
201: */
202:
203: public TypeReference getTypeReferenceAt(int index) {
204: if (bodySource != null && index == 0) {
205: return bodySource;
206: }
207: throw new ArrayIndexOutOfBoundsException();
208: }
209:
210: /**
211: * Get the number of expressions in this container.
212: * @return the number of expressions.
213: */
214:
215: public int getExpressionCount() {
216: int result = 0;
217: if (resultVar != null) {
218: result++;
219: }
220: if (arguments != null) {
221: result += arguments.size();
222: }
223: return result;
224: }
225:
226: /**
227: * Return the expression at the specified index in this node's
228: * "virtual" expression array.
229: * @param index an index for a expression.
230: * @return the expression with the given index.
231: * @exception ArrayIndexOutOfBoundsException if <tt>index</tt> is out
232: * of bounds.
233: */
234: public Expression getExpressionAt(int index) {
235: if (resultVar != null) {
236: if (index == 0)
237: return resultVar;
238: index--;
239: }
240: if (arguments != null) {
241: return arguments.getExpression(index);
242: }
243: throw new ArrayIndexOutOfBoundsException();
244: }
245:
246: /**
247: * Replace a single child in the current node.
248: * The child to replace is matched by identity and hence must be known
249: * exactly. The replacement element can be null - in that case, the child
250: * is effectively removed.
251: * The parent role of the new child is validated, while the
252: * parent link of the replaced child is left untouched.
253: * @param p the old child.
254: * @param q the new child.
255: * @return true if a replacement has occured, false otherwise.
256: * @exception ClassCastException if the new child cannot take over
257: * the role of the old one.
258: */
259:
260: public boolean replaceChild(ProgramElement p, ProgramElement q) {
261: if (p == null)
262: throw new NullPointerException();
263: if (bodySource == p) {
264: TypeReference r = (TypeReference) q;
265: bodySource = r;
266: if (r != null) {
267: r.setParent(this );
268: }
269: return true;
270: } else if (resultVar == p) {
271: Expression r = (Expression) q;
272: resultVar = r;
273: if (r != null) {
274: r.setExpressionContainer(this );
275: }
276: return true;
277: } else if (methodReferencePrefix == p) {
278: ReferencePrefix rp = (ReferencePrefix) q;
279: methodReferencePrefix = rp;
280: return true;
281: } else if (methodName == p) {
282: Identifier id = (Identifier) q;
283: methodName = id;
284: return true;
285: } else {
286: for (int i = 0; i < arguments.size(); i++) {
287: if (arguments.getProgramElement(i) == p) {
288: if (q == null) {
289: arguments.remove(i);
290: } else {
291: Expression r = (Expression) q;
292: arguments.set(i, r);
293: r.setExpressionContainer(this );
294: }
295: return true;
296: }
297: }
298: }
299:
300: return false;
301: }
302:
303: /**
304: * Ensures that each child has "this" as syntactical parent.
305: */
306: public void makeParentRoleValid() {
307: super .makeParentRoleValid();
308:
309: if (bodySource != null) {
310: bodySource.setParent(this );
311: }
312:
313: if (resultVar != null) {
314: resultVar.setExpressionContainer(this );
315: }
316:
317: if (methodName != null) {
318: methodName.setParent(this );
319: }
320:
321: if (methodReferencePrefix != null) {
322: methodReferencePrefix.setReferenceSuffix(this );
323: }
324:
325: if (arguments != null) {
326: for (int i = 0, sz = arguments.size(); i < sz; i++) {
327: arguments.getExpression(i).setExpressionContainer(this );
328: }
329: }
330: }
331:
332: public int getChildPositionCode(ProgramElement child) {
333: // role 0: bodySource
334: // role 1: resultVar
335: // role 2: prefix
336: // others: arguments
337: if (bodySource == child) {
338: return 0;
339: }
340: if (resultVar == child) {
341: return 1;
342: }
343: if (methodReferencePrefix == child) {
344: return 2;
345: }
346: if (methodName == child) {
347: return 3;
348: }
349:
350: for (int i = 0, sz = arguments.size(); i < sz; i++) {
351: final Expression e = arguments.getExpression(i);
352: if (e == child) {
353: return i + 4;
354: }
355: }
356:
357: return -1;
358: }
359:
360: //don't think we need it
361: public void accept(SourceVisitor v) {
362: throw new IllegalStateException("Not implemented in "
363: + "MethodBodyStatement");
364: }
365:
366: //don't think we need it
367: public Object deepClone() {
368: throw new IllegalStateException("Not implemented in "
369: + "MethodBodyStatement");
370: }
371:
372: public String getName() {
373: StringBuffer args = new StringBuffer();
374: if (arguments != null) {
375: for (int i = 0; i < arguments.size(); i++) {
376: args.append(arguments.getExpression(i));
377: if (i != arguments.size() - 1) {
378: args.append(", ");
379: }
380: }
381: }
382: return getBodySource().getName() + "::" + getReferencePrefix()
383: + "." + getIdentifier().getText() + "(" + args + "):"
384: + resultVar;
385: }
386:
387: public ExpressionMutableList getArguments() {
388: return arguments;
389: }
390:
391: public void setArguments(ExpressionMutableList arguments) {
392: this .arguments = arguments;
393: }
394:
395: public Identifier getMethodName() {
396: return methodName;
397: }
398:
399: public void setMethodName(Identifier methodName) {
400: this .methodName = methodName;
401: }
402:
403: public ReferencePrefix getMethodReferencePrefix() {
404: return methodReferencePrefix;
405: }
406:
407: public void setMethodReferencePrefix(
408: ReferencePrefix methodReferencePrefix) {
409: this .methodReferencePrefix = methodReferencePrefix;
410: }
411:
412: public Identifier getIdentifier() {
413: return methodName;
414: }
415:
416: public void setIdentifier(Identifier name) {
417: this .methodName = name;
418: }
419:
420: public MethodReference getsMethodReference() {
421: return new MethodReference(methodReferencePrefix, methodName,
422: arguments);
423: }
424:
425: public ReferencePrefix getReferencePrefix() {
426: return methodReferencePrefix;
427: }
428:
429: }
|