[Spoon-discuss] Exception inserting code when if-statement body has no curly braces
Alex Epshteyn
alexander.epshteyn at gmail.com
Mon Jan 5 01:11:33 CET 2009
If I do the replace before inserting the return into the block, I end
up with an empty block.
This code:
public void process(CtReturn ret) {
if (!(ret.getParent() instanceof CtBlock)) {
CtBlock<Object> block = Factory.getLauchingFactory().Core().createBlock();
ret.replace(block);
block.insertBegin(ret);
}
Yields:
if (x < 0) {
}
But this code:
public void process(CtReturn ret) {
if (!(ret.getParent() instanceof CtBlock)) {
CtBlock<Object> block = Factory.getLauchingFactory().Core().createBlock();
block.insertBegin(ret);
ret.replace(block);
}
Yields:
if (x < 0)
return;
Now if I can just figure out how to combine the two... :)
- Alex
On Sun, Jan 4, 2009 at 6:47 PM, Alex Epshteyn
<alexander.epshteyn at gmail.com> wrote:
> Hi Renaud,
>
> I had the same intuition, and I tried writing a separate pre-processor
> for this, but did not succeed:
>
> public class ReturnStmtProcessor extends AbstractProcessor<CtReturn> {
> public void process(CtReturn ret) {
> if (!(ret.getParent() instanceof CtBlock)) {
> CtBlock block = Factory.getLauchingFactory().Core().createBlock();
> block.insertEnd(ret);
> ret.replace(block);
> }
> }
> }
>
> Running this processor before my method processor seems to just take
> the return statement out of the AST somehow. The result is that the
> method processor (from my previous) email seems to ignore this return
> statement.
>
> Code output:
>
> public void foo(int x, float y) {
> {
> com.stackspooner.main.client.VirtualCallStack.enterMethod("0"
> ,x ,y);
> }
> if (x < 0)
> return ;
>
> if (x == 0)
> zero();
> else
> positive();
> {
> com.stackspooner.main.client.VirtualCallStack.leaveMethod("0");
> }
> }
>
>
> Expected output:
>
> public void foo(int x, float y) {
> {
> com.stackspooner.main.client.VirtualCallStack.enterMethod("0"
> ,x ,y);
> }
> if (x < 0) {
> com.stackspooner.main.client.VirtualCallStack.leaveMethod("0");
> return ;
> }
> if (x == 0)
> zero();
> else
> positive();
> {
> com.stackspooner.main.client.VirtualCallStack.leaveMethod("0");
> }
> }
>
> I think I'm doing exactly what you suggested but in a separate processor.
>
>> Iterate on the CtReturn list returned by the filter
>
> I'm not sure how to do this with spoon. I only see methods like
> insertBefore and insertAfter, and replace, that accept the filter as
> an argument, but I don't see a method like block.search(filter)...
> Either way, replacing the return statement with a block containing it
> doesn't seem to work...
>
> Thanks for your help!
> Alex
>
> P.S.
>
> In case you're wondering about my project - I'm trying to instrument
> Java code, which will be compiled to Javascript using the GWT
> compiler, to retain stack traces corresponding to the original Java
> code, not javascript, in case of an exception. So I'm instrumenting
> the entry point and all return statements (but purposely not throw
> statements) of each method to push/pop items to/from a simulated call
> stack.
>
> I heard about Spoon a few years ago when working with Eliot Moss and
> Emery Berger at the University of Massachusetts, and happy to finally
> have a chance to try it out!
>
>
>
>
> On Sun, Jan 4, 2009 at 10:56 AM, Renaud Pawlak <renaud.pawlak at gmail.com> wrote:
>> Hi Alex,
>>
>> The only way is to add the block (curly brackets) when it is not
>> there. Iterate on the CtReturn list returned by the filter, then for
>> each CtReturn, check that the parent (CtElement.getParent) is a
>> CtBlock. If it is, proceed like you did before. If it not, create a
>> new empty CtBlock with the factory and add the return and the
>> endMethod statements. Then call the CtElement.replace(CtElement)
>> method on the return statement with your new block as a parameter.
>>
>> Note that the insertBefore method could do this operation
>> transparently but it could be a little bit too invasive to modify the
>> AST that much... insertBefore assumes that the target statement is
>> within a block...
>>
>> Cheers,
>> /Renaud
>>
>> On Sun, Jan 4, 2009 at 12:28 AM, Alex Epshteyn
>> <alexander.epshteyn at gmail.com> wrote:
>>> I'm trying to insert some code before every return statement in each
>>> method. There is a problem when a return statement occurs inside a
>>> block with no curly braces like this:
>>>
>>>
>>> /** Spoon throws an exception when trying to instrument a block with
>>> no curlies around it */
>>> public void foo(int x) {
>>> if (x < 0)
>>> return; // will fail here
>>> if (x == 0) {
>>> return; // this is OK because curly braces present
>>> }
>>> else
>>> positive(xStr);
>>> }
>>>
>>> Spoon throws:
>>>
>>> java.lang.ClassCastException: spoon.support.reflect.code.CtIfImpl
>>> cannot be cast to spoon.reflect.code.CtBlock
>>> at spoon.support.reflect.code.CtStatementImpl.insertBefore(CtStatementImpl.java:78)
>>>
>>>
>>> Here is my Processor code:
>>>
>>> public void process(CtMethod method) {
>>> ...
>>> // instrument all return statements
>>> // TODO: if statements without curly braces will throw an
>>> exception: java.lang.ClassCastException:
>>> spoon.support.reflect.code.CtIfImpl cannot be cast to
>>> spoon.reflect.code.CtBlock
>>>
>>> method.getBody().insertBefore(
>>> new TypeFilter<CtReturn>(CtReturn.class),
>>> Substitution.substituteMethodBody(
>>> (CtClass) method.getDeclaringType(),
>>> createTemplate(methodId, paramNames), "endMethod"));
>>> }
>>>
>>>
>>> I'm using Spoon 1.4. Would appreciate your assistance in finding a
>>> workaround to this problem.
>>>
>>> Thanks,
>>> Alex
>>>
>>> _______________________________________________
>>> Spoon-discuss mailing list
>>> Spoon-discuss at lists.gforge.inria.fr
>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/spoon-discuss
>>>
>>
>>
>>
>> --
>> Renaud Pawlak, Professor
>> ISEP - 21 rue d'Assas 75006 Paris, France
>> Head of the Computer Engineering Department
>> Head of ISEP Research and Consulting for Computer Engineering
>> Phone: +33 149 54 52 78
>> Cell #1: +33 6 37 29 12 15
>> Cell #2: +33 6 36 47 06 01
>> Fax: +33 1 49 54 52 51
>> http://renaudpawlak.wikidot.com
>>
>> _______________________________________________
>> Spoon-discuss mailing list
>> Spoon-discuss at lists.gforge.inria.fr
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/spoon-discuss
>>
>
More information about the Spoon-discuss
mailing list