This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY-11753 in repository https://gitbox.apache.org/repos/asf/groovy.git
commit fd922511af629b501934f9d42e7ff5e8e823aa7b Author: Eric Milles <eric.mil...@thomsonreuters.com> AuthorDate: Fri Sep 12 11:33:26 2025 -0500 GROOVY-10687, GROOVY-11753: reorder classes given inner class closure --- .../groovy/classgen/ClassCompletionVerifier.java | 6 - .../codehaus/groovy/control/CompilationUnit.java | 37 +- src/test/groovy/groovy/PropertyTest.groovy | 553 ++++++++++++--------- .../groovy/classgen/asm/NestHostTests.groovy | 2 +- 4 files changed, 344 insertions(+), 254 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java b/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java index 5cf32d125e..c470489b99 100644 --- a/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java +++ b/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java @@ -217,12 +217,6 @@ public class ClassCompletionVerifier extends ClassCodeVisitorSupport { if (node.isAbstract()) return; for (MethodNode method : node.getAbstractMethods()) { MethodNode sameArgsMethod = node.getMethod(method.getName(), method.getParameters()); - if (sameArgsMethod == null) { - sameArgsMethod = ClassHelper.GROOVY_OBJECT_TYPE.getMethod(method.getName(), method.getParameters()); - if (sameArgsMethod != null && !sameArgsMethod.isAbstract() && sameArgsMethod.getReturnType().equals(method.getReturnType())) { - continue; - } - } String what; ASTNode where = node; if (sameArgsMethod == null || sameArgsMethod.getReturnType().equals(method.getReturnType())) { diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java index 43704358d1..471c79eb05 100644 --- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java +++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java @@ -23,12 +23,14 @@ import groovy.lang.GroovyRuntimeException; import groovy.transform.CompilationUnitAware; import org.codehaus.groovy.GroovyBugError; import org.codehaus.groovy.ast.AnnotationNode; +import org.codehaus.groovy.ast.ClassCodeVisitorSupport; import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.CompileUnit; import org.codehaus.groovy.ast.GroovyClassVisitor; import org.codehaus.groovy.ast.InnerClassNode; import org.codehaus.groovy.ast.ModuleNode; +import org.codehaus.groovy.ast.expr.ClosureExpression; import org.codehaus.groovy.classgen.AsmClassGenerator; import org.codehaus.groovy.classgen.ClassCompletionVerifier; import org.codehaus.groovy.classgen.EnumCompletionVisitor; @@ -1023,7 +1025,7 @@ public class CompilationUnit extends ProcessingUnit { } else { count = getSuperClassCount(cn) + 1000; } - if (cn.getOuterClass() == null && cn.getInnerClasses().hasNext()) { + if (cn.getOuterClass() == null && hasInnerClassWithClosure(cn)) { count += 2000; // GROOVY-10687: nest host must follow members (with closures) } return count; @@ -1033,6 +1035,39 @@ public class CompilationUnit extends ProcessingUnit { return classes; } + private static boolean hasInnerClassWithClosure(final ClassNode cn) { + for (var it = cn.getInnerClasses(); it.hasNext(); ) { + class ClosureFound extends RuntimeException { + private static final long serialVersionUID = 1; + @Override public Throwable fillInStackTrace() { + return this; + } + } + + var visitor = new ClassCodeVisitorSupport() { + @Override + public SourceUnit getSourceUnit() { + return cn.getModule().getContext(); + } + @Override + public void visitClosureExpression(final ClosureExpression ce) { + throw new ClosureFound(); + } + }; + + ClassNode innerClass = it.next(); + try { + visitor.visitClass(innerClass); + } catch (ClosureFound done) { + return true; + } + if (hasInnerClassWithClosure(innerClass)) { + return true; + } + } + return false; + } + private void changeBugText(final GroovyBugError e, final SourceUnit context) { e.setBugText("exception in phase '" + getPhaseDescription() + "' in source unit '" + (context != null ? context.getName() : "?") + "' " + e.getBugText()); } diff --git a/src/test/groovy/groovy/PropertyTest.groovy b/src/test/groovy/groovy/PropertyTest.groovy index fe7b7c29ba..30f6653370 100644 --- a/src/test/groovy/groovy/PropertyTest.groovy +++ b/src/test/groovy/groovy/PropertyTest.groovy @@ -18,13 +18,17 @@ */ package groovy -import groovy.test.GroovyTestCase +import org.junit.jupiter.api.Test + +import static groovy.test.GroovyAssert.assertScript +import static groovy.test.GroovyAssert.shouldFail /** * Tests the use of properties in Groovy */ -final class PropertyTest extends GroovyTestCase { +final class PropertyTest { + @Test void testNormalPropertyGettersAndSetters() { def foo = new Foo() def value = foo.getMetaClass() @@ -46,12 +50,14 @@ final class PropertyTest extends GroovyTestCase { } // GROOVY-1809 + @Test void testClassWithPrivateFieldAndGetter() { if (HeadlessTestSupport.headless) return assert java.awt.Font.getName() == 'java.awt.Font' assert java.awt.Font.name == 'java.awt.Font' } + @Test void testOverloadedGetter() { def foo = new Foo() assert foo.getCount() == 1 @@ -61,6 +67,7 @@ final class PropertyTest extends GroovyTestCase { assert foo.getCount() == 7 } + @Test void testNoSetterAvailableOnPrivateProperty() { def foo = new Foo() @@ -69,6 +76,7 @@ final class PropertyTest extends GroovyTestCase { shouldFail { foo.setBlah(4) } } + @Test void testCannotSeePrivateProperties() { def foo = new Foo() @@ -79,6 +87,7 @@ final class PropertyTest extends GroovyTestCase { shouldFail { foo.getQ() } } + @Test void testConstructorWithNamedProperties() { def foo = new Foo(name: 'Gromit', location: 'Moon') @@ -86,11 +95,13 @@ final class PropertyTest extends GroovyTestCase { assert foo.location == 'Moon' } + @Test void testToString() { def foo = new Foo(name: 'Gromit', location: 'Moon') assert foo.toString().endsWith('name: Gromit location: Moon') } + @Test void testArrayLengthProperty() { // create two arrays, since all use the same MetaArrayLengthProperty object - // make sure it can work for all types and sizes @@ -111,46 +122,43 @@ final class PropertyTest extends GroovyTestCase { shouldFail { i.length = 6 } } + @Test void testGstringAssignment() { def foo = new Foo() foo.body = "${foo.name}" assert foo.body == "James" } + @Test void testFinalProperty() { - def shell = new GroovyShell(); - assertScript """ - class A { - final foo = 1 - } - A.class.declaredMethods.each { - assert it.name!="setFoo" - - } - assert new A().foo==1 - """ - shouldFail { - shell.execute """ - class A { - final foo = 1 - } - new A().foo = 2 - """ - } + assertScript ''' + class A { + final foo = 1 + } + A.class.declaredMethods.each { + assert it.name!="setFoo" + } + assert new A().foo==1 + ''' + shouldFail ''' + class A { + final foo = 1 + } + new A().foo = 2 + ''' } + @Test void testFinalField() { - def shell = new GroovyShell(); - shouldFail { - shell.execute """ - class A { - public final foo = 1 - } - new A().foo = 2 - """ - } + shouldFail ''' + class A { + public final foo = 1 + } + new A().foo = 2 + ''' } + @Test void testFinalPropertyWithInheritance() { def child = new Child() assert child.finalProperty == 1 @@ -158,11 +166,13 @@ final class PropertyTest extends GroovyTestCase { assert child.finalProperty == 1 } + @Test void testBaseProperties() { assert new Child().field == 'foobar' } // GROOVY-1736 + @Test void testGetSuperProperties() { def c = new Child() assert c.thing == 'bar thing' @@ -173,6 +183,7 @@ final class PropertyTest extends GroovyTestCase { } // GROOVY-1736, GROOVY-9609 + @Test void testGetSuperProperties2() { for (vis in ['', 'public', 'protected', '@groovy.transform.PackageScope']) { assertScript """ @@ -192,6 +203,7 @@ final class PropertyTest extends GroovyTestCase { } // GROOVY-6097 + @Test void testGetSuperProperties3() { for (vis in ['', 'public', 'protected', '@groovy.transform.PackageScope']) { assertScript """ @@ -209,6 +221,7 @@ final class PropertyTest extends GroovyTestCase { } } + @Test void testSetSuperProperties() { def c = new Child() assert c.superField == 'bar' @@ -222,12 +235,14 @@ final class PropertyTest extends GroovyTestCase { assert c.superthing() == 'bar1bar thing' } + @Test void testOverwritingNormalProperty() { def c = new Child() assert c.normalProperty == 2 } - //GROOVY-2244 + // GROOVY-2244 + @Test void testWriteOnlyBeanProperty() { def bean = new Child() @@ -239,11 +254,12 @@ final class PropertyTest extends GroovyTestCase { // attempt to read it shouldFail(MissingPropertyException) { - fail("We shouldn't be able to read bean.superThing, but we can: '$bean.superThing'") + bean.superThing } } // GROOVY-10456 + @Test void testEmptyPropertyAccessForObject() { assertScript ''' import static groovy.test.GroovyAssert.shouldFail @@ -255,6 +271,7 @@ final class PropertyTest extends GroovyTestCase { ''' } + @Test void testPrivatePropertyThroughSubclass() { assertScript ''' class A { @@ -268,6 +285,7 @@ final class PropertyTest extends GroovyTestCase { ''' } + @Test void testPropertyWithMultipleSetters() { assertScript ''' class A { @@ -284,6 +302,30 @@ final class PropertyTest extends GroovyTestCase { ''' } + // GROOVY-11753 + @Test + void testPropertyOverridesGetterAndSetter() { + assertScript ''' + interface A { + String getFoo() + } + interface B { + void setFoo(String s) + } + class C implements A,B { + class NestMate { } + String foo + } + class D extends C { + } + + def pogo = new D() + pogo.setFoo("") + assert pogo.getFoo().isEmpty() + ''' + } + + @Test void testPropertyWithOverrideGetterAndSetter() { assertScript ''' abstract class Base { @@ -309,23 +351,25 @@ final class PropertyTest extends GroovyTestCase { ''' } + @Test void testOverrideMultiSetterThroughMetaClass() { assertScript ''' - class A { - private String field - void setConstraints(Closure cl) {} - void setConstraints(String s) {} - String getField() { field } - } + class A { + private String field + void setConstraints(Closure cl) {} + void setConstraints(String s) {} + String getField() { field } + } - A.metaClass.setConstraints = { delegate.field = it+it } - def a = new A() - a.constraints = '100' - assert a.field == '100100' + A.metaClass.setConstraints = { delegate.field = it+it } + def a = new A() + a.constraints = '100' + assert a.field == '100100' ''' } // GROOVY-9618 + @Test void testJavaBeanNamingForPropertyAccess() { assertScript ''' class A { @@ -359,58 +403,128 @@ final class PropertyTest extends GroovyTestCase { } // GROOVY-9618 + @Test void testJavaBeanNamingForPropertyAccessCS() { assertScript ''' - class A { - String getProp() { 'Prop' } - String getSomeProp() { 'SomeProp' } - String getX() { 'X' } - String getDB() { 'DB' } - String getXML() { 'XML' } - String getaProp() { 'aProp' } - String getAProp() { 'AProp' } - String getpNAME() { 'pNAME' } - } - class B { - @groovy.transform.CompileStatic - def method() { - new A().with { - assert prop == 'Prop' - assert Prop == 'Prop' - assert x == 'X' - assert X == 'X' - assert someProp == 'SomeProp' - assert SomeProp == 'SomeProp' - assert DB == 'DB' - assert XML == 'XML' - assert AProp == 'AProp' - assert aProp == 'aProp' - assert pNAME == 'pNAME' + class A { + String getProp() { 'Prop' } + String getSomeProp() { 'SomeProp' } + String getX() { 'X' } + String getDB() { 'DB' } + String getXML() { 'XML' } + String getaProp() { 'aProp' } + String getAProp() { 'AProp' } + String getpNAME() { 'pNAME' } + } + class B { + @groovy.transform.CompileStatic + def method() { + new A().with { + assert prop == 'Prop' + assert Prop == 'Prop' + assert x == 'X' + assert X == 'X' + assert someProp == 'SomeProp' + assert SomeProp == 'SomeProp' + assert DB == 'DB' + assert XML == 'XML' + assert AProp == 'AProp' + assert aProp == 'aProp' + assert pNAME == 'pNAME' + } } } - } - new B().method() + new B().method() ''' } // GROOVY-9618 + @Test void testJavaBeanNamingForStaticPropertyAccess() { assertScript ''' - class A { - private static String X = 'fieldX' - private static String Prop = 'fieldProp' - private static String DB = 'fieldDB' - private static String XML = 'fieldXML' - static String getProp() { 'Prop' } - static String getSomeProp() { 'SomeProp' } - static String getX() { 'X' } - static String getDB() { 'DB' } - static String getXML() { 'XML' } - static String getaProp() { 'aProp' } - static String getAProp() { 'AProp' } - static String getpNAME() { 'pNAME' } - } - A.with { + class A { + private static String X = 'fieldX' + private static String Prop = 'fieldProp' + private static String DB = 'fieldDB' + private static String XML = 'fieldXML' + static String getProp() { 'Prop' } + static String getSomeProp() { 'SomeProp' } + static String getX() { 'X' } + static String getDB() { 'DB' } + static String getXML() { 'XML' } + static String getaProp() { 'aProp' } + static String getAProp() { 'AProp' } + static String getpNAME() { 'pNAME' } + } + A.with { + assert prop == 'Prop' + assert Prop == 'Prop' + assert x == 'X' + assert X == 'X' + assert someProp == 'SomeProp' + assert SomeProp == 'SomeProp' + assert DB == 'DB' + assert XML == 'XML' + assert AProp == 'AProp' + assert aProp == 'aProp' + assert pNAME == 'pNAME' + } + ''' + } + + // GROOVY-9618 + @Test + void testJavaBeanNamingForStaticPropertyAccessCS() { + assertScript ''' + class A { + static String getProp() { 'Prop' } + static String getSomeProp() { 'SomeProp' } + static String getX() { 'X' } + static String getDB() { 'DB' } + static String getXML() { 'XML' } + static String getaProp() { 'aProp' } + static String getAProp() { 'AProp' } + static String getpNAME() { 'pNAME' } + } + class B { + @groovy.transform.CompileStatic + static method() { + A.with { + assert prop == 'Prop' + assert Prop == 'Prop' + assert x == 'X' // TODO fix CCE + assert X == 'X' // TODO fix CCE + assert someProp == 'SomeProp' + assert SomeProp == 'SomeProp' + assert DB == 'DB' + assert XML == 'XML' + assert AProp == 'AProp' + assert aProp == 'aProp' + assert pNAME == 'pNAME' + } + } + } + B.method() + ''' + } + + // GROOVY-9618 + @Test + void testJavaBeanNamingForPropertyStaticImport() { + assertScript ''' + class A { + static String getProp() { 'Prop' } + static String getSomeProp() { 'SomeProp' } + static String getX() { 'X' } + static String getDB() { 'DB' } + static String getXML() { 'XML' } + static String getaProp() { 'aProp' } + static String getAProp() { 'AProp' } + static String getpNAME() { 'pNAME' } + } + + import static A.* + assert prop == 'Prop' assert Prop == 'Prop' assert x == 'X' @@ -422,31 +536,33 @@ final class PropertyTest extends GroovyTestCase { assert AProp == 'AProp' assert aProp == 'aProp' assert pNAME == 'pNAME' - } ''' } // GROOVY-9618 - void testJavaBeanNamingForStaticPropertyAccessCS() { + @Test + void testJavaBeanNamingForPropertyStaticImportCS() { assertScript ''' - class A { - static String getProp() { 'Prop' } - static String getSomeProp() { 'SomeProp' } - static String getX() { 'X' } - static String getDB() { 'DB' } - static String getXML() { 'XML' } - static String getaProp() { 'aProp' } - static String getAProp() { 'AProp' } - static String getpNAME() { 'pNAME' } - } - class B { - @groovy.transform.CompileStatic - static method() { - A.with { + class A { + static String getProp() { 'Prop' } + static String getSomeProp() { 'SomeProp' } + static String getX() { 'X' } + static String getDB() { 'DB' } + static String getXML() { 'XML' } + static String getaProp() { 'aProp' } + static String getAProp() { 'AProp' } + static String getpNAME() { 'pNAME' } + } + + import static A.* + + class B { + @groovy.transform.CompileStatic + def method() { assert prop == 'Prop' assert Prop == 'Prop' - assert x == 'X' // TODO fix CCE - assert X == 'X' // TODO fix CCE + assert x == 'X' + assert X == 'X' assert someProp == 'SomeProp' assert SomeProp == 'SomeProp' assert DB == 'DB' @@ -456,111 +572,46 @@ final class PropertyTest extends GroovyTestCase { assert pNAME == 'pNAME' } } - } - B.method() - ''' - } - - // GROOVY-9618 - void testJavaBeanNamingForPropertyStaticImport() { - assertScript ''' - class A { - static String getProp() { 'Prop' } - static String getSomeProp() { 'SomeProp' } - static String getX() { 'X' } - static String getDB() { 'DB' } - static String getXML() { 'XML' } - static String getaProp() { 'aProp' } - static String getAProp() { 'AProp' } - static String getpNAME() { 'pNAME' } - } - - import static A.* - - assert prop == 'Prop' - assert Prop == 'Prop' - assert x == 'X' - assert X == 'X' - assert someProp == 'SomeProp' - assert SomeProp == 'SomeProp' - assert DB == 'DB' - assert XML == 'XML' - assert AProp == 'AProp' - assert aProp == 'aProp' - assert pNAME == 'pNAME' - ''' - } - - // GROOVY-9618 - void testJavaBeanNamingForPropertyStaticImportCS() { - assertScript ''' - class A { - static String getProp() { 'Prop' } - static String getSomeProp() { 'SomeProp' } - static String getX() { 'X' } - static String getDB() { 'DB' } - static String getXML() { 'XML' } - static String getaProp() { 'aProp' } - static String getAProp() { 'AProp' } - static String getpNAME() { 'pNAME' } - } - - import static A.* - - class B { - @groovy.transform.CompileStatic - def method() { - assert prop == 'Prop' - assert Prop == 'Prop' - assert x == 'X' - assert X == 'X' - assert someProp == 'SomeProp' - assert SomeProp == 'SomeProp' - assert DB == 'DB' - assert XML == 'XML' - assert AProp == 'AProp' - assert aProp == 'aProp' - assert pNAME == 'pNAME' - } - } - new B().method() + new B().method() ''' } // GROOVY-9618 + @Test void testJavaBeanNamingForPropertyAccessWithCategory() { assertScript ''' - class A {} - class ACategory { - static String getProp(A self) { 'Prop' } - static String getSomeProp(A self) { 'SomeProp' } - static String getX(A self) { 'X' } - static String getDB(A self) { 'DB' } - static String getXML(A self) { 'XML' } - static String getaProp(A self) { 'aProp' } - static String getAProp(A self) { 'AProp' } - static String getpNAME(A self) { 'pNAME' } - } - use(ACategory) { - def a = new A() - assert a.prop == 'Prop' - assert a.Prop == 'Prop' - assert a.x == 'X' - assert a.X == 'X' - assert a.someProp == 'SomeProp' - assert a.SomeProp == 'SomeProp' - assert a.DB == 'DB' - assert a.XML == 'XML' - assert a.AProp == 'AProp' - assert a.aProp == 'aProp' - assert a.pNAME == 'pNAME' - } + class A {} + class ACategory { + static String getProp(A self) { 'Prop' } + static String getSomeProp(A self) { 'SomeProp' } + static String getX(A self) { 'X' } + static String getDB(A self) { 'DB' } + static String getXML(A self) { 'XML' } + static String getaProp(A self) { 'aProp' } + static String getAProp(A self) { 'AProp' } + static String getpNAME(A self) { 'pNAME' } + } + use(ACategory) { + def a = new A() + assert a.prop == 'Prop' + assert a.Prop == 'Prop' + assert a.x == 'X' + assert a.X == 'X' + assert a.someProp == 'SomeProp' + assert a.SomeProp == 'SomeProp' + assert a.DB == 'DB' + assert a.XML == 'XML' + assert a.AProp == 'AProp' + assert a.aProp == 'aProp' + assert a.pNAME == 'pNAME' + } ''' } - void testMissingPropertyWithStaticImport() { // GROOVY-5852+GROOVY-9618 - - def errMsg = shouldFail ''' + // GROOVY-5852, GROOVY-9618 + @Test + void testMissingPropertyWithStaticImport() { + def err = shouldFail ''' class Constants { static final pi = 3.14 } @@ -569,23 +620,25 @@ final class PropertyTest extends GroovyTestCase { assert PI.toString().startsWith('3') ''' - - assert errMsg.contains('No such property: PI for class:') + assert err.message.contains('No such property: PI for class:') } - void testMissingPropertyWithDirectUsage() { // GROOVY-5852+GROOVY-9618 - def errMsg = shouldFail ''' + // GROOVY-5852, GROOVY-9618 + @Test + void testMissingPropertyWithDirectUsage() { + def err = shouldFail ''' class Constants { static final pi = 3.14 } assert Constants.PI.toString().startsWith('3') ''' - - assert errMsg.contains('No such property: PI for class: Constants') + assert err.message.contains('No such property: PI for class: Constants') } - void testPropertyDirectUsageWithAllowableCaseChange() { // GROOVY-5852+GROOVY-9618 + // GROOVY-5852, GROOVY-9618 + @Test + void testPropertyDirectUsageWithAllowableCaseChange() { assertScript ''' class Constants { static final pi = 3.14 @@ -595,7 +648,9 @@ final class PropertyTest extends GroovyTestCase { ''' } - void testPropertyStaticImportWithAllowableCaseChange() { // GROOVY-5852+GROOVY-9618 + // GROOVY-5852, GROOVY-9618 + @Test + void testPropertyStaticImportWithAllowableCaseChange() { assertScript ''' class Constants { static final pi = 3.14 @@ -607,7 +662,9 @@ final class PropertyTest extends GroovyTestCase { ''' } - void testPropertyAndStaticUppercaseFieldPriority() { // GROOVY-9618 + // GROOVY-9618 + @Test + void testPropertyAndStaticUppercaseFieldPriority() { assertScript ''' class A { public static X = 1 @@ -622,62 +679,66 @@ final class PropertyTest extends GroovyTestCase { assert new C().test() == 2 ''' } -} -class Base { - protected String field = 'bar' + //-------------------------------------------------------------------------- - protected thing = 'foo thing' + static class Base { + protected String field = 'bar' - def getXprop() { 'foo x prop' } + protected thing = 'foo thing' - def x() { 'foo x' } + def getXprop() { 'foo x prop' } - void setThing(value) { thing = value } + def x() { 'foo x' } - //testing final property getter - final getFinalProperty() { 1 } + void setThing(value) { thing = value } - // testing normal property - def normalProperty = 1 -} + // testing final property getter + final getFinalProperty() { 1 } -class Child extends Base { - protected String field = 'foo' + super.field + // testing normal property + def normalProperty = 1 + } - def getField() { field } + static class Child extends Base { + protected String field = 'foo' + super.field - void setSuperField(value) { super.field = value } + def getField() { field } - def getSuperField() { super.field } + void setSuperField(value) { super.field = value } - def thing = 'bar thing' + def getSuperField() { super.field } - def superthing() { - 'bar1' + super.thing - } + def thing = 'bar thing' - def x() { - 'bar2' + super.x() - } + def superthing() { + 'bar1' + super.thing + } - def getXprop() { - 'bar3' + super.xprop - } + @Override + def x() { + 'bar2' + super.x() + } - def getXpropViaMethod() { - 'bar4' + super.getXprop() - } + @Override + def getXprop() { + 'bar3' + super.xprop + } - def setSuperThing(value) { - super.thing = value - } + def getXpropViaMethod() { + 'bar4' + super.getXprop() + } - // testing final property getter - // the following property should not add a new getter - // method, this would result in a verify error - def finalProperty = 32 + def setSuperThing(value) { + super.thing = value + } - // testing overwriting normal property - def normalProperty = 2 + // testing final property getter + // the following property should not add a new getter + // method, this would result in a verify error + def finalProperty = 32 + + // testing overwriting normal property + def normalProperty = 2 + } } diff --git a/src/test/groovy/org/codehaus/groovy/classgen/asm/NestHostTests.groovy b/src/test/groovy/org/codehaus/groovy/classgen/asm/NestHostTests.groovy index db63589cda..07ee8ea33f 100644 --- a/src/test/groovy/org/codehaus/groovy/classgen/asm/NestHostTests.groovy +++ b/src/test/groovy/org/codehaus/groovy/classgen/asm/NestHostTests.groovy @@ -20,7 +20,7 @@ package org.codehaus.groovy.classgen.asm import org.codehaus.groovy.control.CompilationUnit import org.codehaus.groovy.control.Phases -import org.junit.Test +import org.junit.jupiter.api.Test final class NestHostTests {