[jira] [Comment Edited] (GROOVY-7996) Using with method with a closure that references a protected property produces ClassCastException

2019-10-28 Thread Eric Milles (Jira)


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

Eric Milles edited comment on GROOVY-7996 at 10/28/19 8:36 PM:
---

This is a bit of an experiment.  If the initial issue is re-written this way 
(cut from unit test) and if I add to 
{{StaticTypeCheckingVisitor#existsProperty}} checks for dynamic property 
resolution (see below), then the test case will indeed run through 
{{Foo#propertyMissing}} and there will be no {{ClassCastException}}.

{code:java}
"Foo.groovy",
"class Foo {\n" +
"  def build(@DelegatesTo(value=Foo, 
strategy=Closure.DELEGATE_FIRST) Closure block) {\n" +
"return this.with(block)\n" +
"  }\n" +
"  def propertyMissing(String name) {\n" +
"return 'stuff'\n" +
"  }\n" +
"}\n",

"Bar.groovy",
"@groovy.transform.CompileStatic\n" +
"class Bar {\n" +
"  protected List bars = []\n" +
"  def doStuff() {\n" +
"new Foo().build {\n" +
"  return bars.toString()\n" +
"}\n" +
"  }\n" +
"}\n",

"Main.groovy",
"assert new Bar().doStuff() == 'stuff'\n",
{code}

StaticTypeCheckingVisitor:
{code:java}
// TODO: What if receiver implements get(String)/set(String,Object), 
getProperty(String)/setProperty(String,Object) or propertyMissing(String)?
if (!isPrimitiveType(getUnwrapper(testClass)) && objectExpression instanceof 
VariableExpression && typeCheckingContext.getEnclosingClosure() != null) {
MethodNode mopMethod;
if (readMode) {
mopMethod = testClass.getMethod("getProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name")});
if (mopMethod == null) mopMethod = testClass.getMethod("get", new 
Parameter[]{new Parameter(STRING_TYPE, "name")});
} else {
mopMethod = testClass.getMethod("setProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, "value")});
if (mopMethod == null) mopMethod = testClass.getMethod("set", new 
Parameter[]{new Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, 
"value")});
}
if (mopMethod == null) mopMethod = testClass.getMethod("propertyMissing", 
new Parameter[]{new Parameter(STRING_TYPE, "name")});

if (mopMethod != null) {
pexp.putNodeMetaData(DYNAMIC_RESOLUTION, Boolean.TRUE);
pexp.removeNodeMetaData(DECLARATION_INFERRED_TYPE);
pexp.removeNodeMetaData(INFERRED_TYPE);
return true;
}
}
{code}


was (Author: emilles):
This is a bit of an experiment.  If the initial issue is re-written this way 
(cut from unit test) and if I add to 
{{StaticTypeCheckingVisitor#existsProperty}} checks for dynamic property 
resolution (see below), then the test case will indeed run through 
{{Foo#propertyMissing}} and there will be no {{ClassCastException}}.

{code:java}
"Foo.groovy",
"class Foo {\n" +
"  def build(@DelegatesTo(value=Foo, 
strategy=Closure.DELEGATE_FIRST) Closure block) {\n" +
"return this.with(block)\n" +
"  }\n" +
"  def propertyMissing(String name) {\n" +
"return 'stuff'\n" +
"  }\n" +
"}\n",

"Bar.groovy",
"@groovy.transform.CompileStatic\n" +
"class Bar {\n" +
"  protected List bars = []\n" +
"  def doStuff() {\n" +
"new Foo().build {\n" +
"  return bars.toString()\n" +
"}\n" +
"  }\n" +
"}\n",

"Main.groovy",
"assert new Bar().doStuff() == 'stuff'\n",
{code}

StaticTypeCheckingVisitor:
{code:java}
// TODO: What if receiver implements get(String)/set(String,Object), 
getProperty(String)/setProperty(String,Object) or propertyMissing(String)?
if (objectExpression instanceof VariableExpression && 
typeCheckingContext.getEnclosingClosure() != null) {
if (isPrimitiveType(testClass)) testClass = getWrapper(testClass);
MethodNode mopMethod;
if (readMode) {
mopMethod = testClass.getMethod("getProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name")});
if (mopMethod == null) mopMethod = testClass.getMethod("get", new 
Parameter[]{new Parameter(STRING_TYPE, "name")});
} else {
mopMethod = testClass.getMethod("setProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, "value")});
if (mopMethod == null) mopMethod = testClass.getMethod("set", new 
Parameter[]{new Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, 
"value")});
}
if (mopMethod == null) mopMethod = testClass.getMethod("propertyMissing", 
new Parameter[]{new Parameter(STRING_TYPE, 

[jira] [Comment Edited] (GROOVY-7996) Using with method with a closure that references a protected property produces ClassCastException

2019-10-28 Thread Eric Milles (Jira)


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

Eric Milles edited comment on GROOVY-7996 at 10/28/19 8:32 PM:
---

This is a bit of an experiment.  If the initial issue is re-written this way 
(cut from unit test) and if I add to 
{{StaticTypeCheckingVisitor#existsProperty}} checks for dynamic property 
resolution (see below), then the test case will indeed run through 
{{Foo#propertyMissing}} and there will be no {{ClassCastException}}.

{code:java}
"Foo.groovy",
"class Foo {\n" +
"  def build(@DelegatesTo(value=Foo, 
strategy=Closure.DELEGATE_FIRST) Closure block) {\n" +
"return this.with(block)\n" +
"  }\n" +
"  def propertyMissing(String name) {\n" +
"return 'stuff'\n" +
"  }\n" +
"}\n",

"Bar.groovy",
"@groovy.transform.CompileStatic\n" +
"class Bar {\n" +
"  protected List bars = []\n" +
"  def doStuff() {\n" +
"new Foo().build {\n" +
"  return bars.toString()\n" +
"}\n" +
"  }\n" +
"}\n",

"Main.groovy",
"assert new Bar().doStuff() == 'stuff'\n",
{code}

StaticTypeCheckingVisitor:
{code:java}
// TODO: What if receiver implements get(String)/set(String,Object), 
getProperty(String)/setProperty(String,Object) or propertyMissing(String)?
if (objectExpression instanceof VariableExpression && 
typeCheckingContext.getEnclosingClosure() != null) {
if (isPrimitiveType(testClass)) testClass = getWrapper(testClass);
MethodNode mopMethod;
if (readMode) {
mopMethod = testClass.getMethod("getProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name")});
if (mopMethod == null) mopMethod = testClass.getMethod("get", new 
Parameter[]{new Parameter(STRING_TYPE, "name")});
} else {
mopMethod = testClass.getMethod("setProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, "value")});
if (mopMethod == null) mopMethod = testClass.getMethod("set", new 
Parameter[]{new Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, 
"value")});
}
if (mopMethod == null) mopMethod = testClass.getMethod("propertyMissing", 
new Parameter[]{new Parameter(STRING_TYPE, "name")});

if (mopMethod != null) {
pexp.putNodeMetaData(DYNAMIC_RESOLUTION, Boolean.TRUE);
pexp.removeNodeMetaData(DECLARATION_INFERRED_TYPE);
pexp.removeNodeMetaData(INFERRED_TYPE);
return true;
}
}
{code}


was (Author: emilles):
This is a bit of an experiment.  If the initial issue is re-written this way 
(cut from unit test) and if I add to 
{{StaticTypeCheckingVisitor#existsProperty}} checks for dynamic property 
resolution (see below), then the test case will indeed run through 
{{Foo#propertyMissing}} and there will be no {{ClassCastException}}.

{code:java}
"Foo.groovy",
"class Foo {\n" +
"  def build(@DelegatesTo(value=Foo, 
strategy=Closure.DELEGATE_FIRST) Closure block) {\n" +
"return this.with(block)\n" +
"  }\n" +
"  def propertyMissing(String name) {\n" +
"return 'stuff'\n" +
"  }\n" +
"}\n",

"Bar.groovy",
"@groovy.transform.CompileStatic\n" +
"class Bar {\n" +
"  protected List bars = []\n" +
"  def doStuff() {\n" +
"new Foo().build {\n" +
"  return bars.toString()\n" +
"}\n" +
"  }\n" +
"}\n",

"Main.groovy",
"assert new Bar().doStuff() == 'stuff'\n",
{code}

StaticTypeCheckingVisitor:
{code:java}
// TODO: What if receiver implements get(String)/set(String,Object), 
getProperty(String)/setProperty(String,Object) or propertyMissing(String)?
if (objectExpression instanceof VariableExpression && 
typeCheckingContext.getEnclosingClosure() != null) {
MethodNode mopMethod;
if (readMode) {
mopMethod = testClass.getMethod("getProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name")});
if (mopMethod == null) mopMethod = testClass.getMethod("get", new 
Parameter[]{new Parameter(STRING_TYPE, "name")});
} else {
mopMethod = testClass.getMethod("setProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, "value")});
if (mopMethod == null) mopMethod = testClass.getMethod("set", new 
Parameter[]{new Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, 
"value")});
}
if (mopMethod == null) mopMethod = testClass.getMethod("propertyMissing", 
new Parameter[]{new Parameter(STRING_TYPE, "name")});

if (mopMethod != null) {

[jira] [Comment Edited] (GROOVY-7996) Using with method with a closure that references a protected property produces ClassCastException

2019-10-28 Thread Eric Milles (Jira)


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

Eric Milles edited comment on GROOVY-7996 at 10/28/19 8:20 PM:
---

This is a bit of an experiment.  If the initial issue is re-written this way 
(cut from unit test) and if I add to 
{{StaticTypeCheckingVisitor#existsProperty}} checks for dynamic property 
resolution (see below), then the test case will indeed run through 
{{Foo#propertyMissing}} and there will be no {{ClassCastException}}.

{code:java}
"Foo.groovy",
"class Foo {\n" +
"  def build(@DelegatesTo(value=Foo, 
strategy=Closure.DELEGATE_FIRST) Closure block) {\n" +
"return this.with(block)\n" +
"  }\n" +
"  def propertyMissing(String name) {\n" +
"return 'stuff'\n" +
"  }\n" +
"}\n",

"Bar.groovy",
"@groovy.transform.CompileStatic\n" +
"class Bar {\n" +
"  protected List bars = []\n" +
"  def doStuff() {\n" +
"new Foo().build {\n" +
"  return bars.toString()\n" +
"}\n" +
"  }\n" +
"}\n",

"Main.groovy",
"assert new Bar().doStuff() == 'stuff'\n",
{code}

StaticTypeCheckingVisitor:
{code:java}
// TODO: What if receiver implements get(String)/set(String,Object), 
getProperty(String)/setProperty(String,Object) or propertyMissing(String)?
if (objectExpression instanceof VariableExpression && 
typeCheckingContext.getEnclosingClosure() != null) {
MethodNode mopMethod;
if (readMode) {
mopMethod = testClass.getMethod("getProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name")});
if (mopMethod == null) mopMethod = testClass.getMethod("get", new 
Parameter[]{new Parameter(STRING_TYPE, "name")});
} else {
mopMethod = testClass.getMethod("setProperty", new Parameter[]{new 
Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, "value")});
if (mopMethod == null) mopMethod = testClass.getMethod("set", new 
Parameter[]{new Parameter(STRING_TYPE, "name"), new Parameter(OBJECT_TYPE, 
"value")});
}
if (mopMethod == null) mopMethod = testClass.getMethod("propertyMissing", 
new Parameter[]{new Parameter(STRING_TYPE, "name")});

if (mopMethod != null) {
pexp.putNodeMetaData(DYNAMIC_RESOLUTION, Boolean.TRUE);
pexp.removeNodeMetaData(DECLARATION_INFERRED_TYPE);
pexp.removeNodeMetaData(INFERRED_TYPE);
return true;
}
}
{code}


was (Author: emilles):
This is a bit of an experiment.  If the initial issue is re-written this way 
(cut from unit test) and if I add to 
{{StaticTypeCheckingVisitor#existsProperty}} checks for dynamic property 
resolution (see below), then the test case will indeed run through 
{{Foo#propertyMissing}} and there will be no {{ClassCastException}}.

{code:java}
"Foo.groovy",
"class Foo {\n" +
"  def build(@DelegatesTo(value=Foo, 
strategy=Closure.DELEGATE_FIRST) Closure block) {\n" +
"return this.with(block)\n" +
"  }\n" +
"  def propertyMissing(String name) {\n" +
"return 'stuff'\n" +
"  }\n" +
"}\n",

"Bar.groovy",
"@groovy.transform.CompileStatic\n" +
"class Bar {\n" +
"  protected List bars = []\n" +
"  def doStuff() {\n" +
"new Foo().build {\n" +
"  return bars.toString()\n" +
"}\n" +
"  }\n" +
"}\n",

"Main.groovy",
"assert new Bar().doStuff() == 'stuff'\n",
{code}

StaticTypeCheckingVisitor:
{code:java}
// TODO: What if receiver implements get(String)/set(String,Object), 
getProperty(String)/setProperty(String,Object) or propertyMissing(String)?
if (objectExpression instanceof VariableExpression && 
typeCheckingContext.getEnclosingClosure() != null) {
MethodNode mopMethod;
if (readMode) {
mopMethod = receiver.getType().getMethod("getProperty", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name")));
if (mopMethod == null) mopMethod = testClass.getMethod("get", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name")));
} else {
mopMethod = receiver.getType().getMethod("setProperty", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name"), 
GeneralUtils.param(OBJECT_TYPE, "value")));
if (mopMethod == null) mopMethod = testClass.getMethod("set", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name"), 
GeneralUtils.param(OBJECT_TYPE, "value")));
}
if (mopMethod == null) mopMethod = testClass.getMethod("propertyMissing", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name")));

if (mopMethod != null) {

[jira] [Comment Edited] (GROOVY-7996) Using with method with a closure that references a protected property produces ClassCastException

2019-10-28 Thread Eric Milles (Jira)


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

Eric Milles edited comment on GROOVY-7996 at 10/28/19 7:47 PM:
---

This is a bit of an experiment.  If the initial issue is re-written this way 
(cut from unit test) and if I add to 
{{StaticTypeCheckingVisitor#existsProperty}} checks for dynamic property 
resolution (see below), then the test case will indeed run through 
{{Foo#propertyMissing}} and there will be no {{ClassCastException}}.

{code:java}
"Foo.groovy",
"class Foo {\n" +
"  def build(@DelegatesTo(value=Foo, 
strategy=Closure.DELEGATE_FIRST) Closure block) {\n" +
"return this.with(block)\n" +
"  }\n" +
"  def propertyMissing(String name) {\n" +
"return 'stuff'\n" +
"  }\n" +
"}\n",

"Bar.groovy",
"@groovy.transform.CompileStatic\n" +
"class Bar {\n" +
"  protected List bars = []\n" +
"  def doStuff() {\n" +
"new Foo().build {\n" +
"  return bars.toString()\n" +
"}\n" +
"  }\n" +
"}\n",

"Main.groovy",
"assert new Bar().doStuff() == 'stuff'\n",
{code}

StaticTypeCheckingVisitor:
{code:java}
// TODO: What if receiver implements get(String)/set(String,Object), 
getProperty(String)/setProperty(String,Object) or propertyMissing(String)?
if (objectExpression instanceof VariableExpression && 
typeCheckingContext.getEnclosingClosure() != null) {
MethodNode mopMethod;
if (readMode) {
mopMethod = receiver.getType().getMethod("getProperty", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name")));
if (mopMethod == null) mopMethod = testClass.getMethod("get", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name")));
} else {
mopMethod = receiver.getType().getMethod("setProperty", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name"), 
GeneralUtils.param(OBJECT_TYPE, "value")));
if (mopMethod == null) mopMethod = testClass.getMethod("set", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name"), 
GeneralUtils.param(OBJECT_TYPE, "value")));
}
if (mopMethod == null) mopMethod = testClass.getMethod("propertyMissing", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name")));

if (mopMethod != null) {
pexp.putNodeMetaData(DYNAMIC_RESOLUTION, Boolean.TRUE);
pexp.removeNodeMetaData(DECLARATION_INFERRED_TYPE);
pexp.removeNodeMetaData(INFERRED_TYPE);
return true;
}
}
{code}


was (Author: emilles):
This is a bit of an experiment.  If the initial issue is re-written this way 
(cut from unit test) and if I add to 
{{StaticTypeCheckingVisitor#existsProperty}} checks for dynamic property 
resolution (see below), then the test case will indeed run through 
{{Foo#propertyMissing}} and there will be no {{ClassCastException}}.

{code:java}
"Foo.groovy",
"class Foo {\n" +
"  def build(@DelegatesTo(value=Foo, 
strategy=Closure.DELEGATE_FIRST) Closure block) {\n" +
"return this.with(block)\n" +
"  }\n" +
"  def propertyMissing(String name) {\n" +
"return 'stuff'\n" +
"  }\n" +
"}\n",

"Bar.groovy",
"@groovy.transform.CompileStatic\n" +
"class Bar {\n" +
"  protected List bars = []\n" +
"  String doStuff() {\n" +
"new Foo().build {\n" +
"  return bars.toString()\n" +
"}\n" +
"  }\n" +
"}\n",

"Main.groovy",
"print new Bar().doStuff()\n",
{code}

StaticTypeCheckingVisitor:
{code:java}
// TODO: What if receiver implements get(String)/set(String,Object), 
getProperty(String)/setProperty(String,Object) or propertyMissing(String)?
if (objectExpression instanceof VariableExpression && 
typeCheckingContext.getEnclosingClosure() != null) {
MethodNode mopMethod;
if (readMode) {
mopMethod = receiver.getType().getMethod("getProperty", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name")));
if (mopMethod == null) mopMethod = testClass.getMethod("get", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name")));
} else {
mopMethod = receiver.getType().getMethod("setProperty", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name"), 
GeneralUtils.param(OBJECT_TYPE, "value")));
if (mopMethod == null) mopMethod = testClass.getMethod("set", 
GeneralUtils.params(GeneralUtils.param(STRING_TYPE, "name"), 
GeneralUtils.param(OBJECT_TYPE, "value")));
}
if (mopMethod == null) mopMethod = testClass.getMethod("propertyMissing", 

[jira] [Comment Edited] (GROOVY-7996) Using with method with a closure that references a protected property produces ClassCastException

2019-10-27 Thread Eric Milles (Jira)


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

Eric Milles edited comment on GROOVY-7996 at 10/27/19 3:51 PM:
---

Rolling back initial changes for this issue.  There were a number of other 
issues created by this and I think the case of a delegate having the same 
property name as an owner field is a bit less likely of a use case than the 
others.  Also, there are at east 2 workarounds available for this issue: 1) 
specify the closure as OWNER_FIRST and 2) use "owner" or "thisObject" or "this" 
qualifier on field access.

A number of test cases have been added so if a fix is approached for this 
again, there will be less chance of breaking other closure variable expression 
access scenarios.


was (Author: emilles):
Rolling back initial changes for this issue.  There were a number of other 
issues created by this and I think the case of a delegate having the same 
property name as an owner field is a bit less likely of a use case than the 
others.

A number of test cases have been added so if a fix is approached for this 
again, there will be less chance of breaking other closure variable expression 
access scenarios.

> Using with method with a closure that references a protected property 
> produces ClassCastException
> -
>
> Key: GROOVY-7996
> URL: https://issues.apache.org/jira/browse/GROOVY-7996
> Project: Groovy
>  Issue Type: Bug
>Affects Versions: 2.4.7
>Reporter: Graeme Rocher
>Priority: Major
> Fix For: 2.5.6, 3.0.0-beta-1
>
>  Time Spent: 0.5h
>  Remaining Estimate: 0h
>
> The following example:
> {code}
> class Foo {
> Object propertyMissing(String name) {
>  return "stuff"
> }
> 
> void build(Closure callable) {
>  this.with(callable)
> }
> }
> @groovy.transform.CompileStatic
> class Bar {
> protected List bar = []
> 
> boolean doStuff() {
> Foo foo = new Foo()
> foo.build {
>return bar.isEmpty() 
> }
> }
> }
> new Bar().doStuff()
> {code}
> Produces 
> {code}
> java.lang.ClassCastException: java.lang.String cannot be cast to 
> java.util.List
>   at Bar$_doStuff_closure1.doCall(ConsoleScript3:19)
>   at Bar$_doStuff_closure1.call(ConsoleScript3)
>   at 
> org.codehaus.groovy.runtime.DefaultGroovyMethods.with(DefaultGroovyMethods.java:242)
>   at Bar.doStuff(ConsoleScript3:18)
>   at Ba
> {code}
> The equivalent code without CompileStatic prints:
> {code}
> Result: false
> {code}
> The behaviour of both should be he same IMO



--
This message was sent by Atlassian Jira
(v8.3.4#803005)


[jira] [Comment Edited] (GROOVY-7996) Using with method with a closure that references a protected property produces ClassCastException

2019-04-18 Thread Eric Milles (JIRA)


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

Eric Milles edited comment on GROOVY-7996 at 4/18/19 8:04 PM:
--

If written this way, no error occurs on Groovy 2.4:
{code}
class Foo {
  def propertyMissing(String name) {
return 'stuff'
  }
  def build(@DelegatesTo(value=Foo, strategy=Closure.OWNER_FIRST) Closure 
block) {
block.delegate = this
return block.call()
  }
}

@groovy.transform.CompileStatic
class Bar {
  protected List bars = []
  boolean doStuff() {
new Foo().build {
  return bars.isEmpty()
}
  }
}
{code}
This should return {{true}} for {{new Bar().doStuff()}} since {{build}} now 
returns the value returned from the closure.


was (Author: emilles):
If written this way, no error occurs on Groovy 2.4:
{code:groovy}
class Foo {
  def propertyMissing(String name) {
return 'stuff'
  }
  def build(@DelegatesTo(value=Foo, strategy=Closure.OWNER_FIRST) Closure 
block) {
block.delegate = this
return block()
  }
}

@groovy.transform.CompileStatic
class Bar {
  protected List bars = []
  boolean doStuff() {
new Foo().build {
  return bars.isEmpty()
}
  }
}
{code}

This should return {{true}} for {{new Bar().doStuff()}} since {{build}} now 
returns the value returned from the closure.

> Using with method with a closure that references a protected property 
> produces ClassCastException
> -
>
> Key: GROOVY-7996
> URL: https://issues.apache.org/jira/browse/GROOVY-7996
> Project: Groovy
>  Issue Type: Bug
>Affects Versions: 2.4.7
>Reporter: Graeme Rocher
>Assignee: Paul King
>Priority: Major
> Fix For: 2.5.6, 3.0.0-beta-1
>
>  Time Spent: 0.5h
>  Remaining Estimate: 0h
>
> The following example:
> {code}
> class Foo {
> Object propertyMissing(String name) {
>  return "stuff"
> }
> 
> void build(Closure callable) {
>  this.with(callable)
> }
> }
> @groovy.transform.CompileStatic
> class Bar {
> protected List bar = []
> 
> boolean doStuff() {
> Foo foo = new Foo()
> foo.build {
>return bar.isEmpty() 
> }
> }
> }
> new Bar().doStuff()
> {code}
> Produces 
> {code}
> java.lang.ClassCastException: java.lang.String cannot be cast to 
> java.util.List
>   at Bar$_doStuff_closure1.doCall(ConsoleScript3:19)
>   at Bar$_doStuff_closure1.call(ConsoleScript3)
>   at 
> org.codehaus.groovy.runtime.DefaultGroovyMethods.with(DefaultGroovyMethods.java:242)
>   at Bar.doStuff(ConsoleScript3:18)
>   at Ba
> {code}
> The equivalent code without CompileStatic prints:
> {code}
> Result: false
> {code}
> The behaviour of both should be he same IMO



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)


[jira] [Comment Edited] (GROOVY-7996) Using with method with a closure that references a protected property produces ClassCastException

2019-01-21 Thread Paul King (JIRA)


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

Paul King edited comment on GROOVY-7996 at 1/22/19 4:46 AM:


Proposed PR merged. Workaround is to use `owner.bar.isEmpty()` orĀ 
`this.bar.isEmpty()`


was (Author: paulk):
Proposed PR merged.

> Using with method with a closure that references a protected property 
> produces ClassCastException
> -
>
> Key: GROOVY-7996
> URL: https://issues.apache.org/jira/browse/GROOVY-7996
> Project: Groovy
>  Issue Type: Bug
>Affects Versions: 2.4.7
>Reporter: Graeme Rocher
>Assignee: Paul King
>Priority: Major
> Fix For: 2.5.6, 3.0.0-alpha-5
>
>  Time Spent: 20m
>  Remaining Estimate: 0h
>
> The following example:
> {code}
> class Foo {
> Object propertyMissing(String name) {
>  return "stuff"
> }
> 
> void build(Closure callable) {
>  this.with(callable)
> }
> }
> @groovy.transform.CompileStatic
> class Bar {
> protected List bar = []
> 
> boolean doStuff() {
> Foo foo = new Foo()
> foo.build {
>return bar.isEmpty() 
> }
> }
> }
> new Bar().doStuff()
> {code}
> Produces 
> {code}
> java.lang.ClassCastException: java.lang.String cannot be cast to 
> java.util.List
>   at Bar$_doStuff_closure1.doCall(ConsoleScript3:19)
>   at Bar$_doStuff_closure1.call(ConsoleScript3)
>   at 
> org.codehaus.groovy.runtime.DefaultGroovyMethods.with(DefaultGroovyMethods.java:242)
>   at Bar.doStuff(ConsoleScript3:18)
>   at Ba
> {code}
> The equivalent code without CompileStatic prints:
> {code}
> Result: false
> {code}
> The behaviour of both should be he same IMO



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)