001: /*
002: * Spoon - http://spoon.gforge.inria.fr/
003: * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
004: *
005: * This software is governed by the CeCILL-C License under French law and
006: * abiding by the rules of distribution of free software. You can use, modify
007: * and/or redistribute the software under the terms of the CeCILL-C license as
008: * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
009: *
010: * This program is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
013: *
014: * The fact that you are presently reading this means that you have had
015: * knowledge of the CeCILL-C license and that you accept its terms.
016: */
017:
018: package spoon.support.reflect.eval;
019:
020: import java.lang.annotation.Annotation;
021: import java.util.ArrayList;
022: import java.util.List;
023:
024: import spoon.reflect.code.BinaryOperatorKind;
025: import spoon.reflect.code.CtArrayAccess;
026: import spoon.reflect.code.CtAssert;
027: import spoon.reflect.code.CtAssignment;
028: import spoon.reflect.code.CtBinaryOperator;
029: import spoon.reflect.code.CtBlock;
030: import spoon.reflect.code.CtBreak;
031: import spoon.reflect.code.CtCase;
032: import spoon.reflect.code.CtCatch;
033: import spoon.reflect.code.CtCodeElement;
034: import spoon.reflect.code.CtCodeSnippetExpression;
035: import spoon.reflect.code.CtCodeSnippetStatement;
036: import spoon.reflect.code.CtConditional;
037: import spoon.reflect.code.CtContinue;
038: import spoon.reflect.code.CtDo;
039: import spoon.reflect.code.CtExpression;
040: import spoon.reflect.code.CtFieldAccess;
041: import spoon.reflect.code.CtFor;
042: import spoon.reflect.code.CtForEach;
043: import spoon.reflect.code.CtIf;
044: import spoon.reflect.code.CtInvocation;
045: import spoon.reflect.code.CtLiteral;
046: import spoon.reflect.code.CtLocalVariable;
047: import spoon.reflect.code.CtNewArray;
048: import spoon.reflect.code.CtNewClass;
049: import spoon.reflect.code.CtOperatorAssignment;
050: import spoon.reflect.code.CtReturn;
051: import spoon.reflect.code.CtStatement;
052: import spoon.reflect.code.CtStatementList;
053: import spoon.reflect.code.CtSwitch;
054: import spoon.reflect.code.CtSynchronized;
055: import spoon.reflect.code.CtTargetedExpression;
056: import spoon.reflect.code.CtThrow;
057: import spoon.reflect.code.CtTry;
058: import spoon.reflect.code.CtUnaryOperator;
059: import spoon.reflect.code.CtVariableAccess;
060: import spoon.reflect.code.CtWhile;
061: import spoon.reflect.declaration.CtAnnotation;
062: import spoon.reflect.declaration.CtAnnotationType;
063: import spoon.reflect.declaration.CtAnonymousExecutable;
064: import spoon.reflect.declaration.CtClass;
065: import spoon.reflect.declaration.CtConstructor;
066: import spoon.reflect.declaration.CtElement;
067: import spoon.reflect.declaration.CtEnum;
068: import spoon.reflect.declaration.CtExecutable;
069: import spoon.reflect.declaration.CtField;
070: import spoon.reflect.declaration.CtInterface;
071: import spoon.reflect.declaration.CtMethod;
072: import spoon.reflect.declaration.CtPackage;
073: import spoon.reflect.declaration.CtParameter;
074: import spoon.reflect.declaration.CtSimpleType;
075: import spoon.reflect.declaration.CtTypeParameter;
076: import spoon.reflect.declaration.CtTypedElement;
077: import spoon.reflect.declaration.CtVariable;
078: import spoon.reflect.declaration.ModifierKind;
079: import spoon.reflect.eval.PartialEvaluator;
080: import spoon.reflect.reference.CtArrayTypeReference;
081: import spoon.reflect.reference.CtExecutableReference;
082: import spoon.reflect.reference.CtFieldReference;
083: import spoon.reflect.reference.CtGenericElementReference;
084: import spoon.reflect.reference.CtLocalVariableReference;
085: import spoon.reflect.reference.CtPackageReference;
086: import spoon.reflect.reference.CtParameterReference;
087: import spoon.reflect.reference.CtReference;
088: import spoon.reflect.reference.CtTypeParameterReference;
089: import spoon.reflect.reference.CtTypeReference;
090: import spoon.reflect.reference.CtVariableReference;
091: import spoon.reflect.visitor.CtVisitor;
092: import spoon.support.util.RtHelper;
093:
094: /**
095: * This visitor implements a simple partial evaluator for the program
096: * compile-time metamodel.
097: */
098: public class VisitorPartialEvaluator implements CtVisitor,
099: PartialEvaluator {
100:
101: boolean flowEnded = false;
102:
103: CtCodeElement result;
104:
105: Number convert(CtTypeReference<?> type, Number n) {
106: if ((type.getActualClass() == int.class)
107: || (type.getActualClass() == Integer.class)) {
108: return n.intValue();
109: }
110: if ((type.getActualClass() == byte.class)
111: || (type.getActualClass() == Byte.class)) {
112: return n.byteValue();
113: }
114: if ((type.getActualClass() == long.class)
115: || (type.getActualClass() == Long.class)) {
116: return n.longValue();
117: }
118: if ((type.getActualClass() == float.class)
119: || (type.getActualClass() == Float.class)) {
120: return n.floatValue();
121: }
122: if ((type.getActualClass() == short.class)
123: || (type.getActualClass() == Short.class)) {
124: return n.shortValue();
125: }
126: return n;
127: }
128:
129: @SuppressWarnings("unchecked")
130: public <R extends CtCodeElement> R evaluate(CtElement parent,
131: R element) {
132: if (element == null) {
133: return null;
134: }
135: element.accept(this );
136: if (result != null) {
137: result.setParent(parent);
138: }
139: return (R) result;
140: }
141:
142: void setResult(CtCodeElement element) {
143: result = element;
144: }
145:
146: public <T> void visitCtCodeSnippetExpression(
147: CtCodeSnippetExpression<T> expression) {
148: }
149:
150: public void visitCtCodeSnippetStatement(
151: CtCodeSnippetStatement statement) {
152: }
153:
154: public <A extends Annotation> void visitCtAnnotation(
155: CtAnnotation<A> annotation) {
156: throw new RuntimeException("Unknow Element");
157: }
158:
159: public <A extends Annotation> void visitCtAnnotationType(
160: CtAnnotationType<A> annotationType) {
161: throw new RuntimeException("Unknow Element");
162: }
163:
164: public void visitCtAnonymousExecutable(CtAnonymousExecutable impl) {
165: throw new RuntimeException("Unknow Element");
166: }
167:
168: public <T, E extends CtExpression<?>> void visitCtArrayAccess(
169: CtArrayAccess<T, E> arrayAccess) {
170: setResult(arrayAccess.getFactory().Core().clone(arrayAccess));
171: }
172:
173: public <T> void visitCtArrayTypeReference(
174: CtArrayTypeReference<T> reference) {
175: throw new RuntimeException("Unknow Element");
176: }
177:
178: public <T> void visitCtAssert(CtAssert<T> asserted) {
179: throw new RuntimeException("Unknow Element");
180: }
181:
182: @SuppressWarnings("unchecked")
183: public <T> void visitCtBinaryOperator(CtBinaryOperator<T> operator) {
184: CtExpression<?> left = evaluate(operator, operator
185: .getLeftHandOperand());
186: CtExpression<?> right = evaluate(operator, operator
187: .getRightHandOperand());
188: if ((left instanceof CtLiteral) && (right instanceof CtLiteral)) {
189: Object leftObject = ((CtLiteral<?>) left).getValue();
190: Object rightObject = ((CtLiteral<?>) right).getValue();
191: CtLiteral<Object> res = operator.getFactory().Core()
192: .createLiteral();
193: switch (operator.getKind()) {
194: case AND:
195: res.setValue((Boolean) leftObject
196: && (Boolean) rightObject);
197: break;
198: case OR:
199: res.setValue((Boolean) leftObject
200: || (Boolean) rightObject);
201: break;
202: case EQ:
203: if (leftObject == null) {
204: res.setValue(leftObject == rightObject);
205: } else {
206: res.setValue(leftObject.equals(rightObject));
207: }
208: break;
209: case NE:
210: if (leftObject == null) {
211: res.setValue(leftObject != rightObject);
212: } else {
213: res.setValue(!leftObject.equals(rightObject));
214: }
215: break;
216: case GE:
217: res
218: .setValue(((Number) leftObject).doubleValue() >= ((Number) rightObject)
219: .doubleValue());
220: break;
221: case LE:
222: res
223: .setValue(((Number) leftObject).doubleValue() <= ((Number) rightObject)
224: .doubleValue());
225: break;
226: case GT:
227: res
228: .setValue(((Number) leftObject).doubleValue() > ((Number) rightObject)
229: .doubleValue());
230: break;
231: case LT:
232: res
233: .setValue(((Number) leftObject).doubleValue() < ((Number) rightObject)
234: .doubleValue());
235: break;
236: case MINUS:
237: res
238: .setValue(convert(operator.getType(),
239: ((Number) leftObject).doubleValue()
240: - ((Number) rightObject)
241: .doubleValue()));
242: break;
243: case MUL:
244: res
245: .setValue(convert(operator.getType(),
246: ((Number) leftObject).doubleValue()
247: * ((Number) rightObject)
248: .doubleValue()));
249: break;
250: case DIV:
251: res
252: .setValue(convert(operator.getType(),
253: ((Number) leftObject).doubleValue()
254: / ((Number) rightObject)
255: .doubleValue()));
256: break;
257: case PLUS:
258: if ((leftObject instanceof String)
259: || (rightObject instanceof String)) {
260: res.setValue("" + leftObject + rightObject);
261: } else {
262: res.setValue(convert(operator.getType(),
263: ((Number) leftObject).doubleValue()
264: + ((Number) rightObject)
265: .doubleValue()));
266: }
267: break;
268: case BITAND:
269: if (leftObject instanceof Boolean) {
270: res.setValue(((Boolean) leftObject).booleanValue()
271: & ((Boolean) rightObject).booleanValue());
272: } else {
273: res.setValue(((Number) leftObject).intValue()
274: & ((Number) rightObject).intValue());
275: }
276: break;
277: case BITOR:
278: if (leftObject instanceof Boolean) {
279: res.setValue(((Boolean) leftObject).booleanValue()
280: | ((Boolean) rightObject).booleanValue());
281: } else {
282: res.setValue(((Number) leftObject).intValue()
283: | ((Number) rightObject).intValue());
284: }
285: break;
286: case BITXOR:
287: if (leftObject instanceof Boolean) {
288: res.setValue(((Boolean) leftObject).booleanValue()
289: ^ ((Boolean) rightObject).booleanValue());
290: } else {
291: res.setValue(((Number) leftObject).intValue()
292: ^ ((Number) rightObject).intValue());
293: }
294: break;
295: default:
296: throw new RuntimeException("unsupported operator "
297: + operator.getKind());
298: }
299: setResult(res);
300: return;
301: } else if (operator.getKind() == BinaryOperatorKind.INSTANCEOF) {
302: CtLiteral<Boolean> res = operator.getFactory().Core()
303: .createLiteral();
304: CtTypeReference<?> leftType = ((CtTypedElement<?>) left)
305: .getType().box();
306: CtTypeReference<?> rightType = ((CtLiteral<CtTypeReference<?>>) right)
307: .getValue();
308: if (leftType.isSubtypeOf(rightType)) {
309: res.setValue(true);
310: setResult(res);
311: }
312: return;
313: } else if ((left instanceof CtLiteral)
314: || (right instanceof CtLiteral)) {
315: CtLiteral<?> literal;
316: CtExpression expr;
317: if (left instanceof CtLiteral) {
318: literal = (CtLiteral<?>) left;
319: expr = right;
320: } else {
321: literal = (CtLiteral<?>) right;
322: expr = left;
323: }
324: Object o = literal.getValue();
325: CtLiteral<Object> res = operator.getFactory().Core()
326: .createLiteral();
327: switch (operator.getKind()) {
328: case AND:
329: if ((Boolean) o) {
330: setResult(expr);
331: } else {
332: res.setValue(false);
333: setResult(res);
334: }
335: return;
336: case OR:
337: if ((Boolean) o) {
338: res.setValue(true);
339: setResult(res);
340: } else {
341: setResult(expr);
342: }
343: return;
344: case BITOR:
345: if ((o instanceof Boolean)
346: && ((Boolean) o).booleanValue()) {
347: res.setValue(true);
348: setResult(res);
349: }
350: return;
351: }
352: }
353: CtBinaryOperator<T> op = operator.getFactory().Core()
354: .createBinaryOperator();
355: op.setKind(operator.getKind());
356: op.setLeftHandOperand(left);
357: left.setParent(op);
358: op.setRightHandOperand(right);
359: right.setParent(op);
360: op.setType(operator.getType());
361: setResult(op);
362: }
363:
364: public <R> void visitCtBlock(CtBlock<R> block) {
365: CtBlock<?> b = block.getFactory().Core().createBlock();
366: for (CtStatement s : block.getStatements()) {
367: CtStatement res = evaluate(b, s);
368: if (res != null) {
369: b.getStatements().add(res);
370: }
371: // do not copy unreachable statements
372: if (flowEnded) {
373: break;
374: }
375: }
376: if ((b.getStatements().size() == 1)
377: && (b.getStatements().get(0) instanceof CtBlock)) {
378: setResult(b.getStatements().get(0));
379: } else {
380: setResult(b);
381: }
382: }
383:
384: public void visitCtBreak(CtBreak breakStatement) {
385: setResult(breakStatement.getFactory().Core().clone(
386: breakStatement));
387: }
388:
389: public <E> void visitCtCase(CtCase<E> caseStatement) {
390: throw new RuntimeException("Unknow Element");
391: }
392:
393: public void visitCtCatch(CtCatch catchBlock) {
394: setResult(catchBlock.getFactory().Core().clone(catchBlock));
395: }
396:
397: public <T> void visitCtClass(CtClass<T> ctClass) {
398: throw new RuntimeException("Unknow Element");
399: }
400:
401: public <T> void visitCtConstructor(CtConstructor<T> c) {
402: throw new RuntimeException("Unknow Element");
403: }
404:
405: public void visitCtContinue(CtContinue continueStatement) {
406: setResult(continueStatement.getFactory().Core().clone(
407: continueStatement));
408: }
409:
410: public void visitCtDo(CtDo doLoop) {
411: CtDo w = doLoop.getFactory().Core().clone(doLoop);
412: w.setLoopingExpression(evaluate(w, doLoop
413: .getLoopingExpression()));
414: w.setBody(evaluate(w, doLoop.getBody()));
415: setResult(w);
416: }
417:
418: public <T extends Enum<?>> void visitCtEnum(CtEnum<T> ctEnum) {
419: throw new RuntimeException("Unknow Element");
420: }
421:
422: public <T> void visitCtExecutableReference(
423: CtExecutableReference<T> reference) {
424: throw new RuntimeException("Unknow Element");
425: }
426:
427: public void visitCtExpression(CtExpression<?> expression) {
428: throw new RuntimeException("Unknow Element");
429: }
430:
431: public <T> void visitCtField(CtField<T> f) {
432: throw new RuntimeException("Unknow Element");
433: }
434:
435: public <T> void visitCtFieldAccess(CtFieldAccess<T> fieldAccess) {
436: if (fieldAccess.getVariable().getSimpleName().equals("class")) {
437: Class<?> c = fieldAccess.getVariable().getDeclaringType()
438: .getActualClass();
439: if (c != null) {
440: CtLiteral<Class<?>> l = fieldAccess.getFactory().Core()
441: .createLiteral();
442: l.setValue(c);
443: setResult(l);
444: return;
445: }
446: }
447: if (fieldAccess.getFactory().Type().createReference(Enum.class)
448: .isAssignableFrom(
449: fieldAccess.getVariable().getDeclaringType())) {
450: CtLiteral<CtFieldReference<?>> l = fieldAccess.getFactory()
451: .Core().createLiteral();
452: l.setValue(fieldAccess.getVariable());
453: setResult(l);
454: return;
455: }
456: CtField<?> f = fieldAccess.getVariable().getDeclaration();
457: if ((f != null)
458: && f.getModifiers().contains(ModifierKind.FINAL)) {
459: setResult(f.getDefaultExpression());
460: return;
461: }
462: setResult(fieldAccess.getFactory().Core().clone(fieldAccess));
463: }
464:
465: public <T> void visitCtFieldReference(CtFieldReference<T> reference) {
466: throw new RuntimeException("Unknow Element");
467: }
468:
469: public void visitCtFor(CtFor forLoop) {
470:
471: // Evaluate forInit
472: List<CtStatement> lst = forLoop.getForInit();
473: List<CtStatement> evaluatelst = new ArrayList<CtStatement>();
474: for (CtStatement s : lst) {
475: CtStatement evaluateStatement = evaluate(forLoop, s);
476: if (evaluateStatement != null) {
477: evaluatelst.add(evaluateStatement);
478: }
479: }
480: forLoop.setForInit(evaluatelst);
481:
482: // Evaluate Expression
483: forLoop
484: .setExpression(evaluate(forLoop, forLoop
485: .getExpression()));
486:
487: // Evaluate forUpdate
488: lst = forLoop.getForUpdate();
489: evaluatelst = new ArrayList<CtStatement>();
490: for (CtStatement s : lst) {
491: CtStatement evaluateStatement = evaluate(forLoop, s);
492: if (evaluateStatement != null) {
493: evaluatelst.add(evaluateStatement);
494: }
495: }
496: forLoop.setForUpdate(evaluatelst);
497:
498: setResult(forLoop.getFactory().Core().clone(forLoop));
499: }
500:
501: public void visitCtForEach(CtForEach foreach) {
502: setResult(foreach.getFactory().Core().clone(foreach));
503: }
504:
505: public void visitCtGenericElementReference(
506: CtGenericElementReference reference) {
507: throw new RuntimeException("Unknow Element");
508: }
509:
510: public void visitCtIf(CtIf ifElement) {
511: CtExpression<Boolean> r = evaluate(ifElement, ifElement
512: .getCondition());
513: if (r instanceof CtLiteral) {
514: CtLiteral<Boolean> l = (CtLiteral<Boolean>) r;
515: if (l.getValue()) {
516: setResult(evaluate(null, ifElement.getThenStatement()));
517: } else {
518: setResult(evaluate(null, ifElement.getElseStatement()));
519: }
520: } else {
521: CtIf ifRes = ifElement.getFactory().Core().createIf();
522: ifRes.setCondition(r);
523: r.setParent(ifRes);
524: boolean thenEnded = false, elseEnded = false;
525: ifRes.setThenStatement(evaluate(ifRes, ifElement
526: .getThenStatement()));
527: if (flowEnded) {
528: thenEnded = true;
529: flowEnded = false;
530: }
531: ifRes.setElseStatement(evaluate(ifRes, ifElement
532: .getElseStatement()));
533: if (flowEnded) {
534: elseEnded = true;
535: flowEnded = false;
536: }
537: setResult(ifRes);
538: if (thenEnded && elseEnded) {
539: flowEnded = true;
540: }
541: }
542: }
543:
544: public <T> void visitCtInterface(CtInterface<T> intrface) {
545: throw new RuntimeException("Unknow Element");
546: }
547:
548: public <T> void visitCtInvocation(CtInvocation<T> invocation) {
549: CtInvocation<T> i = invocation.getFactory().Core()
550: .createInvocation();
551: i.setType(invocation.getType());
552: i.setExecutable(invocation.getExecutable());
553: boolean constant = true;
554: i.setTarget(evaluate(i, invocation.getTarget()));
555: if ((i.getTarget() != null)
556: && !(i.getTarget() instanceof CtLiteral)) {
557: constant = false;
558: }
559: for (CtExpression<?> e : invocation.getArguments()) {
560: CtExpression<?> re = evaluate(i, e);
561: if (!(re instanceof CtLiteral)) {
562: constant = false;
563: }
564: i.getArguments().add(re);
565: }
566: // do not partially evaluate super(...)
567: if (i.getExecutable().getSimpleName().equals("<init>")) {
568: setResult(i);
569: return;
570: }
571: if (constant) {
572: CtExecutable<?> executable = invocation.getExecutable()
573: .getDeclaration();
574: // try to inline partial evaluation results for local calls
575: // (including to superclasses)
576: if ((executable != null)
577: && (invocation.getType() != null)
578: && invocation
579: .getExecutable()
580: .getDeclaringType()
581: .isAssignableFrom(
582: ((CtSimpleType<?>) invocation
583: .getParent(CtSimpleType.class))
584: .getReference())) {
585: CtBlock<?> b = evaluate(invocation.getParent(),
586: executable.getBody());
587: flowEnded = false;
588: CtStatement last = b.getStatements().get(
589: b.getStatements().size() - 1);
590: if ((last != null) && (last instanceof CtReturn)) {
591: if (((CtReturn<?>) last).getReturnedExpression() instanceof CtLiteral) {
592: setResult(((CtReturn<?>) last)
593: .getReturnedExpression());
594: return;
595: }
596: }
597: } else {
598: // try to completely evaluate
599: T r = null;
600: try {
601: // System.err.println("invocking "+i);
602: r = RtHelper.invoke(i);
603: CtLiteral<T> l = invocation.getFactory().Core()
604: .createLiteral();
605: l.setValue(r);
606: setResult(l);
607: return;
608: } catch (Exception e) {
609: // swalow and don't simplify
610: // e.printStackTrace();
611: }
612: }
613: }
614: setResult(i);
615: }
616:
617: public <T> void visitCtLiteral(CtLiteral<T> literal) {
618: setResult(literal.getFactory().Core().clone(literal));
619: }
620:
621: public <T> void visitCtLocalVariable(
622: final CtLocalVariable<T> localVariable) {
623: // if (localVariable.getParent(CtBlock.class)!=null) {
624: //
625: // List<CtVariableAccess> res = Query.getElements(localVariable
626: // .getParent(CtBlock.class), new TypeFilter<CtVariableAccess>(
627: // CtVariableAccess.class) {
628: // @Override
629: // public boolean matches(CtVariableAccess element) {
630: // boolean ret = super.matches(element)
631: // && element.getVariable().getSimpleName().equals(
632: // localVariable.getSimpleName());
633: // return ret;
634: // }
635: // });
636: // if (res.size() != 0)
637: CtLocalVariable<T> r = localVariable.getFactory().Core().clone(
638: localVariable);
639: r.setDefaultExpression(evaluate(r, localVariable
640: .getDefaultExpression()));
641: setResult(r);
642: }
643:
644: public <T> void visitCtLocalVariableReference(
645: CtLocalVariableReference<T> reference) {
646: throw new RuntimeException("Unknow Element");
647: }
648:
649: public <T> void visitCtMethod(CtMethod<T> m) {
650: throw new RuntimeException("Unknow Element");
651: }
652:
653: public <T> void visitCtNewArray(CtNewArray<T> newArray) {
654: setResult(newArray.getFactory().Core().clone(newArray));
655: }
656:
657: public <T> void visitCtNewClass(CtNewClass<T> newClass) {
658: setResult(newClass.getFactory().Core().clone(newClass));
659: }
660:
661: public <T, A extends T> void visitCtOperatorAssignement(
662: CtOperatorAssignment<T, A> assignment) {
663: setResult(assignment.getFactory().Core().clone(assignment));
664: }
665:
666: public void visitCtPackage(CtPackage ctPackage) {
667: throw new RuntimeException("Unknow Element");
668: }
669:
670: public void visitCtPackageReference(CtPackageReference reference) {
671: throw new RuntimeException("Unknow Element");
672: }
673:
674: public <T> void visitCtParameter(CtParameter<T> parameter) {
675: throw new RuntimeException("Unknow Element");
676: }
677:
678: public <R> void visitCtStatementList(CtStatementList<R> statements) {
679: throw new RuntimeException("Unknow Element");
680: }
681:
682: public <T> void visitCtParameterReference(
683: CtParameterReference<T> reference) {
684: throw new RuntimeException("Unknow Element");
685: }
686:
687: public void visitCtReference(CtReference reference) {
688: throw new RuntimeException("Unknow Element");
689: }
690:
691: public <R> void visitCtReturn(CtReturn<R> returnStatement) {
692: CtReturn<R> r = returnStatement.getFactory().Core()
693: .createReturn();
694: r.setReturnedExpression(evaluate(r, returnStatement
695: .getReturnedExpression()));
696: setResult(r);
697: flowEnded = true;
698: }
699:
700: public <E> void visitCtSwitch(CtSwitch<E> switchStatement) {
701: setResult(switchStatement.getFactory().Core().clone(
702: switchStatement));
703: }
704:
705: public void visitCtSynchronized(CtSynchronized synchro) {
706: CtSynchronized s = synchro.getFactory().Core().clone(synchro);
707: s.setBlock(evaluate(s, synchro.getBlock()));
708: setResult(s);
709: }
710:
711: public <T, E extends CtExpression<?>> void visitCtTargetedExpression(
712: CtTargetedExpression<T, E> targetedExpression) {
713: throw new RuntimeException("Unknow Element");
714: }
715:
716: public void visitCtThrow(CtThrow throwStatement) {
717: CtThrow r = throwStatement.getFactory().Core().createThrow();
718: r.setThrownExpression(evaluate(r, throwStatement
719: .getThrownExpression()));
720: setResult(r);
721: flowEnded = true;
722: }
723:
724: public void visitCtTry(CtTry tryBlock) {
725: setResult(tryBlock.getFactory().Core().clone(tryBlock));
726: }
727:
728: public void visitCtTypeParameter(CtTypeParameter typeParameter) {
729: throw new RuntimeException("Unknow Element");
730: }
731:
732: public void visitCtTypeParameterReference(
733: CtTypeParameterReference ref) {
734: throw new RuntimeException("Unknow Element");
735: }
736:
737: public <T> void visitCtTypeReference(CtTypeReference<T> reference) {
738: throw new RuntimeException("Unknow Element");
739: }
740:
741: public <T> void visitCtUnaryOperator(CtUnaryOperator<T> operator) {
742: setResult(operator.getFactory().Core().clone(operator));
743: }
744:
745: public <T> void visitCtVariableAccess(
746: CtVariableAccess<T> variableAccess) {
747: CtVariable<?> v = variableAccess.getVariable().getDeclaration();
748:
749: if ((v != null) && v.hasModifier(ModifierKind.FINAL)
750: && (v.getDefaultExpression() != null)) {
751: setResult(v.getDefaultExpression().getFactory().Core()
752: .clone(v.getDefaultExpression()));
753: } else {
754: setResult(variableAccess.getFactory().Core().clone(
755: variableAccess));
756: }
757: }
758:
759: public <T, A extends T> void visitCtAssignment(
760: CtAssignment<T, A> variableAssignment) {
761: CtAssignment<T, A> a = variableAssignment.getFactory().Core()
762: .clone(variableAssignment);
763: a.setAssignment(evaluate(a, a.getAssignment()));
764: setResult(a);
765: }
766:
767: public <T> void visitCtVariableReference(
768: CtVariableReference<T> reference) {
769: throw new RuntimeException("Unknow Element");
770: }
771:
772: public void visitCtWhile(CtWhile whileLoop) {
773: CtWhile w = whileLoop.getFactory().Core().clone(whileLoop);
774: w.setLoopingExpression(evaluate(w, whileLoop
775: .getLoopingExpression()));
776: // If lopping Expression always false
777: if ((whileLoop.getLoopingExpression() instanceof CtLiteral)
778: && !((CtLiteral<Boolean>) whileLoop
779: .getLoopingExpression()).getValue()) {
780: setResult(null);
781: return;
782: }
783: w.setBody(evaluate(w, whileLoop.getBody()));
784: setResult(w);
785: }
786:
787: public <T> void visitCtConditional(CtConditional<T> conditional) {
788: CtExpression<Boolean> r = evaluate(conditional, conditional
789: .getCondition());
790: if (r instanceof CtLiteral) {
791: CtLiteral<Boolean> l = (CtLiteral<Boolean>) r;
792: if (l.getValue()) {
793: setResult(evaluate(null, conditional
794: .getThenExpression()));
795: } else {
796: setResult(evaluate(null, conditional
797: .getElseExpression()));
798: }
799: } else {
800: CtConditional<T> ifRes = conditional.getFactory().Core()
801: .createConditional();
802: ifRes.setCondition(r);
803: r.setParent(ifRes);
804: ifRes.setThenExpression(evaluate(ifRes, conditional
805: .getThenExpression()));
806: ifRes.setElseExpression(evaluate(ifRes, conditional
807: .getElseExpression()));
808: setResult(ifRes);
809: }
810: }
811:
812: }
|