[ 
https://issues.apache.org/jira/browse/GROOVY-12554?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18134335#comment-18134335
 ] 

ASF GitHub Bot commented on GROOVY-12554:
-----------------------------------------

jdaugherty opened a new pull request, #3083:
URL: https://github.com/apache/groovy/pull/3083

   The order of the super$ and this$ methods followed the order of the
   methods of the class nodes they come from, which differs between nodes
   built by reflection and nodes read from bytecode. Sort them by name and
   type descriptor.
   
   `bugs.Groovy12554` compiles the classes once together and once with one of 
them compiled against the others already compiled, as an incremental build 
does, and compares the class files. It fails without the fix.
   
   - Jira: [GROOVY-12554](https://issues.apache.org/jira/browse/GROOVY-12554)
   - Reproducer, with `groovyc` and a Gradle incremental build: 
https://github.com/jdaugherty/groovy-mop-method-order
   - Backport to `GROOVY_5_1_X`: 
https://github.com/jdaugherty/groovy/commit/cc7eb32b259d2d65925faa30727ea34129727234,
 on the branch 
[`GROOVY-12554-5_1_X`](https://github.com/jdaugherty/groovy/tree/GROOVY-12554-5_1_X).
   
   It reproduces on 4.0.33, 5.1.3 and master. Could this be backported to 5.x 
once it is merged?
   




> The order of super$ MOP methods depends on whether the superclass's 
> interfaces were built by reflection or read from bytecode
> -----------------------------------------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12554
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12554
>             Project: Groovy
>          Issue Type: Bug
>          Components: class generator
>    Affects Versions: 4.0.33, 5.1.3
>            Reporter: James Daugherty
>            Priority: Major
>
> For every superclass method that a class calls through {{super}} in dynamic 
> Groovy, the class gets a synthetic {{super$N$name}} method. Groovy writes 
> these in the order in which it finds the methods, and that order follows the 
> class nodes of the superclass's interfaces. When a transformation adds an 
> interface with a class node built by reflection, as GORM does for the traits 
> of domain classes, the order comes from {{Class.getDeclaredMethods()}}, which 
> is unspecified. When the superclass is read from bytecode, it comes from the 
> class file. So the same source compiles to a different class file depending 
> on what else is compiled, and in principle on the JVM.
> {noformat}
> super$ methods of Sub, compiled together with Base:           alpha beta 
> delta gamma kappa mid omega zeta
> super$ methods of Sub, compiled against Base already compiled: zeta alpha mid 
> omega beta kappa delta gamma
> {noformat}
> Reproduced with 4.0.33, 5.1.3 and master. A reproducer with a small 
> transformation that adds an interface with {{ClassHelper.make(Class)}}, a 
> groovyc script and an incremental Gradle build: 
> https://github.com/jdaugherty/groovy-mop-method-order
> *Cause*
> {{MopWriter.visitMopMethodList}} generates the MOP methods in the order of 
> {{getDeclaredMethodsMap()}} of the superclass, which adds the methods of the 
> superclass's interfaces in the order their class nodes list them: by 
> reflection for a node made with {{ClassHelper.make(Class)}}, from the class 
> file for a node read from bytecode.
> *Proposed fix*
> Sort the MOP methods by name and type descriptor before generating them. The 
> order of methods in a class file does not matter at run time, and 
> {{MetaClassImpl}} sorts the MOP methods it finds itself.
> Found while making incremental builds of a Grails application produce the 
> same classes as a full build; see also GROOVY-12550 and GROOVY-12544.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to