Trait fields for properties are added by TraitComposer as it encounters the getter methods (around line 250). Methods are processed in the order returned from ClassNode#getDeclaredMethods, which uses a HashSet.
From: Andres Almiray <aalmi...@gmail.com> Sent: Sunday, December 1, 2019 12:02 PM To: Groovy_Developers <dev@groovy.apache.org> Subject: Field order from traits Hello everyone, I've encountered a "problem" when using traits. Say you have a couple of traits that define fileds in the following order @CompileStatic trait CompartmentIdAwareTrait implements PathAware, ProjectAware { @Internal final Property<String> compartmentId = project.objects.property(String) @Input final Provider<String> resolvedCompartmentId = stringProvider( 'OCI_COMPARTMENT_ID', 'oci.compartment.id<https://urldefense.proofpoint.com/v2/url?u=http-3A__oci.compartment.id&d=DwMFaQ&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=7cHs5q6y32hBK2dBbtA2KQcUS3BqDrf4y44Ljg-oWLY&s=iwuCmgVnKn2-dxGySIXzW07dJUPBjje1zBT6miGALdQ&e=>', getCompartmentId(), project) } and @CompileStatic trait InstanceNameAwareTrait implements PathAware, ProjectAware { @Internal final Property<String> instanceName = project.objects.property(String) @Input final Provider<String> resolvedInstanceName = stringProvider( 'OCI_INSTANCE_NAME', 'oci.instance.name<https://urldefense.proofpoint.com/v2/url?u=http-3A__oci.instance.name&d=DwMFaQ&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=7cHs5q6y32hBK2dBbtA2KQcUS3BqDrf4y44Ljg-oWLY&s=AdEVlzKe0OagO_WUsPq81vde3azo4heHbQe_gqGXoYE&e=>', getInstanceName(), project) } As you can see there's a regular property field and a "resolved" provider field. I expected these fields to be copied in definition order, that is, resolved fields will always be second thus the reference to their corresponding property field will work. However that's not the case. I'm compiling code with Groovy 2.5.8 (I think that's the version used by Gradle 6.0.1) and I find the following fields in the bytecode of the target class that applies the traits private final org.gradle.api.provider.Provider<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_InstanceNameAwareTrait__resolvedInstanceName; private final org.gradle.api.provider.Property<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_InstanceNameAwareTrait__instanceName; private final org.gradle.api.provider.Property<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_CompartmentIdAwareTrait__compartmentId; private final org.gradle.api.provider.Provider<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_CompartmentIdAwareTrait__resolvedCompartmentId; The order of copied fields is not consistent either private final org.gradle.api.provider.Property<java.lang.Boolean> org_kordamp_gradle_plugin_oci_tasks_traits_VerboseAwareTrait__verbose; private final org.gradle.api.provider.Provider<java.lang.Boolean> org_kordamp_gradle_plugin_oci_tasks_traits_VerboseAwareTrait__resolvedVerbose; private final org.gradle.api.provider.Provider<org.gradle.api.file.RegularFile> org_kordamp_gradle_plugin_oci_tasks_traits_UserDataFileAwareTrait__resolvedUserDataFile; private final org.gradle.api.file.RegularFileProperty org_kordamp_gradle_plugin_oci_tasks_traits_UserDataFileAwareTrait__userDataFile; private final org.gradle.api.file.RegularFileProperty org_kordamp_gradle_plugin_oci_tasks_traits_PublicKeyFileAwareTrait__publicKeyFile; private final org.gradle.api.provider.Provider<org.gradle.api.file.RegularFile> org_kordamp_gradle_plugin_oci_tasks_traits_PublicKeyFileAwareTrait__resolvedPublicKeyFile; private final org.gradle.api.provider.Provider<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_ShapeAwareTrait__resolvedShape; private final org.gradle.api.provider.Property<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_ShapeAwareTrait__shape; private final org.gradle.api.provider.Provider<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_ImageAwareTrait__resolvedImage; private final org.gradle.api.provider.Property<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_ImageAwareTrait__image; private final org.gradle.api.provider.Provider<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_InstanceNameAwareTrait__resolvedInstanceName; private final org.gradle.api.provider.Property<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_InstanceNameAwareTrait__instanceName; private final org.gradle.api.provider.Property<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_CompartmentIdAwareTrait__compartmentId; private final org.gradle.api.provider.Provider<java.lang.String> org_kordamp_gradle_plugin_oci_tasks_traits_CompartmentIdAwareTrait__resolvedCompartmentId; So I wonder if this is some bug or my expectations are wrong. I expected fields to be copied in the same order as they were defined in the trait. Cheers, Andres ------------------------------------------- Java Champion; Groovy Enthusiast http://andresalmiray.com<https://urldefense.proofpoint.com/v2/url?u=http-3A__andresalmiray.com&d=DwMFaQ&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=7cHs5q6y32hBK2dBbtA2KQcUS3BqDrf4y44Ljg-oWLY&s=WkcrAFRNrCUqFjIHM4av_5pB2VM1AqbTX3558UEY-j4&e=> http://www.linkedin.com/in/aalmiray<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.linkedin.com_in_aalmiray&d=DwMFaQ&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=7cHs5q6y32hBK2dBbtA2KQcUS3BqDrf4y44Ljg-oWLY&s=q6VHoX2RoJGp_AL6f75d_eybwUgZKOkOSWZiUtxL22k&e=> -- What goes up, must come down. Ask any system administrator. There are 10 types of people in the world: Those who understand binary, and those who don't. To understand recursion, we must first understand recursion.