[
https://issues.apache.org/jira/browse/GROOVY-10955?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17697231#comment-17697231
]
ASF GitHub Bot commented on GROOVY-10955:
-----------------------------------------
paulk-asert merged PR #1868:
URL: https://github.com/apache/groovy/pull/1868
> @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
> Priority: Major
>
> 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)