[stringtemplate-interest] bug in format option
John Snyders
jjsnyders at rcn.com
Mon Jan 22 22:10:23 PST 2007
This is a bug in the code I submitted for the format option feature.
Each time a template is written it should produce the same output assuming
the attributes have not changed. Right?
With this contrived renderer (I first found the bug with a more reasonable
renderer but this one makes the problem very obvious)
public static class TestStringRenderer implements AttributeRenderer
{
public String toString(Object o, String formatName)
{
String s = (String)o;
return "(" + formatName + ":" + s + ")";
}
...
This code
StringTemplate st = new StringTemplate("v1 is: $v1;format=\"foo\"$");
st.registerRenderer(String.class, new TestStringRenderer());
st.setAttribute("v1", "value");
System.out.println(st.toString());
System.out.println(st.toString());
System.out.println(st.toString());
Produces this output
v1 is: (foo:value)
v1 is: ((foo:foo):value)
v1 is: (((foo:foo):foo):value)
I would expect this output:
v1 is: (foo:value)
v1 is: (foo:value)
v1 is: (foo:value)
There are other cases where a template can get used more than once such as
when iterating over a list. These cases have the exact same problem.
It doesn't even matter if the attribute changes value. Adding these lines
after the first println
st.removeAttribute("v1");
st.setAttribute("v1", "another Value");
produces this which is still wrong:
v1 is: (foo:value)
v1 is: ((foo:foo):another Value)
v1 is: (((foo:foo):foo):another Value)
The problem is in ASTExpr.java method handleExprOptions. The problem is that
the current formatString is used when evaluating the option value
expressions. Now the other options (such as null) don't seem to have a
similar problem even though the option already has a value when the template
is used again. I only played around with null and separator. But I did find
that format used with null and separator (and presumably the others that
take arguments) causes a problem. For example, if the above template is
changed to "v1 is: $v1;format=\"foo\",separator=\",\"$" and the value of v1
is a list with items "x", "y", "z" then the output is:
v1 is: (foo:x),(foo:y),(foo:z)
v1 is: ((foo:foo):x)(foo:,)((foo:foo):y)(foo:,)((foo:foo):z)
v1 is:
(((foo:foo):foo):x)((foo:foo):,)(((foo:foo):foo):y)((foo:foo):,)(((foo:foo):
foo):z)
The null option when combined with format has the same problem.
The solution is that the current value of formatString should not be used
when evaluating the expressions of any of the options. The code change I
made was to save off the current value of formatString before evaluating the
options and put it back when done.
String tempFormatString = formatString;
formatString = null;
StringTemplateAST wrapAST = (StringTemplateAST)getOption("wrap");
if ( wrapAST!=null ) {
wrapString = evaluateExpression(self,wrapAST);
...
StringTemplateAST formatAST = (StringTemplateAST)getOption("format");
if ( formatAST!=null ) {
// this gets assigned to the real formatString below
tempFormatString = evaluateExpression(self, formatAST);
...
formatString = tempFormatString;
I have not yet sync'ed with the repository but have diffed my code with it
and believe the same problem exists there. If anyone wants the whole file I
can supply it.
Let me know if you think there is a better solution.
Thanks,
-John
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org:8080/pipermail/stringtemplate-interest/attachments/20070123/75c2bf40/attachment.html
More information about the stringtemplate-interest
mailing list