[
https://issues.apache.org/jira/browse/GROOVY-11796?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18035748#comment-18035748
]
Valentine commented on GROOVY-11796:
------------------------------------
I tested with Groovy 4.0.29 and all my test cases work correctly.
In 4.0.29, getClasses() returns classes in this order:
0 = MyTrait
1 = MyTrait$Trait$Helper
2 = MyTrait$Trait$Helper$_test_closure1
3 = MyEnum
This order allows sequential class definition in ClassLoader.
I understand the order wasn't specified. However, this is a breaking change
from 4.0.29 that affects our production code.
Question: Is the new behavior intended to stay, or will this be addressed?
If it's intended, we'll need to implement dependency sorting on our side. If it
might be fixed, we could wait for a future release.
> CompilationUnit.getClasses() returns classes in incorrect order when trait
> with closure is used
> ------------------------------------------------------------------------------------------------
>
> Key: GROOVY-11796
> URL: https://issues.apache.org/jira/browse/GROOVY-11796
> Project: Groovy
> Issue Type: Bug
> Components: groovy-jdk
> Affects Versions: 5.0.0, 5.0.1, 5.0.2
> Environment: Java version: OpenJDK 21
> OS: Linux
> Reporter: Valentine
> Priority: Major
> Attachments: TraitOrderTest.java
>
>
> After upgrading to Groovy 5.0.x, the CompilationUnit.getClasses() method
> returns classes in an incorrect order when traits with closures are used.
>
> When compiling a trait with a closure and a class that implements this trait,
> getClasses() returns classes in an order where the implementing class comes
> BEFORE the trait class.
> This causes ClassNotFoundException when trying to define classes sequentially
> in a ClassLoader.
> *Steps to reproduce*
> this code with closure FAILS
>
> {code:java}
> trait MyTrait {
> MyTrait findByName(String name) {
> return values().find { it.name() == name }
> }
> }
> enum MyEnum implements MyTrait {
> A, B, C
> }
> {code}
>
> *Actual order from getClasses()*
> 0 = MyTrait$Trait$Helper
> 1 = MyTrait$Trait$Helper$_findByName_closure1
> 2 = MyEnum ← PROBLEM: MyEnum comes BEFORE MyTrait
> 3 = MyTrait
>
> *This code without closure WORKS*
>
> {code:java}
> trait MyTrait {
> MyTrait findByName(String name) {
> for (def value : values()) {
> if (value.name() == name){
> return value
> }
> }
> return null
> }
> }
>
> enum MyEnum implements MyTrait {
> A, B, C
> }
> {code}
>
>
> *Actual order from getClasses()*
> 0 = MyTrait
> 1 = MyTrait$Trait$Helper
> 2 = MyEnum ← CORRECT: MyEnum comes AFTER MyTrait
>
> IMO this is regression because:
> 1. {*}Groovy 4.0.28{*}: This code worked correctly - classes were returned in
> proper dependency order.
> 2. {*}Groovy 5.0.0 and 5.0.1{*}: Even simple cases like
> trait A {}
> class B implements A{}
> returned incorrect order.
> 3. {*}Groovy 5.0.2{*}: Simple cases were fixed, but the problem still
> persists when closures are used in traits.
> Additionally, this code WORKS and getClasses() provides *correct* order.
>
> {code:java}
> trait MyTrait {
> static String test(int x) {
> def result
> switch {
> case 1: result = 'one'; break
> default: result = 'other'; break
> }
> return result
> }
> }
> enum MyEnum implements MyTrait
> { A, B }
> {code}
>
> {*}This code doesn't work{*}.
>
> {code:java}
> trait MyTrait {
> static String test(int x) {
> def result = switch (x) {
> case 1 -> 'one'
> default -> 'other'
> }
> return result
> }
> }
> enum MyEnum implements MyTrait { A, B }
> {code}
>
> getClasses() provides this order of classes.
> 0 = MyTrait$Trait$Helper
> 1 = MyTrait$Trait$Helper$_test_closure1
> 2 = MyEnum ← PROBLEM: MyEnum comes BEFORE MyTrait
> 3 = MyTrait
> This code *doesn't work* either
>
> {code:java}
> trait MyTrait {
> def process() {
> values().stream()
> .filter(v -> v.name() == 'A')
> .findFirst()
> }
> }
> enum MyEnum implements MyTrait
> { A, B }
> {code}
>
> The same problem with the order.
> 0 = MyTrait$Trait$Helper
> 1 = MyTrait$Trait$Helper$_process_closure1
> 2 = MyEnum
> 3 = MyTrait
--
This message was sent by Atlassian Jira
(v8.20.10#820010)