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 2022/08/26 00:06:47 UTC
[groovy] branch GROOVY_3_0_X updated: GROOVY-8074: SC: property syntax for groovy object that implements `Map`
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
new 4d1105e96b GROOVY-8074: SC: property syntax for groovy object that implements `Map`
4d1105e96b is described below
commit 4d1105e96b120381dae91a33332c9ea3d1d689d3
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 25 18:52:27 2022 -0500
GROOVY-8074: SC: property syntax for groovy object that implements `Map`
---
.../groovy/classgen/AsmClassGenerator.java | 12 +-
.../stc/FieldsAndPropertiesSTCTest.groovy | 626 +++++++++++----------
.../ArraysAndCollectionsStaticCompileTest.groovy | 27 +-
.../sc/FieldsAndPropertiesStaticCompileTest.groovy | 416 ++++++--------
4 files changed, 534 insertions(+), 547 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 36602e8e93..8cb1e49b07 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -133,6 +133,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.getSetterName;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.isOrImplements;
import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.PROPERTY_OWNER;
@@ -1072,7 +1073,12 @@ public class AsmClassGenerator extends ClassGenerator {
ClassNode objectExpressionType = controller.getTypeChooser().resolveType(objectExpression, controller.getClassNode());
if (objectExpressionType.equals(ClassHelper.OBJECT_TYPE)) objectExpressionType = objectExpression.getType();
- return objectExpressionType.isDerivedFromGroovyObject();
+ if (isOrImplements(objectExpressionType, ClassHelper.MAP_TYPE)) return false; // GROOVY-8074
+ return implementsGroovyObject(objectExpressionType); // GROOVY-9195, GROOVY-9288, et al.
+ }
+
+ private static boolean implementsGroovyObject(final ClassNode cn) {
+ return cn.isDerivedFromGroovyObject() || (!cn.isInterface() && cn.getCompileUnit() != null);
}
@Override
@@ -1585,8 +1591,8 @@ public class AsmClassGenerator extends ClassGenerator {
public void loadWrapper(final Expression argument) {
MethodVisitor mv = controller.getMethodVisitor();
ClassNode goalClass = argument.getType();
- visitClassExpression(new ClassExpression(goalClass));
- if (goalClass.isDerivedFromGroovyObject()) {
+ visitClassExpression(classX(goalClass));
+ if (implementsGroovyObject(goalClass)) {
createGroovyObjectWrapperMethod.call(mv);
} else {
createPojoWrapperMethod.call(mv);
diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index e2c57ad82e..08689348b9 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -27,78 +27,66 @@ import groovy.transform.PackageScope
class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
void testAssignFieldValue() {
- assertScript """
- class A {
+ assertScript '''
+ class C {
int x
}
-
- A a = new A()
- a.x = 1
- """
+ C c = new C()
+ c.x = 1
+ '''
}
void testAssignFieldValueWithWrongType() {
shouldFailWithMessages '''
- class A {
+ class C {
int x
}
-
- A a = new A()
- a.x = '1'
- ''', 'Cannot assign value of type java.lang.String to variable of type int'
- }
-
- void testMapDotPropertySyntax() {
- assertScript '''
- HashMap map = [:]
- map['a'] = 1
- map.b = 2
- assert map.get('a') == 1
- assert map.get('b') == 2
- '''
+ C c = new C()
+ c.x = '1'
+ ''',
+ 'Cannot assign value of type java.lang.String to variable of type int'
}
void testInferenceFromFieldType() {
assertScript '''
- class A {
+ class C {
String name = 'Cedric'
}
- A a = new A()
- def b = a.name
- b.toUpperCase() // type of b should be inferred from field type
+ C c = new C()
+ def x = c.name
+ x.toUpperCase() // type of x should be inferred from field type
'''
}
void testAssignFieldValueWithAttributeNotation() {
- assertScript """
- class A {
+ assertScript '''
+ class C {
int x
}
-
- A a = new A()
- a.@x = 1
- """
+ C c = new C()
+ c.@x = 1
+ '''
}
void testAssignFieldValueWithWrongTypeAndAttributeNotation() {
shouldFailWithMessages '''
- class A {
+ class C {
int x
}
-
- A a = new A()
- a.@x = '1'
- ''', 'Cannot assign value of type java.lang.String to variable of type int'
+ C c = new C()
+ c.@x = '1'
+ ''',
+ 'Cannot assign value of type java.lang.String to variable of type int'
}
void testInferenceFromAttributeType() {
assertScript '''
- class A {
+ class C {
String name = 'Cedric'
}
- A a = new A()
- def b = a.@name
- b.toUpperCase() // type of b should be inferred from field type
+ C c = new C()
+ def x = c.@name
+ x.toUpperCase() // type of x should be inferred from field type
'''
}
@@ -106,133 +94,141 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
shouldFailWithMessages '''
Object o = new Object()
o.x = 0
- ''', 'No such property: x for class: java.lang.Object'
+ ''',
+ 'No such property: x for class: java.lang.Object'
}
void testShouldComplainAboutMissingProperty2() {
shouldFailWithMessages '''
- class A {
+ class C {
}
- A a = new A()
- a.x = 0
- ''', 'No such property: x for class: A'
+ C c = new C()
+ c.x = 0
+ ''',
+ 'No such property: x for class: C'
}
@NotYetImplemented
void testShouldComplainAboutMissingProperty3() {
shouldFailWithMessages '''
- class A {
+ class C {
private x
}
- class B extends A {
+ class D extends C {
void test() {
this.x
}
}
- ''', 'The field A.x is not accessible'
+ ''',
+ 'The field C.x is not accessible'
}
void testShouldComplainAboutMissingAttribute() {
shouldFailWithMessages '''
Object o = new Object()
o.@x = 0
- ''', 'No such attribute: x for class: java.lang.Object'
+ ''',
+ 'No such attribute: x for class: java.lang.Object'
}
void testShouldComplainAboutMissingAttribute2() {
shouldFailWithMessages '''
- class A {
+ class C {
}
- A a = new A()
- a.@x = 0
- ''', 'No such attribute: x for class: A'
+ C c = new C()
+ c.@x = 0
+ ''',
+ 'No such attribute: x for class: C'
}
void testShouldComplainAboutMissingAttribute3() {
shouldFailWithMessages '''
- class A {
+ class C {
def getX() { }
}
- A a = new A()
- println a.@x
- ''', 'No such attribute: x for class: A'
+ C c = new C()
+ println c.@x
+ ''',
+ 'No such attribute: x for class: C'
}
void testShouldComplainAboutMissingAttribute4() {
shouldFailWithMessages '''
- class A {
+ class C {
def setX(x) { }
}
- A a = new A()
- a.@x = 0
- ''', 'No such attribute: x for class: A'
+ C c = new C()
+ c.@x = 0
+ ''',
+ 'No such attribute: x for class: C'
}
void testShouldComplainAboutMissingAttribute5() {
shouldFailWithMessages '''
- class A {
+ class C {
private x
}
- class B extends A {
+ class D extends C {
void test() {
this.@x
}
}
- ''', 'The field A.x is not accessible'
+ ''',
+ 'The field C.x is not accessible'
}
void testPropertyWithInheritance() {
assertScript '''
- class A {
+ class C {
int x
}
- class B extends A {
+ class D extends C {
}
-
- B b = new B()
- assert b.x == 0
-
- b.x = 2
- assert b.x == 2
+ D d = new D()
+ assert d.x == 0
+ d.x = 2
+ assert d.x == 2
'''
}
void testPropertyTypeWithInheritance() {
shouldFailWithMessages '''
- class A {
+ class C {
int x
}
- class B extends A {
+ class D extends C {
}
- B b = new B()
- b.x = '2'
- ''', 'Cannot assign value of type java.lang.String to variable of type int'
+ D d = new D()
+ d.x = '2'
+ ''',
+ 'Cannot assign value of type java.lang.String to variable of type int'
}
void testPropertyWithInheritanceFromAnotherSourceUnit() {
assertScript '''
- class B extends groovy.transform.stc.FieldsAndPropertiesSTCTest.BaseClass {
+ class C extends groovy.transform.stc.FieldsAndPropertiesSTCTest.BaseClass {
}
- B b = new B()
- b.x = 2
+ C c = new C()
+ c.x = 2
'''
}
void testPropertyWithInheritanceFromAnotherSourceUnit2() {
shouldFailWithMessages '''
- class B extends groovy.transform.stc.FieldsAndPropertiesSTCTest.BaseClass {
+ class C extends groovy.transform.stc.FieldsAndPropertiesSTCTest.BaseClass {
}
- B b = new B()
- b.x = '2'
- ''', 'Cannot assign value of type java.lang.String to variable of type int'
+ C c = new C()
+ c.x = '2'
+ ''',
+ 'Cannot assign value of type java.lang.String to variable of type int'
}
void testPropertyWithSuperInheritanceFromAnotherSourceUnit() {
assertScript '''
- class B extends groovy.transform.stc.FieldsAndPropertiesSTCTest.BaseClass2 {
+ class C extends groovy.transform.stc.FieldsAndPropertiesSTCTest.BaseClass2 {
}
- B b = new B()
- b.x = 2
+ C c = new C()
+ c.x = 2
'''
}
@@ -240,6 +236,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
void testStaticPropertyWithInheritanceFromAnotherSourceUnit() {
assertScript '''
import groovy.transform.stc.FieldsAndPropertiesSTCTest.Public
+
assert Public.answer == 42
assert Public.CONST == 'XX'
assert Public.VALUE == null
@@ -247,6 +244,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
assert Public.VALUE == 'YY'
Public.@VALUE = 'ZZ'
assert Public.@VALUE == 'ZZ'
+ Public.VALUE = null
'''
}
@@ -277,7 +275,6 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
Integer m() { 123456 - p }
Integer m(int i) { i - p }
}
-
def c = new C()
assert c.m() == 123456 // BUG! exception in phase 'class generation' ...
assert c.m(123) == 123 // ClassCastException: class org.codehaus.groovy.ast.Parameter cannot be cast to ...
@@ -289,7 +286,6 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
assertScript '''
class Person {
String name
-
static Person create() {
def p = new Person()
p.setName("Guillaume")
@@ -297,7 +293,6 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
return p
}
}
-
Person.create()
'''
}
@@ -305,69 +300,75 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
// GROOVY-5443
void testFieldInitShouldPass() {
assertScript '''
- class Foo {
+ class C {
int bar = 1
}
- new Foo()
+ new C()
'''
}
// GROOVY-5443
void testFieldInitShouldNotPassBecauseOfIncompatibleTypes() {
shouldFailWithMessages '''
- class Foo {
+ class C {
int bar = new Date()
}
- new Foo()
- ''', 'Cannot assign value of type java.util.Date to variable of type int'
+ new C()
+ ''',
+ 'Cannot assign value of type java.util.Date to variable of type int'
}
// GROOVY-5443
void testFieldInitShouldNotPassBecauseOfIncompatibleTypesWithClosure() {
shouldFailWithMessages '''
- class Foo {
+ class C {
Closure<List> bar = { Date date -> date.getTime() }
}
- new Foo()
- ''', 'Incompatible generic argument types. Cannot assign groovy.lang.Closure <java.lang.Long> to: groovy.lang.Closure <List>'
+ new C()
+ ''',
+ 'Incompatible generic argument types. Cannot assign groovy.lang.Closure <java.lang.Long> to: groovy.lang.Closure <List>'
}
void testFieldInitShouldNotPassBecauseOfIncompatibleTypesWithClosure2() {
shouldFailWithMessages '''
- class Foo {
+ class C {
java.util.function.Supplier<String> bar = { 123 }
}
- new Foo()
- ''', 'Incompatible generic argument types. Cannot assign java.util.function.Supplier <java.lang.Integer> to: java.util.function.Supplier <String>'
+ new C()
+ ''',
+ 'Incompatible generic argument types. Cannot assign java.util.function.Supplier <java.lang.Integer> to: java.util.function.Supplier <String>'
}
// GROOVY-9882
void testFieldInitShouldPassForCompatibleTypesWithClosure() {
assertScript '''
- class Foo {
+ class C {
java.util.function.Supplier<String> bar = { 'abc' }
}
- assert new Foo().bar.get() == 'abc'
+ assert new C().bar.get() == 'abc'
'''
}
void testClosureParameterMismatch() {
shouldFailWithMessages '''
- class Foo {
+ class C {
java.util.function.Supplier<String> bar = { baz -> '' }
}
- ''', 'Wrong number of parameters for method target get()'
+ ''',
+ 'Wrong number of parameters for method target get()'
+
shouldFailWithMessages '''
- class Foo {
+ class C {
java.util.function.Consumer<String> bar = { -> null }
}
- ''', 'Wrong number of parameters for method target accept(java.lang.String)'
+ ''',
+ 'Wrong number of parameters for method target accept(java.lang.String)'
}
// GROOVY-9991
void testClosureParameterMatch() {
assertScript '''
- java.util.function.Consumer<String> s = { print it }
+ java.util.function.Consumer<String> c = { print it }
'''
assertScript '''
java.util.function.Predicate p = { x -> false }
@@ -377,43 +378,6 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
'''
}
- // GROOVY-5517
- void testShouldFindStaticPropertyEvenIfObjectImplementsMap() {
- assertScript '''
- class MyHashMap extends HashMap {
- public static int version = 666
- }
- def map = new MyHashMap()
- map['foo'] = 123
- Object value = map.foo
- assert value == 123
- value = map['foo']
- assert value == 123
- int v = MyHashMap.version
- assert v == 666
- '''
- }
-
- void testListDotProperty() {
- assertScript '''class Elem { int value }
- List<Elem> list = new LinkedList<Elem>()
- list.add(new Elem(value:123))
- list.add(new Elem(value:456))
- assert list.value == [ 123, 456 ]
- list.add(new Elem(value:789))
- assert list.value == [ 123, 456, 789 ]
- '''
-
- assertScript '''class Elem { String value }
- List<Elem> list = new LinkedList<Elem>()
- list.add(new Elem(value:'123'))
- list.add(new Elem(value:'456'))
- assert list.value == [ '123', '456' ]
- list.add(new Elem(value:'789'))
- assert list.value == [ '123', '456', '789' ]
- '''
- }
-
void testClassPropertyOnInterface() {
assertScript '''
Class test(Serializable arg) {
@@ -433,102 +397,163 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
void testSetterUsingPropertyNotation() {
assertScript '''
- class A {
- boolean ok = false;
- void setFoo(String foo) { ok = foo == 'foo' }
+ class C {
+ boolean ok = false
+ void setFoo(String foo) { ok = (foo == 'foo') }
}
- def a = new A()
- a.foo = 'foo'
- assert a.ok
+ def c = new C()
+ c.foo = 'foo'
+ assert c.ok
'''
}
void testSetterUsingPropertyNotationOnInterface() {
assertScript '''
- interface FooAware { void setFoo(String arg) }
- class A implements FooAware {
- void setFoo(String foo) { }
- }
- void test(FooAware a) {
- a.foo = 'foo'
- }
- def a = new A()
- test(a)
- '''
+ interface FooAware { void setFoo(String arg) }
+ class C implements FooAware {
+ void setFoo(String foo) { }
+ }
+ void test(FooAware fa) {
+ fa.foo = 'foo'
+ }
+ def c = new C()
+ test(c)
+ '''
}
- // GROOVY-5700
- void testInferenceOfMapDotProperty() {
+ void testListDotProperty1() {
+ assertScript '''class Elem { int value }
+ List<Elem> list = new LinkedList<Elem>()
+ list.add(new Elem(value:123))
+ list.add(new Elem(value:456))
+ assert list.value == [ 123, 456 ]
+ list.add(new Elem(value:789))
+ assert list.value == [ 123, 456, 789 ]
+ '''
+ assertScript '''class Elem { String value }
+ List<Elem> list = new LinkedList<Elem>()
+ list.add(new Elem(value:'123'))
+ list.add(new Elem(value:'456'))
+ assert list.value == [ '123', '456' ]
+ list.add(new Elem(value:'789'))
+ assert list.value == [ '123', '456', '789' ]
+ '''
+ }
+
+ void testListDotProperty2() {
assertScript '''
- def m = [retries: 10]
+ class C { int x }
+ def list = [new C(x:1), new C(x:2)]
@ASTTest(phase=INSTRUCTION_SELECTION, value={
- assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
+ def type = node.getNodeMetaData(INFERRED_TYPE)
+ assert type.toString(false) == 'java.util.List <java.lang.Integer>'
})
- def r1 = m['retries']
+ def x = list.x
+ assert x == [1,2]
+ '''
+ }
+ // GROOVY-5700
+ void testMapPropertyAccess1() {
+ assertScript '''
+ def map = [key: 123]
@ASTTest(phase=INSTRUCTION_SELECTION, value={
assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
})
- def r2 = m.retries
+ def val = map.key
+ assert val == 123
'''
}
- void testInferenceOfListDotProperty() {
- assertScript '''class Foo { int x }
- def list = [new Foo(x:1), new Foo(x:2)]
+ // GROOVY-5700, GROOVY-8788
+ void testMapPropertyAccess2() {
+ assertScript '''
+ def map = [key: 123]
@ASTTest(phase=INSTRUCTION_SELECTION, value={
- def iType = node.getNodeMetaData(INFERRED_TYPE)
- assert iType == make(List)
- assert iType.isUsingGenerics()
- assert iType.genericsTypes[0].type == Integer_TYPE
+ assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
})
- def r2 = list.x
- assert r2 == [ 1,2 ]
+ def val = map['key']
+ assert val == 123
+ '''
+ }
+
+ // GROOVY-8074
+ void testMapPropertyAccess3() {
+ assertScript '''
+ class C extends HashMap {
+ def foo = 1
+ }
+ def map = new C()
+ map.put('foo', 42)
+ assert map.foo == 42
+ '''
+
+ assertScript """
+ def map = new ${MapType.name}()
+ map.put('foo', 42)
+ assert map.foo == 42
+ """
+ }
+
+ // GROOVY-5517
+ void testMapPropertyAccess4() {
+ assertScript '''
+ class C extends HashMap {
+ public static int version = 666
+ }
+ def map = new C()
+ map['foo'] = 123
+ def value = map.foo
+ assert value == 123
+ map['foo'] = 4.5
+ value = map['foo']
+ assert value == 4.5
+ assert C.version == 666
'''
}
void testTypeCheckerDoesNotThinkPropertyIsReadOnly() {
assertScript '''
// a base class defining a read-only property
- class Top {
+ class C {
private String foo = 'foo'
String getFoo() { foo }
- String getFooFromTop() { foo }
+ String getFooFromC() { foo }
}
// a subclass defining its own field
- class Bottom extends Top {
+ class D extends C {
private String foo
- Bottom(String msg) {
+ D(String msg) {
this.foo = msg
}
public String getFoo() { this.foo }
}
- def b = new Bottom('bar')
- assert b.foo == 'bar'
- assert b.fooFromTop == 'foo'
+ def d = new D('bar')
+ assert d.foo == 'bar'
+ assert d.fooFromC == 'foo'
'''
}
// GROOVY-5779
void testShouldNotUseNonStaticProperty() {
assertScript '''import java.awt.Color
- Color c = Color.red // should not be interpreted as Color.getRed()
+ Color c = Color.red // should not be interpreted as Color.getRed()
'''
}
// GROOVY-5725
void testAccessFieldDefinedInInterface() {
assertScript '''
- class Foo implements groovy.transform.stc.FieldsAndPropertiesSTCTest.InterfaceWithField {
+ class C implements groovy.transform.stc.FieldsAndPropertiesSTCTest.InterfaceWithField {
void test() {
assert boo == "I don't fancy fields in interfaces"
}
}
- new Foo().test()
+ new C().test()
'''
}
@@ -623,7 +648,8 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
}
def i = new Outer.Inner()
def x = i.m()
- ''', 'The variable [p] is undeclared.'
+ ''',
+ 'The variable [p] is undeclared.'
}
void testOuterPropertyAccess7() {
@@ -638,7 +664,8 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
}
def i = new Outer.Inner()
def x = i.m()
- ''', 'No such property: p for class: Outer$Inner'
+ ''',
+ 'No such property: p for class: Outer$Inner'
}
// GROOVY-7024
@@ -647,7 +674,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
class Outer {
static Map props = [bar: 10, baz: 20]
enum Inner {
- FOO('foo'),
+ FOO('foo');
Inner(String name) {
props[name] = 30
}
@@ -660,7 +687,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
void testPrivateFieldAccessInAIC() {
assertScript '''
- class A {
+ class C {
private int x
void foo() {
def aic = new Runnable() { void run() { x = 666 } }
@@ -670,9 +697,9 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
assert x == 666
}
}
- def a = new A()
- a.foo()
- a.ensure()
+ def c = new C()
+ c.foo()
+ c.ensure()
'''
}
@@ -705,7 +732,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
void testPrivateFieldAccessInClosure1() {
assertScript '''
- class A {
+ class C {
private int x
void test() {
def c = { -> x = 666 }
@@ -713,14 +740,28 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
assert x == 666
}
}
- new A().test()
+ new C().test()
'''
}
// GROOVY-9683
void testPrivateFieldAccessInClosure2() {
assertScript '''
- class A {
+ class C {
+ private static X = 'xxx'
+ void test() {
+ [:].with {
+ assert X == 'xxx'
+ }
+ }
+ }
+ new C().test()
+ '''
+ }
+
+ void testPrivateFieldAccessInClosure3() {
+ assertScript '''
+ class C {
private static X = 'xxx'
void test() {
[:].withDefault { throw new MissingPropertyException(it.toString()) }.with {
@@ -728,26 +769,46 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
}
}
}
- new A().test()
+ new C().test()
+ '''
+ }
+
+ // GROOVY-9695
+ void testPrivateFieldAccessInClosure4() {
+ assertScript '''
+ class C {
+ private static final X = 'xxx'
+ void test() {
+ Map m = [:]
+ def c = { ->
+ assert X == 'xxx'
+ m[X] = 123
+ }
+ c()
+ assert m == [xxx:123]
+ }
+ }
+ new C().test()
+
+ class D extends C {
+ }
+ new D().test()
'''
}
// GROOVY-5737
void testGeneratedFieldAccessInClosure() {
assertScript '''
- import groovy.transform.*
import groovy.util.logging.*
@Log
class GreetingActor {
-
- def receive = {
- log.info "test"
- }
-
+ def receive = {
+ log.info "test"
+ }
}
new GreetingActor()
- '''
+ '''
}
// GROOVY-6610
@@ -756,18 +817,14 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
class Outer {
static class Inner {
public final String value
-
Inner(String string) {
value = string
}
-
Inner() {
this(VALUE.toString())
}
}
-
private static Integer VALUE = 42
-
static main(args) {
assert new Inner().value == '42'
}
@@ -778,57 +835,57 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
// GROOVY-5872
void testAssignNullToFieldWithGenericsShouldNotThrowError() {
assertScript '''
- class Foo {
+ class C {
List<String> list = null // should not throw an error
}
- new Foo()
+ new C()
'''
}
void testSetterInWith() {
assertScript '''
- class Builder {
+ class C {
private int y
- void setFoo(int x) { y = x}
+ void setFoo(int x) { y = x }
int value() { y }
}
- def b = new Builder()
- b.with {
+ def c = new C()
+ c.with {
setFoo(5)
}
- assert b.value() == 5
+ assert c.value() == 5
'''
}
void testSetterInWithUsingPropertyNotation() {
assertScript '''
- class Builder {
+ class C {
private int y
- void setFoo(int x) { y = x}
+ void setFoo(int x) { y = x }
int value() { y }
}
- def b = new Builder()
- b.with {
+ def c = new C()
+ c.with {
foo = 5
}
- assert b.value() == 5
+ assert c.value() == 5
'''
}
void testSetterInWithUsingPropertyNotationAndClosureSharedVariable() {
assertScript '''
- class Builder {
+ class C {
private int y
- void setFoo(int x) { y = x}
+ void setFoo(int x) { y = x }
int value() { y }
}
- def b = new Builder()
+ def c = new C()
def csv = 0
- b.with {
+ c.with {
foo = 5
csv = 10
}
- assert b.value() == 5
+ assert c.value() == 5
assert csv == 10
'''
}
@@ -870,33 +927,29 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
// GROOVY-6489
void testShouldNotThrowUnmatchedGenericsError() {
- assertScript '''public class Foo {
-
- private List<String> names;
-
- public List<String> getNames() {
- return names;
- }
-
- public void setNames(List<String> names) {
- this.names = names;
- }
-}
-
-class FooWorker {
-
- public void doSomething() {
- new Foo().with {
- names = new ArrayList()
- }
- }
-}
-
-new FooWorker().doSomething()'''
+ assertScript '''
+ public class Foo {
+ private List<String> names;
+ public List<String> getNames() {
+ return names;
+ }
+ public void setNames(List<String> names) {
+ this.names = names;
+ }
+ }
+ class FooWorker {
+ public void doSomething() {
+ new Foo().with {
+ names = new ArrayList()
+ }
+ }
+ }
+ new FooWorker().doSomething()
+ '''
}
void testShouldFailWithIncompatibleGenericTypes() {
- shouldFailWithMessages '''\
+ shouldFailWithMessages '''
public class Foo {
private List<String> names;
@@ -932,17 +985,18 @@ new FooWorker().doSomething()'''
}
void testPropertyWithMultipleSetters() {
- assertScript '''import org.codehaus.groovy.ast.expr.BinaryExpression
-import org.codehaus.groovy.ast.expr.BooleanExpression
-import org.codehaus.groovy.ast.stmt.AssertStatement
- class A {
+ assertScript '''
+ import org.codehaus.groovy.ast.expr.*
+ import org.codehaus.groovy.ast.stmt.*
+
+ class C {
private field
void setX(Integer a) {field=a}
void setX(String b) {field=b}
def getX(){field}
}
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
lookup('test1').each { stmt ->
def exp = stmt.expression
assert exp instanceof BinaryExpression
@@ -963,13 +1017,13 @@ import org.codehaus.groovy.ast.stmt.AssertStatement
}
})
void testBody() {
- def a = new A()
+ def c = new C()
test1:
- a.x = 1
- assert a.x==1
+ c.x = 1
+ assert c.x==1
test2:
- a.x = "3"
- assert a.x == "3"
+ c.x = "3"
+ assert c.x == "3"
}
testBody()
'''
@@ -985,12 +1039,9 @@ import org.codehaus.groovy.ast.stmt.AssertStatement
void setX(boolean b) { which = 'boolean' }
}
- void test() {
- def c = new C()
- c.x = 'value'
- assert c.which == 'String'
- }
- test()
+ def c = new C()
+ c.x = 'value'
+ assert c.which == 'String'
'''
}
@@ -1022,33 +1073,30 @@ import org.codehaus.groovy.ast.stmt.AssertStatement
void setX(boolean b) { which = 'boolean' }
}
- void test() {
- def c = new C()
- c.x = 'value'
- assert c.which == 'String'
- }
- test()
+ def c = new C()
+ c.x = 'value'
+ assert c.which == 'String'
'''
}
void testPropertyAssignmentAsExpression() {
assertScript '''
- class Foo {
+ class C {
int x = 2
}
- def f = new Foo()
- def v = f.x = 3
- assert v == 3
+ def c = new C()
+ def x = c.x = 3
+ assert x == 3
'''
}
void testPropertyAssignmentInSubClassAndMultiSetter() {
10.times {
assertScript '''
- class A {
+ class C {
int which
- A() {
+ C() {
contentView = 42L
assert which == 2
}
@@ -1057,7 +1105,7 @@ import org.codehaus.groovy.ast.stmt.AssertStatement
void setContentView(Long value) { which = 2 }
}
- class B extends A {
+ class D extends C {
void m() {
contentView = 42L
assert which == 2
@@ -1066,25 +1114,25 @@ import org.codehaus.groovy.ast.stmt.AssertStatement
}
}
- new B().m()
+ new D().m()
'''
}
}
void testPropertyAssignmentInSubClassAndMultiSetterThroughDelegation() {
10.times {
- assertScript '''\
- class A {
+ assertScript '''
+ class C {
int which
void setContentView(Date value) { which = 1 }
void setContentView(Long value) { which = 2 }
}
- class B extends A {
+ class D extends C {
}
- new B().with {
+ new D().with {
contentView = 42L
assert which == 2
contentView = new Date()
@@ -1169,7 +1217,8 @@ import org.codehaus.groovy.ast.stmt.AssertStatement
Foo foo = new Foo()
foo.bar = new Bar()
- ''', 'Cannot assign value of type Bar to variable of type int'
+ ''',
+ 'Cannot assign value of type Bar to variable of type int'
assertScript '''
class Foo {
@@ -1206,7 +1255,8 @@ import org.codehaus.groovy.ast.stmt.AssertStatement
Foo foo = new Foo(bar: new Bar(x: 1))
Bar bar = foo.bar
- ''', 'Cannot assign value of type int to variable of type Bar'
+ ''',
+ 'Cannot assign value of type int to variable of type Bar'
assertScript '''
class Foo {
@@ -1227,10 +1277,16 @@ import org.codehaus.groovy.ast.stmt.AssertStatement
'''
}
+ //--------------------------------------------------------------------------
+
static interface InterfaceWithField {
String boo = "I don't fancy fields in interfaces"
}
+ static class MapType extends HashMap<String,Object> {
+ def foo = 1
+ }
+
static class BaseClass {
int x
}
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/ArraysAndCollectionsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/ArraysAndCollectionsStaticCompileTest.groovy
index b61bffb579..8e68703f7a 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/ArraysAndCollectionsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/ArraysAndCollectionsStaticCompileTest.groovy
@@ -97,7 +97,7 @@ class ArraysAndCollectionsStaticCompileTest extends ArraysAndCollectionsSTCTest
}
}
- //GROOVY-7442
+ // GROOVY-7442
void testSpreadDotOperatorWithinAssert() {
assertScript '''
def myMethod(String a, String b) {
@@ -108,7 +108,7 @@ class ArraysAndCollectionsStaticCompileTest extends ArraysAndCollectionsSTCTest
'''
}
- //GROOVY-7688
+ // GROOVY-7688
void testSpreadSafeMethodCallReceiversWithSideEffectsShouldNotBeVisitedTwice() {
try {
assertScript '''
@@ -125,27 +125,4 @@ class ArraysAndCollectionsStaticCompileTest extends ArraysAndCollectionsSTCTest
assert astTrees['Foo'][1].count('DefaultGroovyMethods.toList') == 1
}
}
-
- //GROOVY-8074
- void testMapSubclassPropertyStyleAccess() {
- assertScript '''
- class MyMap extends LinkedHashMap {
- def foo = 1
- }
-
- def map = new MyMap()
- map.put('foo', 42)
- assert map.foo == 42
- '''
- }
-
- @Override
- void testForInLoop() {
- try {
- super.testForInLoop()
- } finally {
- println astTrees
- }
- }
}
-
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
index af1dc40472..664b08ebf6 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
@@ -49,7 +49,6 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
def bar = createBar()
bar.foo
}
-
Bar createBar() { new Bar() }
}
class Bar {
@@ -74,7 +73,7 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseDirectWriteFieldAccess() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
protected int x
@@ -83,22 +82,22 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- class B extends A {
+ class D extends C {
void directAccess() {
this.@x = 2
}
}
- B b = new B()
- b.directAccess()
- assert b.isSetterCalled() == false
- assert b.x == 2
+ D d = new D()
+ d.directAccess()
+ assert d.isSetterCalled() == false
+ assert d.x == 2
'''
- assert astTrees['B'][1].contains('PUTFIELD A.x')
+ assert astTrees['D'][1].contains('PUTFIELD C.x')
}
void testUseDirectWriteStaticFieldAccess() {
assertScript '''
- class A {
+ class C {
static boolean setterCalled
static protected int x
@@ -107,21 +106,21 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- class B extends A {
+ class D extends C {
static void directAccess() {
this.@x = 2
}
}
- B.directAccess()
- assert B.isSetterCalled() == false
- assert B.x == 2
+ D.directAccess()
+ assert D.isSetterCalled() == false
+ assert D.x == 2
'''
- assert astTrees['B'][1].contains('PUTSTATIC A.x')
+ assert astTrees['D'][1].contains('PUTSTATIC C.x')
}
void testUseSetterFieldAccess() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
protected int x
@@ -130,135 +129,133 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- class B extends A {
+ class D extends C {
void setterAccess() {
this.x = 2
}
}
- B b = new B()
- b.setterAccess()
- assert b.isSetterCalled() == true
- assert b.x == 2
+ D d = new D()
+ d.setterAccess()
+ assert d.isSetterCalled() == true
+ assert d.x == 2
'''
- assert astTrees['B'][1].contains('INVOKEVIRTUAL B.setX')
+ assert astTrees['D'][1].contains('INVOKEVIRTUAL D.setX')
}
void testUseDirectWriteFieldAccessFromOutsideClass() {
assertScript '''
- class A {
+ class C {
public int x
}
- class B {
- void directAccess(A a) {
- a.@x = 2
+ class D {
+ void directAccess(C c) {
+ c.@x = 2
}
}
- B b = new B()
- A a = new A()
- b.directAccess(a)
- assert a.x == 2
+ D d = new D()
+ C c = new C()
+ d.directAccess(c)
+ assert c.x == 2
'''
- assert astTrees['B'][1].contains('PUTFIELD A.x')
+ assert astTrees['D'][1].contains('PUTFIELD C.x')
}
void testUseDirectWriteFieldAccessPrivateWithRuntimeClassBeingDifferent() {
assertScript '''
- class A {
+ class C {
private int x
- public A(int x) {
+ public C(int x) {
this.@x = x
}
- public boolean sameAs(A a) {
- return this.@x == a.@x
+ public boolean sameAs(C c) {
+ return this.@x == c.@x
}
}
- class B extends A {
- // B.x visible in B A.x in A, but reflection depending on the runtime type
- // would see B.x in A#sameAs and not A.x
+ class D extends C {
+ // D.x visible in D C.x in C, but reflection depending on the runtime type would see C.x in C#sameAs and not C.x
private int x
- public B(int x) {
+ public D(int x) {
super(x)
this.@x = x + 50
}
}
- B b = new B(1)
- A a = new A(1)
- assert b.sameAs(a)
+ D d = new D(1)
+ C c = new C(1)
+ assert d.sameAs(c)
'''
// same with property style access:
assertScript '''
- class A {
+ class C {
private int x
- public A(int x) {
+ public C(int x) {
this.x = x
}
- public boolean sameAs(A a) {
- return this.x == a.x
+ public boolean sameAs(C c) {
+ return this.x == c.x
}
}
- class B extends A {
- // B.x visible in B A.x in A, but reflection depending on the runtime type
- // would see B.x in A#sameAs and not A.x
+ class D extends C {
+ // D.x visible in D C.x in C, but reflection depending on the runtime type would see D.x in C#sameAs and not C.x
private int x
- public B(int x) {
+ public D(int x) {
super(x)
this.x = x + 50
}
}
- B b = new B(1)
- A a = new A(1)
- assert b.sameAs(a)
+ D d = new D(1)
+ C c = new C(1)
+ assert d.sameAs(c)
'''
}
void testReadFieldFromSameClass() {
['', 'public', 'private', 'protected', '@groovy.transform.PackageScope'].each { mod ->
assertScript """
- class A {
+ class C {
$mod int x
int m() {
x
}
}
- assert new A().m() == 0
+ assert new C().m() == 0
"""
- def a = astTrees['A'][1]
- assert (a =~ 'GETFIELD A.x').collect().size() == mod.empty ? 2 : 1
+ def a = astTrees['C'][1]
+ assert (a =~ 'GETFIELD C.x').collect().size() == mod.empty ? 2 : 1
}
}
void testWriteFieldFromSameClass() {
['', 'public', 'private', 'protected', '@groovy.transform.PackageScope'].each { mod ->
assertScript """
- class A {
+ class C {
$mod int x
int m() {
x = 5
x
}
}
- new A().m() == 5
+ new C().m() == 5
"""
- def a = astTrees['A'][1]
- assert (a =~ 'PUTFIELD A.x').collect().size() == mod.empty ? 2 : 1
+ def a = astTrees['C'][1]
+ assert (a =~ 'PUTFIELD C.x').collect().size() == mod.empty ? 2 : 1
}
}
void testReadFieldFromSuperClass() {
['public', 'protected', '@groovy.transform.PackageScope'].each { mod ->
assertScript """
- class A {
+ class C {
$mod int x
}
- class B extends A {
+ class D extends C {
int m() {
x
}
}
- assert new B().m() == 0
+ assert new D().m() == 0
"""
- def b = astTrees['B'][1]
- assert b.contains('GETFIELD A.x')
+ def b = astTrees['D'][1]
+ assert b.contains('GETFIELD C.x')
}
}
@@ -266,21 +263,21 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testReadFieldFromSuperClass2() {
assertScript '''
package p
- class A {
+ class C {
protected int x
}
- new p.A()
+ new p.C()
'''
assertScript '''
- class B extends p.A {
+ class D extends p.C {
int m() {
x
}
}
- assert new B().m() == 0
+ assert new D().m() == 0
'''
- def b = astTrees['B'][1]
- assert b.contains('GETFIELD p/A.x')
+ def b = astTrees['D'][1]
+ assert b.contains('GETFIELD p/C.x')
assert !b.contains('INVOKEINTERFACE groovy/lang/GroovyObject.getProperty')
}
@@ -288,47 +285,47 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testReadFieldFromSuperClass3() {
assertScript '''
package p
- class A {
+ class C {
protected static int x
}
- new p.A()
+ new p.C()
'''
assertScript '''
- class B extends p.A {
+ class D extends p.C {
static int m() {
x
}
}
- assert B.m() == 0
+ assert D.m() == 0
'''
- def b = astTrees['B'][1]
- assert b.contains('GETSTATIC B.x')
+ def b = astTrees['D'][1]
+ assert b.contains('GETSTATIC D.x')
assert !b.contains('INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.getGroovyObjectProperty')
}
void testReadPropertyFromSuperClass() {
['', 'public', 'private', 'protected', '@groovy.transform.PackageScope'].each { mod ->
assertScript """
- class A {
+ class C {
$mod int x
int getX() { x }
}
- class B extends A {
+ class D extends C {
int m() {
x
}
}
- assert new B().m() == 0
+ assert new D().m() == 0
"""
- def b = astTrees['B'][1]
- assert !b.contains('GETFIELD A.x') : 'no GETFIELD in B'
- assert b.contains('INVOKEVIRTUAL B.getX') : 'getX() in B'
+ def b = astTrees['D'][1]
+ assert !b.contains('GETFIELD C.x') : 'no GETFIELD in D'
+ assert b.contains('INVOKEVIRTUAL D.getX') : 'getX() in D'
}
}
void testUseDirectReadFieldAccess() {
assertScript '''
- class A {
+ class C {
boolean getterCalled
protected int x
@@ -337,22 +334,22 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x
}
}
- class B extends A {
+ class D extends C {
void m() {
this.@x
}
}
- B b = new B()
- b.m()
- assert b.isGetterCalled() == false
+ D d = new D()
+ d.m()
+ assert d.isGetterCalled() == false
'''
- def b = astTrees['B'][1]
- assert b.contains('GETFIELD A.x')
+ def b = astTrees['D'][1]
+ assert b.contains('GETFIELD C.x')
}
void testUseAttributeExternal() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
public int x
@@ -361,16 +358,16 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- A a = new A()
- a.@x = 100
- assert a.x == 100
- assert a.isSetterCalled() == false
+ C c = new C()
+ c.@x = 100
+ assert c.x == 100
+ assert c.isSetterCalled() == false
'''
}
void testUseAttributeExternalSafe() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
public int x
@@ -379,16 +376,16 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- A a = new A()
- a?.@x = 100
- assert a.x == 100
- assert a.isSetterCalled() == false
+ C c = new C()
+ c?.@x = 100
+ assert c.x == 100
+ assert c.isSetterCalled() == false
'''
}
void testUseAttributeExternalSafeWithNull() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
public int x
@@ -397,14 +394,14 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- A a = null
- a?.@x = 100
+ C c = null
+ c?.@x = 100
'''
}
void testUseSetterExternal() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
public int x
@@ -413,16 +410,16 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- A a = new A()
- a.x = 100
- assert a.x == 100
- assert a.isSetterCalled() == true
+ C c = new C()
+ c.x = 100
+ assert c.x == 100
+ assert c.isSetterCalled() == true
'''
}
void testUseAttributeExternalSpread() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
public int x
@@ -431,16 +428,16 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- List<A> a = [new A(), new A()]
- a*.@x = 100
- println a[0].x == 100
- println a[0].isSetterCalled() == false
+ List<C> list = [new C(), new C()]
+ list*.@x = 100
+ assert list[0].x == 100
+ assert list[0].isSetterCalled() == false
'''
}
void testUseAttributeExternalSpreadSafeWithNull() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
public int x
@@ -449,17 +446,17 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- List<A> a = [new A(), null]
- a*.@x = 100
- assert a[0].x == 100
- assert a[0].isSetterCalled() == false
- assert a[1] == null
+ List<C> list = [new C(), null]
+ list*.@x = 100
+ assert list[0].x == 100
+ assert list[0].isSetterCalled() == false
+ assert list[1] == null
'''
}
void testUseAttributeExternalSpreadUsingSetter() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
public int x
@@ -468,16 +465,16 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- List<A> a = [new A(), new A()]
- a*.x = 100
- assert a[0].x == 100
- assert a[0].isSetterCalled() == true
+ List<C> list = [new C(), new C()]
+ list*.x = 100
+ assert list[0].x == 100
+ assert list[0].isSetterCalled() == true
'''
}
void testUseAttributeExternalSpreadSafeWithNullUsingSetter() {
assertScript '''
- class A {
+ class C {
boolean setterCalled
public int x
@@ -486,11 +483,11 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
x = a
}
}
- List<A> a = [new A(), null]
- a*.x = 100
- assert a[0].x == 100
- assert a[0].isSetterCalled() == true
- assert a[1] == null
+ List<C> list = [new C(), null]
+ list*.x = 100
+ assert list[0].x == 100
+ assert list[0].isSetterCalled() == true
+ assert list[1] == null
'''
}
@@ -529,19 +526,18 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testPropertyWithMultipleSetters() {
// we need to override the test because the AST is going to be changed
assertScript '''
- import org.codehaus.groovy.ast.expr.BinaryExpression
- import org.codehaus.groovy.ast.expr.BooleanExpression
- import org.codehaus.groovy.ast.stmt.AssertStatement
+ import org.codehaus.groovy.ast.expr.*
+ import org.codehaus.groovy.ast.stmt.*
import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
- class A {
+ class C {
private field
void setX(Integer a) {field=a}
void setX(String b) {field=b}
def getX(){field}
}
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
lookup('test1').each { stmt ->
def exp = stmt.expression
assert exp instanceof ListOfExpressionsExpression
@@ -551,38 +547,35 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
assert exp instanceof ListOfExpressionsExpression
}
})
- void testBody() {
- def a = new A()
+ void test() {
+ def c = new C()
test1:
- a.x = 1
- assert a.x==1
+ c.x = 1
+ assert c.x==1
test2:
- a.x = "3"
- assert a.x == "3"
+ c.x = "3"
+ assert c.x == "3"
}
- testBody()
+ test()
'''
}
void testCallSetterAsPropertyWithinFinallyBlockShouldNotThrowVerifyError() {
try {
assertScript '''
- class Multi {
+ class C {
void setOut(int a) {}
}
- void foo() {
- def m = new Multi()
- try {
- } finally {
- m.out = 1
- }
+ def c = new C()
+ try {
+ } finally {
+ c.out = 1
}
- foo()
'''
} finally {
assert astTrees.values().any {
- it.toString().contains 'INVOKEVIRTUAL Multi.setOut (I)V'
+ it.toString().contains 'INVOKEVIRTUAL C.setOut (I)V'
}
}
}
@@ -590,26 +583,23 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testCallMultiSetterAsPropertyWithinFinallyBlockShouldNotThrowVerifyError() {
try {
assertScript '''
- class Multi {
+ class C {
void setOut(int a) {}
void setOut(String a) {}
}
- void foo() {
- def m = new Multi()
- try {
- } finally {
- m.out = 1
- m.out = 'foo'
- }
+ def c = new C()
+ try {
+ } finally {
+ c.out = 1
+ c.out = 'foo'
}
- foo()
'''
} finally {
assert astTrees.values().any {
def code = it.toString()
- code.contains('INVOKEVIRTUAL Multi.setOut (I)V') &&
- code.contains('INVOKEVIRTUAL Multi.setOut (Ljava/lang/String;)V')
+ code.contains('INVOKEVIRTUAL C.setOut (I)V') &&
+ code.contains('INVOKEVIRTUAL C.setOut (Ljava/lang/String;)V')
}
}
}
@@ -617,15 +607,15 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
// GROOVY-7698
void testSafePropertyStyleSetterCalls() {
assertScript '''
- class Foo {
+ class C {
private String id
void setId(String id) {
this.id = id
}
}
- Foo foo = null
- foo?.id = 'new'
+ C c = null
+ c?.id = 'new'
'''
}
@@ -719,25 +709,25 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testPrivateFieldMutationInAICUsesBridgeMethod() {
try {
assertScript '''
- class A {
+ class C {
private int x
void test() {
- def aic = new Runnable() { void run() { A.this.x = 666 } }
+ def aic = new Runnable() { void run() { C.this.x = 666 } }
aic.run()
assert x == 666
}
}
- new A().test()
+ new C().test()
'''
} finally {
- assert astTrees['A$1'][1].contains('INVOKESTATIC A.pfaccess$00 (LA;I)I')
+ assert astTrees['C$1'][1].contains('INVOKESTATIC C.pfaccess$00 (LC;I)I')
}
}
void testImplicitPrivateFieldMutationInAICUsesBridgeMethod() {
try {
assertScript '''
- class A {
+ class C {
private int x
void test() {
def aic = new Runnable() { void run() { x = 666 } }
@@ -745,17 +735,17 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
assert x == 666
}
}
- new A().test()
+ new C().test()
'''
} finally {
- assert astTrees['A$1'][1].contains('INVOKESTATIC A.pfaccess$00 (LA;I)I')
+ assert astTrees['C$1'][1].contains('INVOKESTATIC C.pfaccess$00 (LC;I)I')
}
}
void testPrivateStaticFieldMutationInAICUsesBridgeMethod() {
try {
assertScript '''
- class A {
+ class C {
private static int x
void test() {
def aic = new Runnable() { void run() { x = 666 } }
@@ -763,17 +753,17 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
assert x == 666
}
}
- new A().test()
+ new C().test()
'''
} finally {
- assert astTrees['A$1'][1].contains('INVOKESTATIC A.pfaccess$00 (LA;I)I')
+ assert astTrees['C$1'][1].contains('INVOKESTATIC C.pfaccess$00 (LC;I)I')
}
}
void testMultiplePrivateFieldMutatorBridgeMethods() {
try {
assertScript '''
- class A {
+ class C {
private int x
private String y
Closure mutate = { x = 1; y = 'abc' }
@@ -784,22 +774,22 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
assert y == 'abc'
}
}
- new A().test()
+ new C().test()
'''
} finally {
- assert astTrees['A$_closure1'][1].contains('INVOKESTATIC A.pfaccess$00 (LA;I)I')
- assert astTrees['A$_closure1'][1].contains('INVOKESTATIC A.pfaccess$01 (LA;Ljava/lang/String;)Ljava/lang/String;')
+ assert astTrees['C$_closure1'][1].contains('INVOKESTATIC C.pfaccess$00 (LC;I)I')
+ assert astTrees['C$_closure1'][1].contains('INVOKESTATIC C.pfaccess$01 (LC;Ljava/lang/String;)Ljava/lang/String;')
}
}
void testPrivateFieldBridgeMethodsAreGeneratedAsNecessary() {
try {
assertScript '''
- class A {
+ class C {
private int accessed = 0
private String mutated
private String accessedAndMutated = ''
- Closure c = {
+ Closure cl = {
println accessed
mutated = 'abc'
println accessedAndMutated
@@ -807,88 +797,46 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
}
void test() {
- c()
+ cl()
assert mutated == 'abc'
assert accessedAndMutated == 'def'
}
}
- new A().test()
+ new C().test()
'''
} finally {
- def dump = astTrees['A'][1]
+ def dump = astTrees['C'][1]
assert dump.contains('pfaccess$0') // accessor bridge method for 'accessed'
assert !dump.contains('pfaccess$00') // no mutator bridge method for 'accessed'
assert dump.contains('pfaccess$01') // mutator bridge method for 'mutated'
assert dump.contains('pfaccess$1') // accessor bridge method for 'mutated' -- GROOVY-9385
assert dump.contains('pfaccess$2') // accessor bridge method for 'accessedAndMutated'
assert dump.contains('pfaccess$02') // mutator bridge method for 'accessedAndMutated'
- dump = astTrees['A$_closure1'][1]
- assert dump.contains('INVOKESTATIC A.pfaccess$2 (LA;)Ljava/lang/String;')
- assert dump.contains('INVOKESTATIC A.pfaccess$02 (LA;Ljava/lang/String;)Ljava/lang/String;')
+ dump = astTrees['C$_closure1'][1]
+ assert dump.contains('INVOKESTATIC C.pfaccess$2 (LC;)Ljava/lang/String;')
+ assert dump.contains('INVOKESTATIC C.pfaccess$02 (LC;Ljava/lang/String;)Ljava/lang/String;')
}
}
// GROOVY-8369
void testPropertyAccessOnEnumClass() {
assertScript '''
- enum Foo {}
-
- def test() {
- assert Foo.getModifiers() == Foo.modifiers
- }
- test()
+ enum E { }
+ assert E.getModifiers() == E.modifiers
'''
}
// GROOVY-8753
void testPrivateFieldWithPublicGetter() {
assertScript '''
- class A {
+ class C {
private List<String> fooNames = []
- public A(Collection<String> names) {
+ public C(Collection<String> names) {
names.each { fooNames << it }
}
public List<String> getFooNames() { fooNames }
}
- assert new A(['foo1', 'foo2']).fooNames.size() == 2
- '''
- }
-
- // GROOVY-9683
- void testPrivateFieldAccessInClosure3() {
- assertScript '''
- class A {
- private static X = 'xxx'
- void test() {
- [:].with {
- assert X == 'xxx'
- }
- }
- }
- new A().test()
- '''
- }
-
- // GROOVY-9695
- void testPrivateFieldAccessInClosure4() {
- assertScript '''
- class A {
- private static final X = 'xxx'
- void test() {
- Map m = [:]
- def c = { ->
- assert X == 'xxx'
- m[X] = 123
- }
- c()
- assert m == [xxx:123]
- }
- }
- new A().test()
-
- class B extends A {
- }
- new B().test()
+ assert new C(['foo1', 'foo2']).fooNames.size() == 2
'''
}
}