[
https://issues.apache.org/jira/browse/GROOVY-5001?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17470772#comment-17470772
]
Eric Milles edited comment on GROOVY-5001 at 1/7/22, 5:53 PM:
--------------------------------------------------------------
[~paulk]
My proposal to lower the precedence of Map#get is this:
# Allow access method (getName() or isName()) to be called through "name"
(GROOVY-662) when not "empty" or "class"
# Allow public field to be read before map property
# Non-public fields would still have precedence below map get
# The precedence of put would be fixed to match (GROOVY-5491)
That is, the "empty" variables in the above screenshot would remain a reference
to map property (greenish). Otherwise, maps would stop supporting map['empty']
and map['class'] (unless a bunch of extra checking was implemented). And the
variables "one" and "three" would all refer to the declared fields/properties
(blueish).
This illustrates the proposal. I think this would be fairly safe to do and
give most of what is expected.
{code:groovy}
class C {
@Delegate Map m = [:]
private def x = 'x'
public def y = 'y'
def getZ() { 'z' }
}
def c = new C()
assert c.class == null
assert c.empty == null
assert c.m === c.@m
assert c.x == null
assert c.y == 'y'
assert c.z == 'z'
{code}
was (Author: emilles):
[~paulk]
My proposal to lower the precedence of Map#get is this:
# Allow access method (getName() or isName()) to be called through "name" when
not "empty" or "class" (GROOVY-662)
# Allow public field to be read before map property
# Non-public fields would still have precedence below map get
# The precedence of put would be fixed to match (GROOVY-5491)
That is, the "empty" variables in the above screenshot would remain a reference
to map property (greenish). Otherwise, maps would stop supporting map['empty']
and map['class'] (unless a bunch of extra checking was implemented). And the
variables "one" and "three" would all refer to the declared fields/properties
(blueish).
This illustrates the proposal. I think this would be fairly safe to do and
give most of what is expected.
{code:groovy}
class C {
@Delegate Map m = [:]
private def x = 'x'
public def y = 'y'
def getZ() { 'z' }
}
def c = new C()
assert c.class == null
assert c.empty == null
assert c.m === c.@m
assert c.x == null
assert c.y == 'y'
assert c.z == 'z'
{code}
> Map access is given higher precedence when trying to access fields/properties
> in classes which implement java.util.Map or extend java.util.HashMap or
> java.util.Properties
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-5001
> URL: https://issues.apache.org/jira/browse/GROOVY-5001
> Project: Groovy
> Issue Type: Bug
> Components: groovy-runtime
> Affects Versions: 1.8.1, 1.8.2
> Environment: linux
> [tauser02@gfmwsp11lds cps]$ uname -a
> Linux gfmwsp11lds.hsi.hughessupply.com 2.6.18-164.el5 #1 SMP Thu Sep 3
> 04:15:13 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
> [tauser02@gfmwsp11lds ~]$ groovy -v
> Groovy Version: 1.8.2 JVM: 1.6.0_20
> I also tried it on Groovy 1.8.1
> Reporter: ericksn
> Priority: Major
> Attachments: screenshot-1.png
>
>
> Using the @Log4j annotation on a groovy class that extends
> java.util.Properties seems to have odd side effects on closures.
> {code:title=testscript}
> import groovy.util.logging.*
> [new Test1(), new Test2(), new Test3()].each {
> runTest(it)
> }
> def runTest (obj) {
> try {
> obj.test()
> obj.method()
> println "${obj.getClass()} success"
> }
> catch (e) {
> println "${obj.getClass()} failed $e"
> }
> }
> // classes
> @Log4j
> class Test1 {
> def test () {
> println '============================='
> println 'testing plain Groovy class'
> println "testing class [${this.getClass().getSimpleName()}]"
> }
> def method () {
> log.debug 'method called, not in closure'
> ['a', 'b', 'c'].each {
> log.debug "inside closure [$it]"
> }
> }
> }
> @Log4j
> class Test2 extends BaseClass {
> def test () {
> println '============================='
> println 'testing Groovy class that extends another Groovy class'
> println "testing class [${this.getClass().getSimpleName()}]"
> }
> def method () {
> log.debug 'method called, not in closure'
> ['a', 'b', 'c'].each {
> log.debug "inside closure [$it]"
> }
> }
> }
> class BaseClass {
> }
> @Log4j
> class Test3 extends java.util.Properties {
> def test () {
> println '============================='
> println 'testing Groovy class that extends java.util.Properties'
> println "testing class [${this.getClass().getSimpleName()}]"
> }
> def method () {
> log.debug 'method called, not in closure'
> ['a', 'b', 'c'].each {
> log.debug "inside closure [$it]"
> }
> }
> }
> {code}
> {code:title=log4j.properties}
> log4j.rootLogger=DEBUG, CONSOLE
> log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
> log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
> log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
> {code}
> {noformat}
> $ groovy testscript
> =============================
> testing plain Groovy class
> testing class [Test1]
> 2011-09-08 15:59:45,757 [main] DEBUG Test1 - method called, not in closure
> 2011-09-08 15:59:45,759 [main] DEBUG Test1 - inside closure [a]
> 2011-09-08 15:59:45,759 [main] DEBUG Test1 - inside closure [b]
> 2011-09-08 15:59:45,759 [main] DEBUG Test1 - inside closure [c]
> class Test1 success
> =============================
> testing Groovy class that extends another Groovy class
> testing class [Test2]
> 2011-09-08 15:59:45,768 [main] DEBUG Test2 - method called, not in closure
> 2011-09-08 15:59:45,769 [main] DEBUG Test2 - inside closure [a]
> 2011-09-08 15:59:45,769 [main] DEBUG Test2 - inside closure [b]
> 2011-09-08 15:59:45,769 [main] DEBUG Test2 - inside closure [c]
> class Test2 success
> =============================
> testing Groovy class that extends java.util.Properties
> testing class [Test3]
> 2011-09-08 15:59:45,771 [main] DEBUG Test3 - method called, not in closure
> class Test3 failed java.lang.NullPointerException: Cannot invoke method
> debug() on null object
> {noformat}
> The problem is on Test3 where the log instance var is null inside the
> closure, but not outside it.
> Only Test 3 has this problem
--
This message was sent by Atlassian Jira
(v8.20.1#820001)