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.

Reply via email to