[
https://issues.apache.org/jira/browse/GROOVY-11367?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17843773#comment-17843773
]
Eric Milles edited comment on GROOVY-11367 at 5/28/24 7:13 PM:
---------------------------------------------------------------
With change (2) from above, the third test case changes as follows:
{code:groovy}
@CompileStatic test3(M map) {
map.pub // field
map.pro // entry
map.pack // entry
map.priv // entry
map.prop // property
map.any // getter (accessible) or entry (inaccessible)
map.empty // isser
map.class // getter
map.metaClass // getter
map.pub = null // field
map.pro = null // TODO
map.pack = null // TODO
map.priv = null // TODO
map.prop = null // property
map.any = null // setter (accessible) or entry (inaccessible)
map.empty = null // TODO
map.class = null // TODO
map.metaClass = null // TODO
}
{code}
A change is required beyond this to align with dynamic mode's public/non-public
division. And an exclusion for "class" and "empty" is required to return to
map lookup (the behavior before GROOVY-5001 / GROOVY-5491).
was (Author: emilles):
With change (2) from above, the third test case changes as follows:
{code:groovy}
@CompileStatic test3(M map) {
map.pub // field
map.pro // entry
map.pack // entry
map.priv // entry
map.prop // property
map.any // getter (accessible) or entry (inaccessible)
map.empty // isser
map.class // getter
map.metaClass // getter
map.pub = null // TODO
map.pro = null // TODO
map.pack = null // TODO
map.priv = null // TODO
map.prop = null // property
map.any = null // setter (accessible) or entry (inaccessible)
map.empty = null // TODO
map.class = null // TODO
map.metaClass = null // TODO
}
{code}
A change is required beyond this to align with dynamic mode's public/non-public
division. And an exclusion for "class" and "empty" is required to return to
map lookup (the behavior before GROOVY-5001 / GROOVY-5491).
> property semantics of map-based types
> -------------------------------------
>
> 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
> Labels: breaking
>
> 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 // entry
> map.pack // entry
> map.priv // entry
> map.prop // 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 // entry ("class" and "metaClass" as well)
> map.pub = null // field
> map.pro = null // field
> map.pack = null // entry
> map.priv = null // entry
> map.prop = null // 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 // entry
> map.class = null // 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 // property
> this.prop = null // 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 // entry
> this.empty // 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 (changed in 5001/5491)
> map.pro // field (changed in 5001/5491: in package or subclass) or entry
> map.pack // field (changed in 5001/5491: in package) or entry
> map.priv // entry
> map.prop // property (changed in 5001/5491)
> map.any // getter (accessible -- changed in 5001/5491) or entry
> (inaccessible)
> map.empty // isser (changed in 5001/5491)
> map.class // getter (changed in 5001/5491)
> map.metaClass // getter (changed in 5001/5491)
> map.pub = null // entry (changed in 6954)
> map.pro = null // entry (changed in 6954)
> map.pack = null // entry
> map.priv = null // entry
> map.prop = null // property
> map.any = null // setter (accessible) or error (inaccessible) -- TODO
> map.empty = null // error "Cannot set read-only property: empty" (and
> "class") -- GROOVY-11369
> map.metaClass = null // field or setter (need to determine which)
> }
> {code}
> # Closures intercept some properties.
> {code:groovy}
> void test4(M map) {
> map.with {
> pub // field
> pro // entry
> pack // entry
> priv // entry
> prop // 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 // entry
> this.class = null // 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-662, GROOVY-5001, GROOVY-5491, GROOVY-5517, GROOVY-5985, GROOVY-6144,
> GROOVY-6277, GROOVY-6954, GROOVY-8065, GROOVY-8074, GROOVY-8555, GROOVY-9127,
> GROOVY-11319, GROOVY-11223, GROOVY-11368, GROOVY-11369, GROOVY-11370,
> GROOVY-11376 GROOVY-11384, GROOVY-11386, GROOVY-11387
--
This message was sent by Atlassian Jira
(v8.20.10#820010)