[ https://issues.apache.org/jira/browse/GROOVY-11367?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Eric Milles updated GROOVY-11367: --------------------------------- Description: 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 } {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 // map entry this.prop = null // object property this.any // getter (all visibilities) this.any = null // setter (all visibilities) 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 map.pro // field map.pack // field map.priv // map entry map.prop // object property map.any // getter (non-private) or map entry (private) map.class // getter map.empty // isser 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 C extends M { void test5() { // TODO } } {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 was: 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? {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 } {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 // map entry this.prop = null // object property this.any // getter (all visibilities) this.any = null // setter (all visibilities) 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 map.pro // field map.pack // field map.priv // map entry map.prop // object property map.any // getter (non-private) or map entry (private) map.class // getter map.empty // isser 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 C extends M { void test5() { // TODO } } {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 > 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 > } > {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 // map entry > this.prop = null // object property > this.any // getter (all visibilities) > this.any = null // setter (all visibilities) > 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 > map.pro // field > map.pack // field > map.priv // map entry > map.prop // object property > map.any // getter (non-private) or map entry (private) > map.class // getter > map.empty // isser > 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 C extends M { > void test5() { > // TODO > } > } > {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)