[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