activelylazy / Rescripter

An Eclipse plugin that lets you run JavaScript to refactor your Java code
http://www.rescripter.com/
12 stars 1 forks source link

Can Rescripter do this? :-) #7

Open boncey opened 12 years ago

boncey commented 12 years ago

Hi, I'm about to have another play with Rescripter.

I'm working on a legacy code base where the unit tests don't use annotations. I want to write a script to update them to use annotations.

This is my rough spec.

I think Rescripter might be missing some of the functionality to do all that. Specifically, finding all methods that start with "test" and a clean way of removing the "extends TestCase" text. I've forked it to see if I can add that.

Just want to know if what I want to do sounds achievable and ask for any alternative ways of doing it with existing functionality.

Finally, if I get it all working I'll add my script to the examples page.

activelylazy commented 12 years ago

Sounds possible. You can find all methods, then filter on name. Removing base class should be possible (you an find the extends clause in the AST and remove that text region).

Finding and removing annotations might be hard, not tried doing that.

Good luck! Let me know how you get on.

Cheers, David.

Sent from my iPhone

On 30 Jan 2012, at 14:19, Darren Greaves reply@reply.github.com wrote:

Hi, I'm about to have another play with Rescripter.

I'm working on a legacy code base where the unit tests don't use annotations. I want to write a script to update them to use annotations.

This is my rough spec.

  • Find all classes that extends TestCase
  • For each method that starts with "test"
    • Add annotation and import
  • For method called "startup" and/or "teardown"
    • Add annotation and import
    • Remove @Override annotation if present
  • Remove " extends TestCase" and import

I think Rescripter might be missing some of the functionality to do all that. Specifically, finding all methods that start with "test" and a clean way of removing the "extends TestCase" text. I've forked it to see if I can add that.

Just want to know if what I want to do sounds achievable and ask for any alternative ways of doing it with existing functionality.

Finally, if I get it all working I'll add my script to the examples page.


Reply to this email directly or view it on GitHub: https://github.com/activelylazy/Rescripter/issues/7

boncey commented 12 years ago

Sounds good.

How do I get it set up so I can develop locally and see my changes in Eclipse etc?

activelylazy commented 12 years ago

Hi Darren,

Have you got the code checked out & compiling in Eclipse? You can run Eclipse runtime workspace within Eclipse, that will use the plugins in your workspace (instead of those installed in eclipse itself). So then you can see your changes. It probably helps to have a separate workspace for rescripter itself vs what you use rescripter on... otherwise it all gets a bit complicated.

Shout if that doesn't make sense or something isn't working.

Cheers, David.

On Mon, Jan 30, 2012 at 5:46 PM, Darren Greaves < reply@reply.github.com

wrote:

Sounds good.

How do I get it set up so I can develop locally and see my changes in Eclipse etc?


Reply to this email directly or view it on GitHub: https://github.com/activelylazy/Rescripter/issues/7#issuecomment-3722766

David Green Co-founder of the London Software Craftsmanship Communityhttp://www.londonswcraft.com Twitter: @activelylazy Mobile: +44 7903 662 182

boncey commented 12 years ago

Hi, for now am gonna see if I can do it as you suggested above so not compiling locally yet.

I seem to have fallen at the first hurdle though. I can't seem to find a way to search the source for the text " extends TestCase". :-) I've been around and around the Eclipse API but can't see a simple way of searching the code for some text. Any ideas?

I've done adding annotations (and their imports) to methods so that part is the only bit left really.

Ta.

activelylazy commented 12 years ago

Have you played with the ast parser? I hope / think I documented it. Gives you the full parse tree. "all" you need to do is search the parse tree for a node of the appropriate type.

Sent from my iPhone

On 30 Jan 2012, at 22:02, Darren Greaves reply@reply.github.com wrote:

Hi, for now am gonna see if I can do it as you suggested above so not compiling locally yet.

I seem to have fallen at the first hurdle though. I can't seem to find a way to search the source for the text " extends TestCase". :-) I've been around and around the Eclipse API but can't see a simple way of searching the code for some text. Any ideas?

