You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2019/11/05 22:33:22 UTC
[groovy] 01/01: GROOVY-7996: check for get(String)/set(String,
Object) or propertyMissing
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-7996
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 3a9b12ad1f3f2307936eb2b3a014a9195d655ff8
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Oct 29 14:37:21 2019 -0500
GROOVY-7996: check for get(String)/set(String,Object) or propertyMissing
---
.../transform/stc/StaticTypeCheckingVisitor.java | 19 +++++++++++++++++++
src/test/groovy/bugs/Groovy7996.groovy | 14 +++++++++-----
.../src/spec/test/MarkupTemplateEngineSpecTest.groovy | 7 ++++---
3 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index f38d0d7..3e562e2 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1716,6 +1716,25 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
}
}
+
+ // GROOVY-7996: check if receiver implements get(String)/set(String,Object) or propertyMissing(String)
+ if (!testClass.isArray() && !isPrimitiveType(getUnwrapper(testClass))
+ && objectExpression instanceof VariableExpression && typeCheckingContext.getEnclosingClosure() != null) {
+ MethodNode mopMethod;
+ if (readMode) {
+ mopMethod = testClass.getMethod("get", new Parameter[]{new Parameter(STRING_TYPE, "name")});
+ } else {
+ 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, "propertyName")});
+
+ if (mopMethod != null) {
+ pexp.putNodeMetaData(DYNAMIC_RESOLUTION, Boolean.TRUE);
+ pexp.removeNodeMetaData(DECLARATION_INFERRED_TYPE);
+ pexp.removeNodeMetaData(INFERRED_TYPE);
+ return true;
+ }
+ }
}
for (Receiver<String> receiver : receivers) {
diff --git a/src/test/groovy/bugs/Groovy7996.groovy b/src/test/groovy/bugs/Groovy7996.groovy
index fc0872f..39de261 100644
--- a/src/test/groovy/bugs/Groovy7996.groovy
+++ b/src/test/groovy/bugs/Groovy7996.groovy
@@ -18,16 +18,18 @@
*/
package groovy.bugs
-import groovy.test.NotYetImplemented
+import groovy.transform.CompileStatic
import org.junit.Test
import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
+@CompileStatic
final class Groovy7996 {
- @Test @NotYetImplemented
+ @Test
void testFieldAccessFromClosure1() {
- assertScript '''
+ def err = shouldFail '''
class Foo {
def build(@DelegatesTo(value=Foo, strategy=Closure.DELEGATE_FIRST) Closure block) {
this.with(block)
@@ -45,13 +47,15 @@ final class Groovy7996 {
boolean doStuff() {
Foo foo = new Foo()
foo.build {
- bar.isEmpty() // "ClassCastException: java.lang.String cannot be cast to java.util.List"
+ bar.isEmpty() // ClassCastException: java.lang.String cannot be cast to java.util.List
}
}
}
- assert new Bar().doStuff()
+ new Bar().doStuff()
'''
+
+ assert err =~ /Cannot find matching method java.lang.Object#isEmpty\(\)/
}
@Test
diff --git a/subprojects/groovy-templates/src/spec/test/MarkupTemplateEngineSpecTest.groovy b/subprojects/groovy-templates/src/spec/test/MarkupTemplateEngineSpecTest.groovy
index c94f449..da68093 100644
--- a/subprojects/groovy-templates/src/spec/test/MarkupTemplateEngineSpecTest.groovy
+++ b/subprojects/groovy-templates/src/spec/test/MarkupTemplateEngineSpecTest.groovy
@@ -22,7 +22,8 @@ import groovy.text.Template
import groovy.text.markup.MarkupTemplateEngine
import groovy.text.markup.TemplateConfiguration
-class MarkupTemplateEngineSpecTest extends GroovyTestCase {
+final class MarkupTemplateEngineSpecTest extends GroovyTestCase {
+
private MarkupTemplateEngine engine
private TemplateConfiguration config
private Map model
@@ -621,7 +622,7 @@ pages.each { page -> // <1>
// end::typechecked_setup_fixed[]
*/
- assertError 'No such property: text for class: MarkupTemplateEngineSpecTest$Page'
+ assertError 'No such property: text for class: MarkupTemplateEngineSpec'
}
void testInlinedTypeCheckedModel() {
@@ -654,7 +655,7 @@ pages.each { page ->
// end::typechecked_inlined_template_expected[]
'''
- assertError 'No such property: text for class: MarkupTemplateEngineSpecTest$Page'
+ assertError 'No such property: text for class: MarkupTemplateEngineSpec'
}
void testFragment() {