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 37043f304c940a297efc9a36ce8de73d0224f574 Author: Eric Milles <[email protected]> AuthorDate: Thu Aug 25 16:04:53 2022 -0500 GROOVY-9127, GROOVY-9195, GROOVY-9293: STC: super field access checks --- .../groovy/classgen/AsmClassGenerator.java | 32 +- .../transform/stc/StaticTypeCheckingVisitor.java | 55 +- src/test/groovy/bugs/Groovy9127.groovy | 164 ++++ src/test/groovy/bugs/Groovy9136.groovy | 61 +- src/test/groovy/bugs/Groovy9288.groovy | 109 ++- src/test/groovy/bugs/Groovy9292.groovy | 382 ++++++++ src/test/groovy/bugs/Groovy9292Bug.groovy | 1008 -------------------- .../stc/FieldsAndPropertiesSTCTest.groovy | 50 +- .../ArraysAndCollectionsStaticCompileTest.groovy | 27 +- .../groovy/text/MarkupTemplateEngineTest.groovy | 7 +- 10 files changed, 729 insertions(+), 1166 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java index a9e12910e7..9d3ced436b 100644 --- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java +++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java @@ -91,6 +91,7 @@ import org.codehaus.groovy.ast.stmt.SynchronizedStatement; import org.codehaus.groovy.ast.stmt.ThrowStatement; import org.codehaus.groovy.ast.stmt.TryCatchStatement; import org.codehaus.groovy.ast.stmt.WhileStatement; +import org.codehaus.groovy.ast.tools.GeneralUtils; import org.codehaus.groovy.ast.tools.WideningCategories; import org.codehaus.groovy.classgen.asm.BytecodeHelper; import org.codehaus.groovy.classgen.asm.BytecodeVariable; @@ -1180,8 +1181,7 @@ public class AsmClassGenerator extends ClassGenerator { } private boolean isThisOrSuperInStaticContext(Expression objectExpression) { - if (controller.isInClosure()) return false; - return controller.isStaticContext() && isThisOrSuper(objectExpression); + return isThisOrSuper(objectExpression) && controller.isStaticContext() && !controller.isInClosure(); } public void visitPropertyExpression(PropertyExpression expression) { @@ -1233,11 +1233,11 @@ public class AsmClassGenerator extends ClassGenerator { if (controller.getCompileStack().isLHS()) { adapter = setField; if (isGroovyObject(objectExpression)) adapter = setGroovyObjectField; - if (usesSuper(expression)) adapter = setFieldOnSuper; + if (isSuperExpression(objectExpression)) adapter = setFieldOnSuper; } else { adapter = getField; if (isGroovyObject(objectExpression)) adapter = getGroovyObjectField; - if (usesSuper(expression)) adapter = getFieldOnSuper; + if (isSuperExpression(objectExpression)) adapter = getFieldOnSuper; } visitAttributeOrProperty(expression, adapter); } @@ -1249,18 +1249,18 @@ public class AsmClassGenerator extends ClassGenerator { } } - private static boolean usesSuper(PropertyExpression pe) { - Expression expression = pe.getObjectExpression(); - if (expression instanceof VariableExpression) { - VariableExpression varExp = (VariableExpression) expression; - String variable = varExp.getName(); - return variable.equals("super"); - } - return false; + private boolean isGroovyObject(Expression objectExpression) { + if (ExpressionUtils.isThisExpression(objectExpression)) return true; + if (objectExpression instanceof ClassExpression) return false; + + ClassNode objectExpressionType = controller.getTypeChooser().resolveType(objectExpression, controller.getClassNode()); + if (objectExpressionType.equals(ClassHelper.OBJECT_TYPE)) objectExpressionType = objectExpression.getType(); + if (GeneralUtils.isOrImplements(objectExpressionType, ClassHelper.MAP_TYPE)) return false; // GROOVY-8074 + return implementsGroovyObject(objectExpressionType); // GROOVY-9195, GROOVY-9288, et al. } - private static boolean isGroovyObject(Expression objectExpression) { - return ExpressionUtils.isThisExpression(objectExpression) || objectExpression.getType().isDerivedFromGroovyObject() && !(objectExpression instanceof ClassExpression); + private static boolean implementsGroovyObject(ClassNode cn) { + return cn.isDerivedFromGroovyObject() || (!cn.isInterface() && cn.getCompileUnit() != null); } public void visitFieldExpression(FieldExpression expression) { @@ -1691,8 +1691,8 @@ public class AsmClassGenerator extends ClassGenerator { public void loadWrapper(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/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 954d8c06ba..9212345315 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -1450,9 +1450,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { return existsProperty(pexp, checkForReadOnly, null); } - private static final Set<String> CLOSURE_IMPLICIT_VARIABLE_SET = - Collections.unmodifiableSet(new HashSet<>(Arrays.asList("it", "this", "thisObject", "owner", "delegate"))); - /** * Checks whether a property exists on the receiver, or on any of the possible receiver classes (found in the * temporary type information table) @@ -1476,9 +1473,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { // Outer.this for any level of nesting ClassNode outerNode = objectExpressionType.getGenericsTypes()[0].getType(); ClassNode found = null; - for (ClassNode current : enclosingTypes) { - if (!current.isStaticClass() && current instanceof InnerClassNode && outerNode.equals(current.getOuterClass())) { - found = current; + for (ClassNode enclosingType : enclosingTypes) { + if (!enclosingType.isStaticClass() && outerNode.equals(enclosingType.getOuterClass())) { + found = enclosingType; break; } } @@ -1492,9 +1489,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { List<Receiver<String>> receivers = new ArrayList<>(); addReceivers(receivers, makeOwnerList(objectExpression), pexp.isImplicitThis()); - String capName = MetaClassHelper.capitalize(propertyName); + String capName = MetaClassHelper.capitalize(propertyName), isserName = "is" + capName, getterName = "get" + capName, setterName = "set" + capName; boolean isAttributeExpression = pexp instanceof AttributeExpression; - HashSet<ClassNode> handledNodes = new HashSet<ClassNode>(); + Set<ClassNode> handledNodes = new HashSet<>(); for (Receiver<String> receiver : receivers) { ClassNode receiverType = receiver.getType(); @@ -1538,16 +1535,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { } field = allowStaticAccessToMember(field, staticOnly); - // GROOVY-9288, GROOVY-9292, GROOVY-9293 - if (null != field) { - int fieldModifiers = field.getModifiers(); - if (Modifier.isProtected(fieldModifiers) || isPackagePrivate(fieldModifiers)) { - if (null != typeCheckingContext.getEnclosingClosure() && CLOSURE_IMPLICIT_VARIABLE_SET.contains(objectExpression.getText())) { - objectExpression.putNodeMetaData(StaticCompilationMetadataKeys.RECEIVER_OF_DYNAMIC_PROPERTY, OBJECT_TYPE); - } - } - } - // skip property/accessor checks for "x.@field" if (storeField(field, isAttributeExpression, pexp, receiverType, visitor, receiver.getData(), !readMode)) { pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY); @@ -1562,13 +1549,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { return true; } - boolean isThisExpression = enclosingTypes.contains(receiverType); - - MethodNode getter = findGetter(current, "get" + capName, pexp.isImplicitThis()); + MethodNode getter = findGetter(current, getterName, pexp.isImplicitThis()); getter = allowStaticAccessToMember(getter, staticOnly); - if (getter == null) getter = findGetter(current, "is" + capName, pexp.isImplicitThis()); + if (getter == null) getter = findGetter(current, isserName, pexp.isImplicitThis()); getter = allowStaticAccessToMember(getter, staticOnly); - final String setterName = "set" + capName; List<MethodNode> setters = findSetters(current, setterName, false); setters = allowStaticAccessToMember(setters, staticOnly); @@ -1578,7 +1562,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { PropertyNode propertyNode = current.getProperty(propertyName); propertyNode = allowStaticAccessToMember(propertyNode, staticOnly); // prefer explicit getter or setter over property if receiver is not 'this' - boolean checkGetterOrSetter = !isThisExpression || propertyNode == null; + boolean checkGetterOrSetter = propertyNode == null || !enclosingTypes.contains(receiverType); if (readMode && checkGetterOrSetter) { if (getter != null) { @@ -1587,8 +1571,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { storeTargetMethod(pexp, getter); pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY); String delegationData = receiver.getData(); - if (delegationData != null) + if (delegationData != null) { pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData); + } return true; } } else if (!readMode && checkGetterOrSetter) { @@ -1610,6 +1595,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { if (enclosingBinaryExpression != null) { putSetterInfo(enclosingBinaryExpression.getLeftExpression(), info); } + pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY); String delegationData = receiver.getData(); if (delegationData != null) { pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData); @@ -1632,8 +1618,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { // GROOVY-5568: the property may be defined by DGM for (ClassNode dgmReceiver : isPrimitiveType(receiverType) ? new ClassNode[]{receiverType, getWrapper(receiverType)} : new ClassNode[]{receiverType}) { - List<MethodNode> methods = findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), dgmReceiver, "get" + capName, ClassNode.EMPTY_ARRAY); - for (MethodNode m : findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), dgmReceiver, "is" + capName, ClassNode.EMPTY_ARRAY)) { + List<MethodNode> methods = findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), dgmReceiver, getterName, ClassNode.EMPTY_ARRAY); + for (MethodNode m : findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), dgmReceiver, isserName, ClassNode.EMPTY_ARRAY)) { if (Boolean_TYPE.equals(getWrapper(m.getReturnType()))) methods.add(m); } if (isUsingGenericsOrIsArrayUsingGenerics(dgmReceiver)) { // GROOVY-10075: "List<Integer>" vs "List<String>" @@ -1697,18 +1683,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { return foundGetterOrSetter; } - private static boolean isPackagePrivate(int modifiers) { - return !(Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers) || Modifier.isPrivate(modifiers)); - } - - private static boolean hasAccessToField(FieldNode field, ClassNode objectExpressionType) { - if (field.isPublic() || field.isProtected()) { + private static boolean hasAccessToField(final FieldNode field, final ClassNode accessor) { + if (field.isPublic() || accessor.equals(field.getDeclaringClass())) { return true; } - if (!field.isPrivate() && Objects.equals(objectExpressionType.getPackageName(), field.getDeclaringClass().getPackageName())) { - return true; + if (field.isProtected()) { + return accessor.isDerivedFrom(field.getDeclaringClass()); + } else { + return !field.isPrivate() && Objects.equals(accessor.getPackageName(), field.getDeclaringClass().getPackageName()); } - return false; } private MethodNode findGetter(ClassNode current, String name, boolean searchOuterClasses) { diff --git a/src/test/groovy/bugs/Groovy9127.groovy b/src/test/groovy/bugs/Groovy9127.groovy new file mode 100644 index 0000000000..60c957a00a --- /dev/null +++ b/src/test/groovy/bugs/Groovy9127.groovy @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package groovy.bugs + +import groovy.transform.CompileStatic +import org.codehaus.groovy.control.CompilationFailedException +import org.codehaus.groovy.control.CompilationUnit + +import static org.codehaus.groovy.control.Phases.CLASS_GENERATION + +@CompileStatic +final class Groovy9127 extends GroovyTestCase { + + void testReadOnlyPropertyAssignment1() { + assertScript ''' + @groovy.transform.CompileStatic + class Foo { + protected String field = 'foo' + String getField() { return field } + } + @groovy.transform.CompileStatic + class Bar extends Foo { + void changeField() { + field = 'bar' // GROOVY-9127: [Static type checking] - Cannot set read-only property: field + } + @Override + String getField() { return 'value' } + } + def bar = new Bar() + bar.changeField() + assert bar.field == 'value' + ''' + } + + void testReadOnlyPropertyAssignment2() { + assertScript ''' + @groovy.transform.CompileStatic + class Foo { + public String field = 'foo' + String getField() { return field } + } + @groovy.transform.CompileStatic + class Bar extends Foo { + void changeField() { + field = 'bar' + } + @Override + String getField() { return 'value' } + } + def bar = new Bar() + bar.changeField() + assert bar.field == 'value' + ''' + } + + void testReadOnlyPropertyAssignment3() { + assertScript ''' + @groovy.transform.CompileStatic + class Foo { + @groovy.transform.PackageScope String field = 'foo' + String getField() { return field } + } + @groovy.transform.CompileStatic + class Bar extends Foo { + void changeField() { + field = 'bar' + } + @Override + String getField() { return 'value' } + } + def bar = new Bar() + bar.changeField() + assert bar.field == 'value' + ''' + } + + void testReadOnlyPropertyAssignment4() { + new CompilationUnit().with { + addSource 'Foo.groovy', ''' + package foo + + @groovy.transform.CompileStatic + class Foo { + @groovy.transform.PackageScope String field = 'foo' + String getField() { return field } + } + ''' + + addSource 'Bar.groovy', ''' + package bar + + @groovy.transform.CompileStatic + class Bar extends foo.Foo { + void changeField() { + field = 'bar' + } + @Override + String getField() { return 'value' } + } + ''' + + def err = shouldFail CompilationFailedException, { + compile CLASS_GENERATION + } + assert err =~ /\[Static type checking\] - Cannot set read-only property: field/ + } + } + + void testReadOnlyPropertyAssignment5() { + def err = shouldFail CompilationFailedException, ''' + @groovy.transform.CompileStatic + class Foo { + private String field = 'foo' + String getField() { return field } + } + @groovy.transform.CompileStatic + class Bar extends Foo { + void changeField() { + field = 'bar' + } + @Override + String getField() { return 'value' } + } + ''' + assert err =~ /\[Static type checking\] - Cannot set read-only property: field/ + } + + void testAttributeAssignmentVariation() { + assertScript ''' + @groovy.transform.CompileStatic + class Foo { + protected String field = 'foo' + String getField() { return field } + } + @groovy.transform.CompileStatic + class Bar extends Foo { + void changeField() { + this.@field = 'bar' + } + @Override + String getField() { return 'value' } + } + def bar = new Bar() + bar.changeField() + assert bar.field == 'value' + ''' + } +} diff --git a/src/test/groovy/bugs/Groovy9136.groovy b/src/test/groovy/bugs/Groovy9136.groovy index f85aff276e..eac12742c8 100644 --- a/src/test/groovy/bugs/Groovy9136.groovy +++ b/src/test/groovy/bugs/Groovy9136.groovy @@ -18,28 +18,71 @@ */ package groovy.bugs -import groovy.transform.CompileStatic +import org.junit.Test -@CompileStatic -final class Groovy9136 extends GroovyTestCase { +import static groovy.test.GroovyAssert.assertScript - void testMethodParameterAccessFromClosure() { +final class Groovy9136 { + + @Test + void testMethodParameterFieldAccessFromClosure1() { assertScript ''' - @groovy.transform.CompileStatic class Foo { public String field = 'foo' } - @groovy.transform.CompileStatic class Bar { - def doIt(Foo foo) { + @groovy.transform.CompileStatic + def test(Foo foo) { 'baz'.with { - foo.field // GROOVY-9136: Access to Foo#foo is forbidden at line: -1, column: -1 + foo.field // Access to Foo#foo is forbidden at line: -1, column: -1 + } + } + } + + def bar = new Bar() + def out = bar.test(new Foo()) + assert out == 'foo' + ''' + } + + @Test // GROOVY-9195 + void testMethodParameterFieldAccessFromClosure2() { + assertScript ''' + class Foo { + private String field = 'foo' + } + class Bar { + @groovy.transform.CompileStatic + def test(Foo foo) { + 'baz'.with { + foo.field + } + } + } + + def bar = new Bar() + def out = bar.test(new Foo()) + assert out == 'foo' + ''' + } + + @Test + void testMethodParameterFieldAccessFromClosure3() { + assertScript ''' + class Foo { + private String field = 'foo' + } + @groovy.transform.CompileStatic + class Bar { + def test(Foo foo) { + foo.with { + field } } } def bar = new Bar() - def out = bar.doIt(new Foo()) + def out = bar.test(new Foo()) assert out == 'foo' ''' } diff --git a/src/test/groovy/bugs/Groovy9288.groovy b/src/test/groovy/bugs/Groovy9288.groovy index d8650eecb3..d1b67e3b6c 100644 --- a/src/test/groovy/bugs/Groovy9288.groovy +++ b/src/test/groovy/bugs/Groovy9288.groovy @@ -19,18 +19,31 @@ package groovy.bugs import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import org.junit.runners.Parameterized.Parameter +import org.junit.runners.Parameterized.Parameters +@RunWith(Parameterized) final class Groovy9288 { + @Parameters + static modifiers() { + ['public', 'protected'] + } + + @Parameter + public String modifier + private final GroovyShell shell = new GroovyShell() @Test - void 'test accessing a protected super class field inside a closure - same package'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - same package'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } class B extends A { @@ -44,20 +57,20 @@ final class Groovy9288 { def obj = new B() assert obj.test() == "works" - ''' + """ } @Test - void 'test accessing a protected super class field inside a closure - diff package'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - diff package'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } assert true - ''' + """ shell.evaluate ''' package b @@ -77,12 +90,12 @@ final class Groovy9288 { } @Test - void 'test accessing a protected super class field inside a closure - same package, it qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - same package, it qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } class B extends A { @@ -96,20 +109,20 @@ final class Groovy9288 { def obj = new B() assert obj.test() == "works" - ''' + """ } @Test - void 'test accessing a protected super class field inside a closure - diff package, it qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - diff package, it qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } assert true - ''' + """ shell.evaluate ''' package b @@ -129,12 +142,12 @@ final class Groovy9288 { } @Test - void 'test accessing a protected super class field inside a closure - same package, this qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - same package, this qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } class B extends A { @@ -148,20 +161,20 @@ final class Groovy9288 { def obj = new B() assert obj.test() == "works" - ''' + """ } @Test - void 'test accessing a protected super class field inside a closure - diff package, this qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - diff package, this qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } assert true - ''' + """ shell.evaluate ''' package b @@ -181,12 +194,12 @@ final class Groovy9288 { } @Test - void 'test accessing a protected super class field inside a closure - same package, owner qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - same package, owner qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } class B extends A { @@ -200,20 +213,20 @@ final class Groovy9288 { def obj = new B() assert obj.test() == "works" - ''' + """ } @Test - void 'test accessing a protected super class field inside a closure - diff package, owner qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - diff package, owner qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } assert true - ''' + """ shell.evaluate ''' package b @@ -233,12 +246,12 @@ final class Groovy9288 { } @Test - void 'test accessing a protected super class field inside a closure - same package, delegate qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - same package, delegate qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } class B extends A { @@ -252,20 +265,20 @@ final class Groovy9288 { def obj = new B() assert obj.test() == "works" - ''' + """ } @Test - void 'test accessing a protected super class field inside a closure - diff package, delegate qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - diff package, delegate qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } assert true - ''' + """ shell.evaluate ''' package b @@ -285,12 +298,12 @@ final class Groovy9288 { } @Test - void 'test accessing a protected super class field inside a closure - same package, thisObject qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - same package, thisObject qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } class B extends A { @@ -304,20 +317,20 @@ final class Groovy9288 { def obj = new B() assert obj.test() == "works" - ''' + """ } @Test - void 'test accessing a protected super class field inside a closure - diff package, thisObject qualifier'() { - shell.evaluate ''' + void 'test accessing a super class field inside a closure - diff package, thisObject qualifier'() { + shell.evaluate """ package a class A { - protected String superField = 'works' + $modifier String superField = 'works' } assert true - ''' + """ shell.evaluate ''' package b diff --git a/src/test/groovy/bugs/Groovy9292.groovy b/src/test/groovy/bugs/Groovy9292.groovy new file mode 100644 index 0000000000..3ffe823f8e --- /dev/null +++ b/src/test/groovy/bugs/Groovy9292.groovy @@ -0,0 +1,382 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package groovy.bugs + +import org.junit.Test + +import static groovy.test.GroovyAssert.shouldFail + +final class Groovy9292 { + + private final GroovyShell shell = new GroovyShell() + + @Test + void 'test accessing a private super class field inside a closure - same module'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + class B extends A { + @groovy.transform.CompileStatic + def test() { + 'something'.with { + return superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - same package'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + assert true + ''' + + shell.evaluate ''' + package a + + class B extends A { + @groovy.transform.CompileStatic + def test() { + 'something'.with { + return superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - diff package'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + assert true + ''' + + shell.evaluate ''' + package b + + class B extends a.A { + @groovy.transform.CompileStatic + def test() { + 'something'.with { + return superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - same package, it qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + class B extends A { + @groovy.transform.CompileStatic + def test() { + with { + return it.superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - diff package, it qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + assert true + ''' + + shell.evaluate ''' + package b + + class B extends a.A { + @groovy.transform.CompileStatic + def test() { + with { + return it.superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - same package, this qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + class B extends A { + @groovy.transform.CompileStatic + def test() { + 'something'.with { + return this.superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - diff package, this qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + assert true + ''' + + shell.evaluate ''' + package b + + class B extends a.A { + @groovy.transform.CompileStatic + def test() { + 'something'.with { + return this.superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - same package, owner qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + class B extends A { + @groovy.transform.CompileStatic + def test() { + 'something'.with { + return owner.superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - diff package, owner qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + assert true + ''' + + shell.evaluate ''' + package b + + class B extends a.A { + @groovy.transform.CompileStatic + def test() { + 'something'.with { + return owner.superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - same package, delegate qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + class B extends A { + @groovy.transform.CompileStatic + def test() { + with { + return delegate.superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - diff package, delegate qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + assert true + ''' + + shell.evaluate ''' + package b + + class B extends a.A { + @groovy.transform.CompileStatic + def test() { + with { + return delegate.superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - same package, thisObject qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + class B extends A { + @groovy.transform.CompileStatic + def test() { + 'something'.with { + return thisObject.superField + } + } + } + + new B().test() + ''' + } + } + + @Test + void 'test accessing a private super class field inside a closure - diff package, thisObject qualifier'() { + shouldFail(MissingPropertyException) { + shell.evaluate ''' + package a + + class A { + private String superField + } + + assert true + ''' + + shell.evaluate ''' + package b + + class B extends a.A { + @groovy.transform.CompileStatic + def test() { + 'something'.with { + return thisObject.superField + } + } + } + + new B().test() + ''' + } + } +} diff --git a/src/test/groovy/bugs/Groovy9292Bug.groovy b/src/test/groovy/bugs/Groovy9292Bug.groovy deleted file mode 100644 index 06cadbca21..0000000000 --- a/src/test/groovy/bugs/Groovy9292Bug.groovy +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.bugs - -import groovy.transform.NotYetImplemented -import org.junit.Test - -final class Groovy9292Bug { - - @Test - void "test accessing a protected super class field from inside a closure - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - protected String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - 'something'.with { - return superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a protected super class field from inside a closure - same package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - protected String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package a - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - 'something'.with { - return superField - } - } - } - assert true - ''') - - shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") - } - - - @Test - void "test accessing a protected super class field from inside a closure - using it - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - protected String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return it.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a protected super class field from inside a closure - using this - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - protected String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - 'something'.with { - return this.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - - @Test - void "test accessing a protected super class field from inside a closure - using thisObject - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - protected String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - 'something'.with { - return thisObject.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a protected super class field from inside a closure - using owner - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - protected String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - 'something'.with { - return owner.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a protected super class field from inside a closure - using delegate - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - protected String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return delegate.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a package-private super class field from inside a closure - same package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - @groovy.transform.PackageScope String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package a - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return delegate.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a package-private super class field from inside a closure - using delegate - same package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - @groovy.transform.PackageScope String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package a - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return delegate.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a package-private super class field from inside a closure - using it - same package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - @groovy.transform.PackageScope String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package a - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return it.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") - } - - @NotYetImplemented // java.lang.IllegalAccessError: class a.ConcreteClass$_doThing_closure1 tried to access field a.Abstract_Class.superField (a.ConcreteClass$_doThing_closure1 is in unnamed module of loader groovy.lang.GroovyClassLoader$InnerLoader @5fa47fea; a.Abstract_Class is in unnamed module of loader groovy.lang.GroovyClassLoader$InnerLoader @28cda624) - @Test - void "test accessing a package-private super class field from inside a closure - using this - same package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - @groovy.transform.PackageScope String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package a - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return this.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a package-private super class field from inside a closure - using thisObject - same package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - @groovy.transform.PackageScope String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package a - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return thisObject.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a package-private super class field from inside a closure - using owner - same package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - @groovy.transform.PackageScope String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package a - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return owner.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new a.ConcreteClass().doThing() == 'field'") - } - - - @Test - void "test accessing a public super class field from inside a closure - different package -- regression"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - public String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a public super class field from inside a closure - using delegate - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - public String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return delegate.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - - @Test - void "test accessing a public super class field from inside a closure - using it - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - public String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return it.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a public super class field from inside a closure - using this - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - public String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return this.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a public super class field from inside a closure - using thisObject - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - public String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return thisObject.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a public super class field from inside a closure - using owner - different package"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - public String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return owner.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - - @Test - void "test accessing a private super class field from inside a closure via getter - different package -- regression"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - - @Test - void "test accessing a private super class field from inside a closure via getter - using delegate - different package -- regression"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return delegate.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a private super class field from inside a closure via getter - using it - different package -- regression"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return it.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - - @Test - void "test accessing a private super class field from inside a closure via getter - using this - different package -- regression"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return this.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a private super class field from inside a closure via getter - using thisObject - different package -- regression"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return thisObject.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } - - @Test - void "test accessing a private super class field from inside a closure via getter - using owner - different package -- regression"() { - GroovyShell shell = new GroovyShell() - shell.evaluate(''' - package a - - import groovy.transform.CompileStatic - - @CompileStatic - abstract class Abstract_Class { - String superField = 'field' - - abstract String doThing() - } - assert true - ''') - - shell.evaluate(''' - package b - - import a.Abstract_Class - import groovy.transform.CompileStatic - - @CompileStatic - class ConcreteClass extends Abstract_Class { - - @Override - String doThing() { - this.with { - return owner.superField - } - } - } - assert true - ''') - - shell.evaluate("assert new b.ConcreteClass().doThing() == 'field'") - } -} diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy index f0688df44e..962272700a 100644 --- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy +++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy @@ -383,23 +383,6 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { ''' } - // GROOVY-5517 - void testShouldFindStaticPropertyEvenIfObjectImplementsMap() { - 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 testClassPropertyOnInterface() { assertScript ''' Class test(Serializable arg) { @@ -476,7 +459,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { } // GROOVY-5700 - void testInferenceOfMapDotProperty() { + void testMapPropertyAccess1() { assertScript ''' def map = [key: 123] @ASTTest(phase=INSTRUCTION_SELECTION, value={ @@ -488,7 +471,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { } // GROOVY-5700, GROOVY-8788 - void testInferenceOfMapSubProperty() { + void testMapPropertyAccess2() { assertScript ''' def map = [key: 123] @ASTTest(phase=INSTRUCTION_SELECTION, value={ @@ -499,6 +482,35 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { ''' } + // GROOVY-8074 + void testMapPropertyAccess3() { + assertScript ''' + class C extends HashMap { + def foo = 1 + } + def map = new C() + 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 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/subprojects/groovy-templates/src/test/groovy/groovy/text/MarkupTemplateEngineTest.groovy b/subprojects/groovy-templates/src/test/groovy/groovy/text/MarkupTemplateEngineTest.groovy index 162edc1665..091913ce4d 100644 --- a/subprojects/groovy-templates/src/test/groovy/groovy/text/MarkupTemplateEngineTest.groovy +++ b/subprojects/groovy-templates/src/test/groovy/groovy/text/MarkupTemplateEngineTest.groovy @@ -736,10 +736,9 @@ html { } ''' StringWriter rendered = new StringWriter() - def model = [persons: [[name: 'Cedric'], [name: 'Jochen']]] + def model = [persons: [Person[name: 'Cedric'], Person[name: 'Jochen']]] template.make(model).writeTo(rendered) assert rendered.toString() == '<html><body><ul><li>Cedric</li><li>Jochen</li></ul></body></html>' - } void testInlinedModelTypeDeclarationShouldFailBecauseIncorrectType() { @@ -761,11 +760,9 @@ html { } ''' StringWriter rendered = new StringWriter() - def model = [persons: [[name: 'Cedric'], [name: 'Jochen']]] + def model = [persons: [Person[name: 'Cedric'], Person[name: 'Jochen']]] template.make(model).writeTo(rendered) - assert rendered.toString() == '<html><body><ul><li>Cedric</li><li>Jochen</li></ul></body></html>' } =~ 'No such property: name for class: java.lang.String' - } void testFragment() {