I've done adding annotations (and their imports) to methods so that part is the only bit left really.

Ta.


Reply to this email directly or view it on GitHub: https://github.com/activelylazy/Rescripter/issues/7#issuecomment-3727628

activelylazy commented 12 years ago

The other way to do it is the source is available as a text string (check the included .rs files in the source if it's not documented how). Although it's not great a regex against the source will probably suffice.

Sent from my iPhone

On 30 Jan 2012, at 22:02, Darren Greaves reply@reply.github.com wrote:

Hi, for now am gonna see if I can do it as you suggested above so not compiling locally yet.

I seem to have fallen at the first hurdle though. I can't seem to find a way to search the source for the text " extends TestCase". :-) I've been around and around the Eclipse API but can't see a simple way of searching the code for some text. Any ideas?

I've done adding annotations (and their imports) to methods so that part is the only bit left really.

Ta.


Reply to this email directly or view it on GitHub: https://github.com/activelylazy/Rescripter/issues/7#issuecomment-3727628

activelylazy commented 12 years ago

If you look at the AST parser example in the tutorial, one approach is to parse the whole source file and then look for a TypeDeclaration node in the tree: http://help.eclipse.org/helios/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/TypeDeclaration.html

This has a child that describes the superclass node. That will give you the exact text start and end point of "extends Foo" so you can delete it.

On Mon, Jan 30, 2012 at 10:06 PM, David Green dave@activelylazy.co.ukwrote:

The other way to do it is the source is available as a text string (check the included .rs files in the source if it's not documented how). Although it's not great a regex against the source will probably suffice.

Sent from my iPhone

On 30 Jan 2012, at 22:02, Darren Greaves < reply@reply.github.com

wrote:

Hi, for now am gonna see if I can do it as you suggested above so not compiling locally yet.

I seem to have fallen at the first hurdle though. I can't seem to find a way to search the source for the text " extends TestCase". :-) I've been around and around the Eclipse API but can't see a simple way of searching the code for some text. Any ideas?

I've done adding annotations (and their imports) to methods so that part is the only bit left really.

Ta.


Reply to this email directly or view it on GitHub: https://github.com/activelylazy/Rescripter/issues/7#issuecomment-3727628

David Green Co-founder of the London Software Craftsmanship Communityhttp://www.londonswcraft.com Twitter: @activelylazy Mobile: +44 7903 662 182

boncey commented 12 years ago

So, I think the bit I'm struggling with is that the extends clause is not a node (as far as I can tell). I've been looking for a way to say "search the source for this text then give me an offset so I can use a DeleteEdit".

Does that make sense?

EDIT: Just saw your last comment - ignore this for now until I get my head around it. :-)

activelylazy commented 12 years ago

Yeah TypeDeclaration is the parent node, I think you can navigate from that down to the supertype declaration, which will be just "extends Foo".

On Mon, Jan 30, 2012 at 10:16 PM, Darren Greaves < reply@reply.github.com

wrote:

So, I think the bit I'm struggling with is that the extends clause is not a node (as far as I can tell). I've been looking for a way to say "search the source for this text then give me an offset so I can use a DeleteEdit".

Does that make sense?


Reply to this email directly or view it on GitHub: https://github.com/activelylazy/Rescripter/issues/7#issuecomment-3727900

David Green Co-founder of the London Software Craftsmanship Communityhttp://www.londonswcraft.com Twitter: @activelylazy Mobile: +44 7903 662 182

boncey commented 12 years ago

Hi, I had a play with the AST stuff like in your tutorial but I think it may be a little too fine-grained. It's giving back nodes like "class" or "extends". I could probably work through node by node and delete extends then the following node but it feels quite hacky.

TypeDeclaration node looks like the thing I need but I can't figure out how to get there from the type I start off with. Sorry to be a pain. :-)

I've added a gist for what I have so far: https://gist.github.com/1709860

activelylazy commented 12 years ago

You should be able to search the ast nodes returned by the parser for one of that type.

If you have a node for extends can you get it's parent? Check what type it is and what it represents.

Sent from my iPhone

On 31 Jan 2012, at 11:48, Darren Greaves reply@reply.github.com wrote:

Hi, I had a play with the AST stuff like in your tutorial but I think it may be a little too fine-grained. It's giving back nodes like "class" or "extends". I could probably work through node by node and delete extends then the following node but it feels quite hacky.

TypeDeclaration node looks like the thing I need but I can't figure out how to get there from the type I start off with. Sorry to be a pain. :-)

I've added a gist for what I have so far: https://gist.github.com/1709860


Reply to this email directly or view it on GitHub: https://github.com/activelylazy/Rescripter/issues/7#issuecomment-3736876

boncey commented 12 years ago

It's not returning nodes (that I can see) - just your javascript token objects. I was using ScanTokens to get those.

Couldn't see the method call to get nodes.

activelylazy commented 12 years ago

Ah hah! That explains it. There's another API that parses the full ast, not just leaf nodes. I can't remember off the top of my head what it's called. You might have to check the source for clues. Or I'll investigate tonight.

Sent from my iPhone

On 31 Jan 2012, at 14:18, Darren Greaves reply@reply.github.com wrote:

It's not returning nodes (that I can see) - just your javascript token objects. I was using ScanTokens to get those.

Couldn't see the method call to get nodes.


Reply to this email directly or view it on GitHub: https://github.com/activelylazy/Rescripter/issues/7#issuecomment-3738703

boncey commented 12 years ago

Yeah, I tried to find it last night but to no avail.

Will have another look tonight. Thanks again for your help.

boncey commented 12 years ago

So, am trying to reduce this to the simplest case.

var type = Find.typeByName("TagsInterfaceTest");
Debug.message("type = " + type);    
var cu = type.getCompilationUnit();
Debug.message("cu = " + cu);
var types = cu.types();
Debug.message("types = " + types);

However, that cu.types call gives me an error like: Cannot call property types in object [Working copy] TagsInterfaceTest.java

That code was taken from http://www.eclipse.org/articles/article.php?file=Article-JavaCodeManipulation_AST/index.html

Struggling to see what's wrong with it.

activelylazy commented 12 years ago

Hi Darren,

Hmm, that's weird. So... I found the example I wanted.

In the rescripter source tree see: examples\easymock-jmock\src\main\script\EasyMockRefactor.rs

var ast =

AST.parseCompilationUnit(reference.getElement().getCompilationUnit()); var node = AST.findCoveredNode(ast, reference.offset, reference.length);

This works for a search match (reference is a single search result match). But given you need a compilation unit (which you should have), and a source offset & reference (which again you should have? at least from the type)

I.e. if you search for classes that extend/reference TestCase, you should get a list of search matches. I think each search match should be the type declaration, so you should get the whole class definition. What you get back from there is a properly navigable AST.

You'll see in EasyMockRefactor how I move up & down the AST to get to the nodes I need. You should be able to do the same.

Very puzzled by the types() thing. Perhaps try cu.types().get(0) or cu.types().size(). Although no idea why that should work if types alone fails, just wondering if it can't handle the return type. The above approach, using the AST and search matches, is how I would go about it though. Once you've got an AST you should be able to do everything you want. It can be a bit cumbersome to work with (the variety of node types is huge), but its very powerful.

On Tue, Jan 31, 2012 at 8:39 PM, Darren Greaves < reply@reply.github.com

wrote:

So, am trying to reduce this to the simplest case.

var type = Find.typeByName("TagsInterfaceTest"); Debug.message("type = " + type); var cu = type.getCompilationUnit(); Debug.message("cu = " + cu); var types = cu.types(); Debug.message("types = " + types);

However, that cu.types call gives me an error like: Cannot call property types in object [Working copy] TagsInterfaceTest.java

That code was taken from http://www.eclipse.org/articles/article.php?file=Article-JavaCodeManipulation_AST/index.html

Struggling to see what's wrong with it.


Reply to this email directly or view it on GitHub: https://github.com/activelylazy/Rescripter/issues/7#issuecomment-3746297

David Green Co-founder of the London Software Craftsmanship Communityhttp://www.londonswcraft.com Twitter: @activelylazy Mobile: +44 7903 662 182