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

Eric Milles edited comment on GROOVY-11367 at 5/5/24 2:36 PM:
--------------------------------------------------------------

The first changes to improve consistency I would suggest are:
# read and write of protected field: write changes entry for non-{{this}} case 
-- one can always use {{map.@pro}} to reference protected field
# read and write of package-private and private methods: access checks 
determine field or entry for read, as they do for write -- 5001 made getter 
pervasive
# read and write of {{metaClass}}: remove special case for "metaClass" read 
being entry


was (Author: emilles):
The first changes to improve consistency I would suggest are:
# read and write of protected field: write changes entry for non-{{this}} case 
-- one can always use {{map.@pro}} to reference protected field
# read and write of package-private and private methods: access checks 
determine field or entry for read, as they do for write -- 5001 made getter 
pervasive
# read and write of {{metaClass}}: remove special case for "metaClass" read

> map-based types property semantics
> ----------------------------------
>
>                 Key: GROOVY-11367
>                 URL: https://issues.apache.org/jira/browse/GROOVY-11367
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Eric Milles
>            Assignee: Eric Milles
>            Priority: Major
>
> The rules for property read and write for map-based types still have several 
> inconsistencies:
> {code:groovy}
> class M extends HashMap<String,Object> {
>   public pub
>   protected pro
>   @PackageScope pack
>   private priv
>   def prop
>   def getAny() {}
>   void setAny(value) {}
> }
> {code}
>  # Read and write do not share a consistent resolution order – noted in 8555. 
> Should access method selection take visibility into account? I think sender 
> information is not always available to {{MetaClassImpl}} so the "inside 
> class" behavior is required.
> {code:groovy}
> void test1(M map) {
>   map.pub  // field (fixed in 5001)
>   map.pro  // map entry
>   map.pack // map entry
>   map.priv // map entry
>   map.prop // object property (fixed in 5001)
>   map.any  // getter (all visibilities -- fixed in 5001) or entry for 
> subclass of M (private or package-private other-package subclass -- fixed in 
> 11357)
>   map.empty // map entry ("class" and "metaClass" as well)
>   map.pub  = null // field
>   map.pro  = null // field
>   map.pack = null // map entry
>   map.priv = null // map entry
>   map.prop = null // object property
>   map.any  = null // setter (all visibilities) or entry for subclass of M 
> (private or package-private other-package subclass -- fixed in 11357)
>   map.empty = null // map entry
>   map.class = null // map entry
>   map.metaClass = null // setter via 
> ScriptBytecodeAdapter#setGroovyObjectProperty
> }
> {code}
>  # "this" and "super" have different behavior.
> {code:groovy}
>   // add this to the body of M
>   void test2(M that) {
>     this.pub  // field
>     this.pro  // field
>     this.pack // field
>     this.priv // field
>     this.prop // object property
>     this.prop = null // object property
>     this.any  // getter (all visibilities -- fixed in 5001)
>     this.any = null // setter (all visibilities) or entry for subclass of M 
> (private or package-private other-package subclass -- fixed in 11357)
>     this.class // map entry
>     this.empty // map entry
>     this.metaClass // field (added by compiler)
>     that.* // see test1
>     that = this
>     that.* // see test1
>   }
> {code}
>  # Dynamic and static compilation have different behavior.
> {code:groovy}
> @groovy.transform.CompileStatic
> void test3(M map) {
>   map.pub  // field (fixed in 5xxx)
>   map.pro  // field (in package or subclass -- fixed in 5xxx)
>   map.pack // field (in package - fixed in 5xxx)
>   map.priv // map entry
>   map.prop // object property
>   map.any  // getter (accessible -- fixed in 5xxx) or map entry (inaccessible)
>   map.empty // isser
>   map.class // getter
>   map.metaClass // getter
>   map.pub  = null // map entry
>   map.pro  = null // map entry
>   map.pack = null // map entry
>   map.priv = null // map entry
>   map.prop = null // object property
>   map.any  = null // setter (all visibilities)
>   map.empty = null // error "Cannot set read-only property: empty" ("class" 
> as well"
>   map.metaClass = null // setter
> }
> {code}
>  # Closures intercept some properties.
> {code:groovy}
> void test4(M map) {
>   map.with {
>     pub // field
>     pro // map entry
>     pack // map entry
>     priv // map entry
>     prop // object property
>     directive // closure property
>     metaClass // closure property (and so on for "owner", "delegate", 
> "thisObject", ...)
>   }
> }
> {code}
>  # The rules change a bit for fields declared by super class.
> {code:groovy}
> class MM extends M {
>   void test5() {
>     this.pub   // field (fixed in 5001)
>     this.pro   // entry
>     this.pack  // entry
>     this.priv  // entry
>     this.prop  // property (fixed in 5001)
>     this.any   // getter (fixed in 5001) (public, protected, package-private 
> if same-package) or entry (private, package-private if other-package)
>     this.class // entry
>     this.empty // entry
>     this.metaClass // entry
>     this.pub  = null // field
>     this.pro  = null // field
>     this.pack = null // entry
>     this.priv = null // entry
>     this.prop = null // property
>     this.any  = null // setter (public, protected, package-private if 
> same-package) or entry (private, package-private if other-package -- fixed in 
> 11357)
>     this.empty = null // map entry
>     this.class = null // map entry
>     this.metaClass = null // setter via 
> ScriptBytecodeAdapter#setGroovyObjectProperty
>   }
> }
> {code}
> # Calling a name bypasses map lookup.
> {code:groovy}
> void test6(M map) {
>   map.pack() // field read and call
>   map.priv() // field read and call
> }
> {code}
> GROOVY-11223, GROOVY-11319, GROOVY-9127, GROOVY-8555, GROOVY-8065, 
> GROOVY-6277, GROOVY-6144, GROOVY-5985, GROOVY-5491, GROOVY-5001, GROOVY-662



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to