This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
new 1099b93445 GROOVY-11369: STC: map entry comes before access method
(pt.3)
1099b93445 is described below
commit 1099b93445df2a460cb9772ec1d5105f8d45838c
Author: Eric Milles <[email protected]>
AuthorDate: Wed May 15 14:22:12 2024 -0500
GROOVY-11369: STC: map entry comes before access method (pt.3)
---
.../transform/stc/StaticTypeCheckingVisitor.java | 17 ++++---
.../stc/FieldsAndPropertiesSTCTest.groovy | 56 +++++++++++++++++-----
2 files changed, 55 insertions(+), 18 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 397189ea7e..6c7abe4692 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1583,6 +1583,9 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
}
+ PropertyNode property = current.getProperty(propertyName);
+ property = allowStaticAccessToMember(property, staticOnly);
+
MethodNode getter = null;
if (!isMapProperty(pexp)) { // GROOVY-11369: map entry before
getter
getter = findGetter(current, isserName,
pexp.isImplicitThis());
@@ -1594,11 +1597,13 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
if (getter != null &&
!hasAccessToMember(typeCheckingContext.getEnclosingClassNode(),
getter.getDeclaringClass(), getter.getModifiers())) {
getter = null; // GROOVY-11319
}
- if (readMode && getter != null && visitor != null)
visitor.visitMethod(getter);
+ if (readMode && getter != null && visitor != null) {
+ visitor.visitMethod(getter);
+ }
+ } else if (readMode) { // GROOVY-5001, GROOVY-5491, GROOVY-8555
+ if (property != null) { property = null; field = null; }
}
- PropertyNode property = current.getProperty(propertyName);
- property = allowStaticAccessToMember(property, staticOnly);
// prefer explicit getter or setter over property if receiver
is not 'this'
if (property == null ||
!enclosingTypes.contains(receiverType)) {
if (readMode) {
@@ -1622,9 +1627,9 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
visitor.visitField(virtual);
}
}
- SetterInfo info = new SetterInfo(current,
setterName, setters);
BinaryExpression enclosingBinaryExpression =
typeCheckingContext.getEnclosingBinaryExpression();
if (enclosingBinaryExpression != null) {
+ SetterInfo info = new SetterInfo(current,
setterName, setters);
putSetterInfo(enclosingBinaryExpression.getLeftExpression(), info);
}
String delegationData = receiver.getData();
@@ -1752,7 +1757,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
return Modifier.isProtected(modifiers) &&
accessor.isDerivedFrom(receiver);
}
- private MethodNode findGetter(final ClassNode current, String name, final
boolean searchOuterClasses) {
+ private static MethodNode findGetter(final ClassNode current, String name,
final boolean searchOuterClasses) {
MethodNode getterMethod = current.getGetterMethod(name);
if (getterMethod == null && searchOuterClasses &&
current.getOuterClass() != null) {
return findGetter(current.getOuterClass(), name, true);
@@ -1828,7 +1833,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
private boolean isMapProperty(final PropertyExpression pexp) {
final Expression objectExpression = pexp.getObjectExpression();
- if ((isThisExpression(objectExpression) ||
isSuperExpression(objectExpression))
+ if (isThisExpression(objectExpression)
&&
Arrays.asList(getTypeCheckingAnnotations()).contains(COMPILESTATIC_CLASSNODE)) {
return false;
}
diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index 8a9d097ec1..e2583d8f32 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -716,7 +716,7 @@ class FieldsAndPropertiesSTCTest extends
StaticTypeCheckingTestCase {
for (mod in ['def', 'public', 'protected',
'@groovy.transform.PackageScope', 'private']) {
assertScript """
class C implements Map<String,String> {
- @Delegate Map<String,String> impl =
[:].withDefault{'entry'}
+ @Delegate Map<String,String> impl = [:].withDefault{
'entry' }
$mod getFoo() { 'getter' }
void test() {
@ASTTest(phase=INSTRUCTION_SELECTION, value={
@@ -756,7 +756,7 @@ class FieldsAndPropertiesSTCTest extends
StaticTypeCheckingTestCase {
"""
}
- // GROOVY-5001, GROOVY-5491, GROOVY-6144
+ // GROOVY-5001, GROOVY-5491, GROOVY-6144, GROOVY-8555
void testMapPropertyAccess7() {
String types = '''
class A { }
@@ -770,24 +770,56 @@ class FieldsAndPropertiesSTCTest extends
StaticTypeCheckingTestCase {
map.put('a', new A())
assert map.get('a') != null
assert map.get('b') == null
- A a = map.a
- B b = map.b
+ def a = map.a
+ def b = map.b
+ assert a instanceof A
+ assert b !instanceof B : 'not yet'
a = map['a']
- //b = map['b']
- assert a instanceof A
- //assert b instanceof B
+ b = map['b']
+ assert a instanceof A
+ assert b !instanceof B : 'not yet'
'''
assertScript types + '''
def test(C map) {
- A a = map.a
- B b = map.b
+ def a = map.a
+ def b = map.b
+ assert a instanceof A
+ assert b !instanceof B : 'not yet'
a = map['a']
- //b = map['b']
- assert a instanceof A
- //assert b instanceof B
+ b = map['b']
+ assert a instanceof A
+ assert b !instanceof B : 'not yet'
}
test(new C().tap{ put('a', new A()) })
'''
+ assertScript types + '''
+ C map = new C()
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE).name == 'A'
+ })
+ def b = map.b // entry
+ assert b == null
+ map.b = null // setter
+ assert map.getB() == null
+ assert !map.containsKey('b')
+ '''
+ assertScript types + '''
+ class D extends C {
+ void test() {
+ //this.a fails hard for SC
+ //typeof(this.b) is A for STC and B for SC
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE).name == 'A'
+ })
+ def b = super.b
+ assert b instanceof A
+ }
+ }
+ def map = new D()
+ map.put('a', new A())
+ map.put('b', new A())
+ map.test()
+ '''
}
// GROOVY-5517