An
InternCallback can be registered with {@link Context#addInterningCallback(InterningCallback)}.
Some care should be taken in implementing a callback considering the recursive nature of code generation within the framework. For instance, the following code will produce undesirable results: {code} new InterningCallback() { public Statement intern(LiteralValue<?> literalValue) { if (literalValue instanceof StringLiteral) { final String varName = "stringLiteral_" + literalValue.getValue().hashCode(); getClassBuilder().publicField(varName, String.class) .initializesWith(literalValue.getValue()); return Refs.get(varName); } return null; } } {code} On the surface, the above seems like a reasonable enough implementation. But there is a recursion problem hidden in it. Because we initialize the field with the string value in the default manner, the value will be obtained from the {@link org.jboss.errai.codegen.literal.LiteralFactory} in the regular manner, and theinterned value will reference itself!
You'll end up with code which looks like this: {code} stringLiteral_382389210 = stringLiteral_382389210; {code} ... And it's fair to say the compiler will not like this.
Instead, you should create non-recursive constructs. We can fix the above code like so: {code} new InterningCallback() { public Statement intern(final LiteralValue<?> literalValue) { if (literalValue instanceof StringLiteral) { final String varName = "stringLiteral_" + literalValue.getValue().hashCode(); getClassBuilder().publicField(varName, String.class) .initializesWith( new Statement() { public String generate(Context context) { return new StringLiteral(literalValue.getValue()).getCanonicalString(context); } public MetaClass getType() { return literalValue.getType(); } } ); return Refs.get(varName); } return null; } } {code}
@author Mike Brock