Skip to content

Commit

Permalink
GROOVY-11368: STC: store parameter inferred type, except self-type param
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed May 6, 2024
1 parent 0cc58e8 commit 2a078df
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -653,10 +653,11 @@ public void visitVariableExpression(final VariableExpression vexp) {
localVariable = (VariableExpression) accessedVariable;
}

ClassNode inferredType = localVariable.getNodeMetaData(INFERRED_TYPE);
inferredType = getInferredTypeFromTempInfo(localVariable, inferredType);
if (inferredType != null && !inferredType.equals(OBJECT_TYPE)
&& !inferredType.equals(accessedVariable.getOriginType())) {
ClassNode inferredType = getInferredTypeFromTempInfo(localVariable, localVariable.getNodeMetaData(INFERRED_TYPE));
if (inferredType != null
&& !inferredType.equals(OBJECT_TYPE)
&& !inferredType.equals(isTraitSelf(vexp))
&& !inferredType.isGenericsPlaceHolder()){
vexp.putNodeMetaData(INFERRED_TYPE, inferredType);
}
}
Expand Down
122 changes: 111 additions & 11 deletions src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
class C {
String p
}
def x = new C().getP()
x = x?.toUpperCase()
'''
Expand All @@ -371,7 +370,6 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
}
}
}
String which = new C().m()
assert which == 'PROPERTY'
"""
Expand Down Expand Up @@ -526,6 +524,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
'''
}

// GROOVY-5585
void testClassPropertyOnInterface() {
assertScript '''
Class test(Serializable arg) {
Expand Down Expand Up @@ -625,8 +624,38 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
'''
}

// GROOVY-8074
void testMapPropertyAccess3() {
assertScript '''
Map map = [a:1, b:2]
assert map['a'] == 1
String bee = 'b'
assert map[bee] == 2
'''
}

void testMapPropertyAccess4() {
assertScript '''
class C {
public static final Map TABLE = [key:'value']
}
String name = 'key'
assert C.TABLE[name] == 'value'
'''
}

// GROOVY-5797
void testMapPropertyAccess5() {
assertScript '''
def test(Map foo) {
def map = [baz: 1]
map[ foo.bar ]
}
assert test(bar:'baz') == 1
'''
}

// GROOVY-8074
void testMapPropertyAccess6() {
assertScript '''
class C extends HashMap {
def foo = 1
Expand All @@ -635,20 +664,55 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
map.put('foo', 42)
assert map.foo == 42
'''

assertScript """
def map = new ${MapType.name}()
map.put('foo', 42)
assert map.foo == 42
"""
}

// GROOVY-5001, GROOVY-5491, GROOVY-6144
void testMapPropertyAccess7() {
String types = '''
class A { }
class B { }
class C extends HashMap<String,A> {
B b = new B()
}
'''
assertScript types + '''
def map = new C()
map.put('a', new A())
assert map.get('a') != null
assert map.get('b') == null
A a = map.a
B b = map.b
a = map['a']
//b = map['b']
assert a instanceof A
//assert b instanceof B
'''
assertScript types + '''
def test(C map) {
A a = map.a
B b = map.b
a = map['a']
//b = map['b']
assert a instanceof A
//assert b instanceof B
}
test(new C().tap{ put('a', new A()) })
'''
}

// GROOVY-5517
void testMapPropertyAccess4() {
assertScript '''
void testMapPropertyAccess8() {
String type = '''
class C extends HashMap {
public static int version = 666
}
'''
assertScript type + '''
def map = new C()
map.foo = 123
def value = map.foo
Expand All @@ -660,6 +724,45 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
assert value == null
assert C.version == 666
'''
assertScript type + '''
def test(C map) {
map.foo = 123
def value = map.foo
assert value == 123
map['foo'] = 4.5
value = map['foo']
assert value == 4.5
value = map.version
assert value == null
assert C.version == 666
}
test(new C())
'''
}

// GROOVY-11368
void testMapPropertyAccess9() {
String type = '''
class C implements Map<String,String> {
@Delegate Map<String,String> impl = [:]
}
'''
assertScript type + '''
def map = new C()
assert map.entry == null
assert map.empty == null
assert map.class == null
assert map.metaClass == null
'''
assertScript type + '''
def test(C map) {
assert map.entry == null
assert map.empty == null
assert map.class == null
assert map.metaClass == null
}
test(new C())
'''
}

void testTypeCheckerDoesNotThinkPropertyIsReadOnly() {
Expand All @@ -673,15 +776,12 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
// a subclass defining its own field
class D extends C {
private String foo
D(String msg) {
this.foo = msg
}
public String getFoo() { this.foo }
private String foo
public String getFoo() { this.foo }
}
def d = new D('bar')
assert d.foo == 'bar'
assert d.fooFromC == 'foo'
Expand Down

0 comments on commit 2a078df

Please sign in to comment.