[ 
https://issues.apache.org/jira/browse/GROOVY-10955?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Paul King closed GROOVY-10955.
------------------------------

> @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
>            Assignee: Paul King
>            Priority: Major
>             Fix For: 4.0.10
>
>
> 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: 
> 'danv...@gmail.com', skills: ['Java', 'Spring'])
> assert dev1.with{ [id, first, last, email, skills] } ==
> //  [1, 'Dan', 'Vega', 'danv...@gmail.com', ['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: 
> 'danv...@gmail.com', skills: ['Java', 'Spring'])
> assert dev1.with{ [id, first, last, email, skills] } ==
>   [1, 'Dan', 'Vega', 'danv...@gmail.com', ['Java', 'Spring']]
> var dev2 = Developer.builder().id(2).full('Paul 
> King').email('pa...@apache.org').skills(['Java', 'Groovy']).build()
> assert dev2.with{ [id, first, last, email, skills] } ==
>   [2, 'Paul', 'King', 'pa...@apache.org', ['Java', 'Groovy']]
> {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to