Field order from traits

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Field order from traits

Andres Almiray
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',
       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',
        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
http://www.linkedin.com/in/aalmiray
--
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 | Threaded
Open this post in threaded view
|

RE: Field order from traits

Milles, Eric (TR Tech, Content & Ops)

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 <[hidden email]>
Sent: Sunday, December 1, 2019 12:02 PM
To: Groovy_Developers <[hidden email]>
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',
       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',
        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
http://www.linkedin.com/in/aalmiray
--
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 | Threaded
Open this post in threaded view
|

Re: Field order from traits

Remko Popma


On Mon, Dec 2, 2019 at 9:31 Milles, Eric (TR Tech, Content & Ops) <[hidden email]> wrote:

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.

Should that be changed to a LinkedHashSet?

 

From: Andres Almiray <[hidden email]>
Sent: Sunday, December 1, 2019 12:02 PM
To: Groovy_Developers <[hidden email]>
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',
       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',
        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
http://www.linkedin.com/in/aalmiray
--
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 | Threaded
Open this post in threaded view
|

Re: Field order from traits

Jochen Theodorou
On 02.12.19 01:51, Remko Popma wrote:

>
>
> On Mon, Dec 2, 2019 at 9:31 Milles, Eric (TR Tech, Content & Ops)
> <[hidden email] <mailto:[hidden email]>>
> wrote:
>
>     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.
>
> Should that be changed to a LinkedHashSet?

If the ClassNode is formed by reflection there is no order to depend on.
I do not even know if ASM gurantees the order. So I wonder if it really
makes sense

bye Jochen

Reply | Threaded
Open this post in threaded view
|

Re: Field order from traits

Jochen Theodorou
In reply to this post by Andres Almiray
Hi Andres,

I think your expectations are wrong. To understand why it is important I
wonder though what you need it for

bye Jochen


On 01.12.19 19:02, Andres Almiray wrote:

> 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 <http://oci.compartment.id>',
>         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 <http://oci.instance.name>',
>          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
> http://www.linkedin.com/in/aalmiray
> --
> 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 | Threaded
Open this post in threaded view
|

Re: Field order from traits

Andres Almiray
I need consistent field order to get around this problem -> https://github.com/gradle/gradle/issues/11522

I'm aware that reflection does not guarantee order. I was under the impression that the compiler would use the AST which would have the correct order but that only works if the trait is compiled in the same session as the target code. The compiler would be forced to use reflection if the trait is found only in binary in the classpath. Anyway, I found a workaround which is to encapsulate the fields on another type and have that latter be injected by the trait.

Thanks.

-------------------------------------------
Java Champion; Groovy Enthusiast
http://andresalmiray.com
http://www.linkedin.com/in/aalmiray
--
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.


On Mon, Dec 2, 2019 at 2:56 AM Jochen Theodorou <[hidden email]> wrote:
Hi Andres,

I think your expectations are wrong. To understand why it is important I
wonder though what you need it for

bye Jochen


On 01.12.19 19:02, Andres Almiray wrote:
> 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 <http://oci.compartment.id>',
>         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 <http://oci.instance.name>',
>          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
> http://www.linkedin.com/in/aalmiray
> --
> 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 | Threaded
Open this post in threaded view
|

Re: Field order from traits

Cédric Champeau
Independently of reflection or not, the compiler should be reproducible. So same sources -> same output, whatever the OS, whatever the time. This is important for trust and cache-ability.
On this specific issue, the default mechanism is to use ASM which is reproducible.

Le lun. 2 déc. 2019 à 10:06, Andres Almiray <[hidden email]> a écrit :
I need consistent field order to get around this problem -> https://github.com/gradle/gradle/issues/11522

I'm aware that reflection does not guarantee order. I was under the impression that the compiler would use the AST which would have the correct order but that only works if the trait is compiled in the same session as the target code. The compiler would be forced to use reflection if the trait is found only in binary in the classpath. Anyway, I found a workaround which is to encapsulate the fields on another type and have that latter be injected by the trait.

Thanks.

-------------------------------------------
Java Champion; Groovy Enthusiast
http://andresalmiray.com
http://www.linkedin.com/in/aalmiray
--
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.


On Mon, Dec 2, 2019 at 2:56 AM Jochen Theodorou <[hidden email]> wrote:
Hi Andres,

I think your expectations are wrong. To understand why it is important I
wonder though what you need it for

bye Jochen


On 01.12.19 19:02, Andres Almiray wrote:
> 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 <http://oci.compartment.id>',
>         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 <http://oci.instance.name>',
>          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
> http://www.linkedin.com/in/aalmiray
> --
> 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.