Friday, May 23, 2008

toString() with templates? Hmm...

As my blog has just joined Planet Eclipse, I'd like to say 'hi' to all the Eclipse fans :) For the next few months you'll probably be hearing from me about automatic toString() generation feature for Eclipse as this is my project for this year's Google Summer of Code.



I'd like to start by sharing some dilemmas I have regarding the form of templates support in the generator. At first I wanted to use templates to set the format of the generated string, for example this template would create toString() returning a class name, followed by a comma separated list of values in one line:

${class_name}: ${field_value}, ${other_fields}

If every field should be placed in a separate line and have its name printed, the template would look like this:
${class_name} (
${field_name} = ${field_value}
${other_fields}
[Super: ${super_string}]
)

The ${super_string} element puts in the call to super.toString(). There could be other elements to call other common methods. The method generated with this template would look like this:
public String toString() {
return "FooClass (\n"
+ " field1 = " + field1
+ " field2 = " + field2
+ " [Super: " + super.toString() + "]\n"
+ ")";



I thought this was fine until Mike Haller suggested that not only the format of generated string is important, but also the style of the implementation itself. Some might want to use string concatenation, others StringBuilder or ToStringCreator from the Spring Framework and so on. I'm still not completely convinced about this - string concatenation is IMO the easiest to read and probably the fastest implementation (java compiler turns '+' into StringBuilder.append()) - then why would someone need something else? But let's assume that multiple style support is necessary. One solution is to hardcode the most common implementations and let the user choose one in the generator's dialog box. But then there will always be unhappy users who need a style that was not implemented.



The other solution is to use templates to determine the toString() method body itself. This approach is used by JUtils ToString Generator, but it's not very flexible. You cannot change the method behaviour for specific categories of fields, for example to skip null values (comparing primitives to null is an error). Considering this I realized that if there were some additional mechanisms making it more flexible, it would be more than just a toString() generator. It could easily replace almost all source generators currently available in Eclipse - a general purpose code generator useful always when you need to perform similar operations on multiple fields (or methods) of a class!



My idea to accomplish this is to use two level template-tree. Every node would have attributes determining when it should be used. To show what I mean, I will use an example of hashCode() method. Here, the top level template (marked to use only with fields) would look like this:

public int hashCode() {
final int prime = 31;
int result = 1;
${hashcode.sub1}
${hashcode.sub2}
return result;
}

The subtemplates should be called twice in order to determine if there should be any separator between them (here the separator is just "\n\t"). There will be several children:

  • result = prime * result + ((${field_name} == null) ? 0 : ${field_name}.hashCode()); (Marked for use with objects)

  • result = prime * result + ${field_name}; (Marked for use with ints)

  • result = prime * result + Float.floattoIntBits(${field_name}); (Marked for use with floats)

  • result = prime * result + (${field_name} ? 1231 : 1237); (Marked for use with booleans)

  • And so on...


Can you see the potential of this mechanism? :) One more extension is template grouping, which allows to iterate over class fields more than once. Again, let me use an example - generate constructor using fields. Here's the top level template:
public ${class_name}(${arg.sub1}, ${arg.sub2}) {
${body.sub1}
${body.sub2}
}

We have two groups here: the arg group for method arguments with this template:
${field_type} ${field_name}

and the body group with this template:
this.${field_name} = ${field_name};

This is just a general idea and definitely needs more design, but it looks very promising to me. As this idea is a bit different from what I presented in my GSOC application, I'm not sure if I should implement it. So I have a question to GSOC mentors who voted on my project: would you still vote for me if I presented the idea above? Another question is to people who know more about JDT and generation of the code from templates: is this going to work? I mean - maybe there are some major problems I'm not aware of... Of course, the question to everyone is how do you like the idea and how would you extend it? :)



If the project turns out to be too hard for a beginning developer like me or mentors won't agree to these changes, I would just implement the modest toString() generator and go for the general generator later. Now I'd like to hear as many opinions as possible :) I'm not sure if comments to this post is a good place for such discussion, but let's start with it. If it should moved somewhere else, please let me know.

Wednesday, May 21, 2008

Preparing for coding

The start of GSOC coding phase is getting closer and closer, so I started examining and debuging the Eclipse source. I'm beginning to understand how all the code generators work, although not without problems. The most difficult for me is the dialogs part - I would say that a little refactoring should be done here. Anyway, it's just GUI so I think it won't be so hard to handle it. As for the code generation itself, the operations seemed rather clear to me. Also, I'm going to read this article about abstract syntax tree to get more details.

After reading Remy's great article How to contribute to Eclipse projects I decided to give it a try and found this bug: 203132. It was pretty easy and referred to functionality I was just examining. But still I forgot to clean up some unused strings and had to send the patch three times. Well, at least I'll be more careful next time. Too bad it's too late to make changes in Eclipse 3.4. It would be much more fun if I didn't have to wait so long to see my code in HEAD CVS.

Tuesday, May 13, 2008

Welcome!

In this blog I will be reporting my progress on the "toString() generation" project for Eclipse, which is part of this year Google Summer of Code.

Through this blog my mentors, Markus Kuppe and Mike Haller, will know what I'm doing and I hope to get some feedback from the Eclipse community.