Paul King created GROOVY-10955:
----------------------------------
Summary: @Builder doesn't work on records
Key: GROOVY-10955
URL: https://issues.apache.org/jira/browse/GROOVY-10955
Project: Groovy
Issue Type: Bug
Reporter: Paul King
For this code:
{code}
import groovy.transform.builder.*
@Builder
record Developer(Integer id, String first, String last, String email,
List<String> skills) { }
Developer.builder().id(2).build()
{code}
The code fails in the {{build}} method. It is meant to create a new Developer
but instead creates a DeveloperBuilder instance and then throws a cast
exception:
{noformat}
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast
object 'Developer$DeveloperBuilder@5ef26266' with class
'Developer$DeveloperBuilder' to class 'Developer'
...
at Developer$DeveloperBuilder.build(ConsoleScript25)
{noformat}
I wasn't necessarily expecting it to work. It could be made to work or we could
explicitly disable it for records.
Similarly, this code fails:
{code}
@Builder(builderStrategy=InitializerStrategy)
record Developer(Integer id, String first, String last, String email,
List<String> skills) { }
Developer.createInitializer().id(2).build()
{code}
with this more obscure error:
{noformat}
java.lang.ArrayIndexOutOfBoundsException: Internal compiler error while
compiling ConsoleScript26
Method:
org.codehaus.groovy.ast.MethodNode@7cd420f9[Developer$DeveloperInitializer
id(java.lang.Integer) from Developer$DeveloperInitializer]
Line -1, expecting casting to
Developer$DeveloperInitializer<groovy.transform.builder.InitializerStrategy$SET,
T1, T2, T3, T4> but operand stack is empty
...
at
org.codehaus.groovy.classgen.asm.OperandStack.doConvertAndCast(OperandStack.java:340)
at
org.codehaus.groovy.classgen.asm.StatementWriter.writeReturn(StatementWriter.java:593)
at
org.codehaus.groovy.classgen.AsmClassGenerator.visitReturnStatement(AsmClassGenerator.java:822)
...
{noformat}
I would probably just used the named args style rather than a builder, e.g.:
{code}
var dev1 = new Developer(id: 1, first: 'Dan', last: 'Vega', email:
'[email protected]', skills: ['Java', 'Spring'])
assert dev1.with{ [id, first, last, email, skills] } ==
// [1, 'Dan', 'Vega', '[email protected]', ['Java', 'Spring']]
{code}
But we should either support or disable one or more of the @Builder strategies.
Builder can also be written on constructors. That does work for the default
strategy but again not for the InitializerStrategy. Here is a working example:
{code}
import groovy.transform.builder.*
record Developer(Integer id, String first, String last, String email,
List<String> skills) {
@Builder
Developer(Integer id, String full, String email, List<String> skills) {
this(id, full.split(' ')[0], full.split(' ')[1], email, skills)
}
}
var dev1 = new Developer(id: 1, first: 'Dan', last: 'Vega', email:
'[email protected]', skills: ['Java', 'Spring'])
assert dev1.with{ [id, first, last, email, skills] } ==
[1, 'Dan', 'Vega', '[email protected]', ['Java', 'Spring']]
var dev2 = Developer.builder().id(2).full('Paul
King').email('[email protected]').skills(['Java', 'Groovy']).build()
assert dev2.with{ [id, first, last, email, skills] } ==
[2, 'Paul', 'King', '[email protected]', ['Java', 'Groovy']]
{code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)