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 2021/03/29 14:26:00 UTC
[groovy] 03/03: GROOVY-9967: makeGroovyObjectGetPropertySite:
leverage property owner
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 42798a8bc60fa71d926ed2bf75e40f97ff9fcdf4
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Mar 29 09:25:43 2021 -0500
GROOVY-9967: makeGroovyObjectGetPropertySite: leverage property owner
Conflicts:
src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
---
.../classgen/asm/sc/StaticTypesCallSiteWriter.java | 14 ++---
.../transform/stc/TypeInferenceSTCTest.groovy | 52 +++++++++++++++-
.../classgen/asm/sc/bugs/Groovy6276Bug.groovy | 70 ++++++++++------------
3 files changed, 87 insertions(+), 49 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index 33329c6..da059f7 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -416,21 +416,17 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
}
@Override
- public void makeGroovyObjectGetPropertySite(final Expression receiver, final String methodName, final boolean safe, final boolean implicitThis) {
- TypeChooser typeChooser = controller.getTypeChooser();
- ClassNode classNode = controller.getClassNode();
- ClassNode receiverType = typeChooser.resolveType(receiver, classNode);
- if (receiver instanceof VariableExpression && ((VariableExpression) receiver).isThisExpression() && !controller.isInClosure()) {
- receiverType = classNode;
+ public void makeGroovyObjectGetPropertySite(final Expression receiver, final String propertyName, final boolean safe, final boolean implicitThis) {
+ ClassNode receiverType = controller.getClassNode();
+ if (!AsmClassGenerator.isThisExpression(receiver) || controller.isInClosure()) {
+ receiverType = getPropertyOwnerType(receiver); // GROOVY-9967, et al.
}
- String propertyName = methodName;
if (implicitThis) {
if (controller.getInvocationWriter() instanceof StaticInvocationWriter) {
MethodCallExpression currentCall = ((StaticInvocationWriter) controller.getInvocationWriter()).getCurrentCall();
if (currentCall != null && currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER) != null) {
- propertyName = currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
- String[] props = propertyName.split("\\.");
+ String[] props = currentCall.<String>getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER).split("\\.");
BytecodeExpression thisLoader = new BytecodeExpression() {
@Override
public void visit(final MethodVisitor mv) {
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index 2ae9b95..cabdcc0 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -252,7 +252,7 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
'''
}
- void testInstanceOfInferenceWithField() {
+ void testInstanceOfInferenceWithProperty1() {
assertScript '''
class A {
int x
@@ -264,7 +264,7 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
'''
}
- void testInstanceOfInferenceWithFieldAndAssignment() {
+ void testInstanceOfInferenceWithProperty2() {
shouldFailWithMessages '''
class A {
int x
@@ -276,7 +276,7 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
''', 'Cannot assign value of type java.lang.String to variable of type int'
}
- void testInstanceOfInferenceWithMissingField() {
+ void testInstanceOfInferenceWithMissingProperty() {
shouldFailWithMessages '''
class A {
int x
@@ -288,6 +288,52 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
''', 'No such property: y for class: A'
}
+ // GROOVY-9967
+ void testInstanceOfInferenceWithSubclassProperty() {
+ assertScript '''
+ class A {
+ int i
+ }
+ class B extends A {
+ String s = 'foo'
+ }
+
+ String scenario1(x) {
+ (x instanceof String) ? x.toLowerCase() : 'bar'
+ }
+ String scenario2(B x) {
+ x.s
+ }
+ String scenario2a(B x) {
+ x.getS()
+ }
+ String scenario3(B x) {
+ (x instanceof B) ? x.s : 'bar'
+ }
+ String scenario3a(B x) {
+ (x instanceof B) ? x.getS() : 'bar'
+ }
+ String scenario4(A x) {
+ (x instanceof B) ? x.s : 'bar' // Access to A#s is forbidden
+ }
+ String scenario4a(A x) {
+ (x instanceof B) ? x.getS() : 'bar'
+ }
+
+ assert scenario1(null) == 'bar'
+ assert scenario1('Foo') == 'foo'
+ assert scenario2(new B()) == 'foo'
+ assert scenario2a(new B()) == 'foo'
+ assert scenario3(new B()) == 'foo'
+ assert scenario3a(new B()) == 'foo'
+
+ assert scenario4(new A()) == 'bar'
+ assert scenario4(new B()) == 'foo'
+ assert scenario4a(new A()) == 'bar'
+ assert scenario4a(new B()) == 'foo'
+ '''
+ }
+
void testShouldNotFailWithWith() {
assertScript '''
class A {
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6276Bug.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6276Bug.groovy
index 51fa3ce..171d006 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6276Bug.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6276Bug.groovy
@@ -16,56 +16,52 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-
-
-
-
-
package org.codehaus.groovy.classgen.asm.sc.bugs
import groovy.transform.stc.StaticTypeCheckingTestCase
import org.codehaus.groovy.classgen.asm.sc.StaticCompilationTestSupport
-class Groovy6276Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+final class Groovy6276Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+
void testOuterClassMethodCall() {
- assertScript '''class Outer {
- private int outerField = 1
+ assertScript '''
+ class Outer {
+ private int outerField = 1
- private int outerMethod() { 2 }
- int outerProperty = 3
- class Inner {
- void assertions() {
- assert outerField == 1 // #1
- assert outerMethod() == 2 // #2
- assert outerProperty == 3 // #3
- assert getOuterProperty() == 3 // #4
- }
- }
+ private int outerMethod() { 2 }
+ int outerProperty = 3
+ class Inner {
+ void assertions() {
+ assert outerField == 1 // #1
+ assert outerMethod() == 2 // #2
+ assert outerProperty == 3 // #3
+ assert getOuterProperty() == 3 // #4
+ }
+ }
- void test() {
- new Inner().assertions()
- }
-}
+ void test() {
+ new Inner().assertions()
+ }
+ }
-new Outer().test()
- '''
+ new Outer().test()
+ '''
}
void testAccessPrivateMethodFromClosure() {
assertScript '''
- class Outer {
- private int foo(int x) {
- 2*x
- }
+ class Outer {
+ private int foo(int x) {
+ 2*x
+ }
- public int bar() {
- (Integer) [1,2,3].collect {
- foo(it)
- }.sum()
- }
- }
- new Outer().bar()
-'''
+ int bar() {
+ (Integer) [1,2,3].collect {
+ foo(it)
+ }.sum()
+ }
+ }
+ new Outer().bar()
+ '''
}
}