You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/06/13 13:40:23 UTC
[groovy] 04/06: GROOVY-7701: do not cast RHS before LHS of
assignment is visited
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 1c779b7baf6c9e4ea9839ed5d36b6adbf1e2a124
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Jun 4 13:59:12 2020 -0500
GROOVY-7701: do not cast RHS before LHS of assignment is visited
(cherry picked from commit 3bf8f9fe71aaa471a72029d410cedbffa83d52fb)
---
.../classgen/asm/BinaryExpressionHelper.java | 8 ++----
src/test/groovy/lang/ClosureResolvingTest.groovy | 31 +++++++++++++++++++---
2 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
index 02f02e9..0e3f623 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
@@ -382,8 +382,8 @@ public class BinaryExpressionHelper {
operandStack.loadOrStoreVariable(var, false);
return;
}
-
- // let's evaluate the RHS and store the result
+ // evaluate the RHS and store the result
+ // TODO: LHS has not been visited, it could be a variable in a closure and type chooser is not aware.
ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode());
if (rightExpression instanceof ListExpression && lhsType.isArray()) {
ListExpression list = (ListExpression) rightExpression;
@@ -467,11 +467,7 @@ public class BinaryExpressionHelper {
} else {
// normal assignment
int mark = operandStack.getStackLength();
- // to leave a copy of the rightExpression value on the stack after the assignment.
rhsValueLoader.visit(acg);
- TypeChooser typeChooser = controller.getTypeChooser();
- ClassNode targetType = typeChooser.resolveType(leftExpression, controller.getClassNode());
- operandStack.doGroovyCast(targetType);
leftExpression.visit(acg);
operandStack.remove(operandStack.getStackLength() - mark);
}
diff --git a/src/test/groovy/lang/ClosureResolvingTest.groovy b/src/test/groovy/lang/ClosureResolvingTest.groovy
index 14f27a2..69d2932 100644
--- a/src/test/groovy/lang/ClosureResolvingTest.groovy
+++ b/src/test/groovy/lang/ClosureResolvingTest.groovy
@@ -84,7 +84,33 @@ class ClosureResolvingTest extends GroovyTestCase {
assertEquals "stuff", c.call()
c.delegate = new TestResolve1()
assertEquals "foo", c.call()
+ }
+
+ // GROOVY-7701
+ void testResolveDelegateFirst2() {
+ assertScript '''
+ class Foo {
+ List type
+ }
+ class Bar {
+ int type = 10
+ List<Foo> something = { ->
+ List<Foo> tmp = []
+ def foo = new Foo()
+ foo.with {
+ type = ['String']
+ // ^^^^ should be Foo.type, not Bar.type
+ }
+ tmp.add(foo)
+ return tmp
+ }()
+ }
+ def bar = new Bar()
+ assert bar.type == 10
+ assert bar.something*.type == [['String']]
+ assert bar.type == 10
+ '''
}
void testResolveOwnerFirst() {
@@ -125,7 +151,6 @@ class ClosureResolvingTest extends GroovyTestCase {
c.resolveStrategy = Closure.DELEGATE_ONLY
c.delegate = new TestResolve1()
assertEquals "foo", c.call()
-
}
void testResolveOwnerOnly() {
@@ -142,7 +167,6 @@ class ClosureResolvingTest extends GroovyTestCase {
c.resolveStrategy = Closure.OWNER_ONLY
c.delegate = new TestResolve1()
assertEquals "stuff", c.call()
-
}
void testOwnerDelegateChain() {
@@ -196,10 +220,9 @@ class TestResolve2 {
class TestResolve3 {
def del;
- String toString() {del}
+ String toString() { del }
def whoisThis() { return this }
def met() { return "I'm the method inside '" + del + "'" }
}
-