You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2021/03/31 22:26:12 UTC
[groovy] branch master updated: GROOVY-10004: @Lazy transform
should check for explicit getters/setters (closes #1537)
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new a93b782 GROOVY-10004: @Lazy transform should check for explicit getters/setters (closes #1537)
a93b782 is described below
commit a93b782639246b864304b0e5383ca160cdd7dc60
Author: Paul King <pa...@asert.com.au>
AuthorDate: Mon Mar 29 16:44:14 2021 +1000
GROOVY-10004: @Lazy transform should check for explicit getters/setters (closes #1537)
---
.../groovy/transform/LazyASTTransformation.java | 39 +++++++++++++++-------
.../groovy/transform/LazyTransformTest.groovy | 24 +++++++++++++
2 files changed, 51 insertions(+), 12 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/LazyASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/LazyASTTransformation.java
index e95b8b2..9251d0b 100644
--- a/src/main/java/org/codehaus/groovy/transform/LazyASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/LazyASTTransformation.java
@@ -25,6 +25,7 @@ import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.InnerClassNode;
+import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.PropertyNode;
import org.codehaus.groovy.ast.expr.ConstantExpression;
@@ -37,6 +38,7 @@ import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
+import org.objectweb.asm.Opcodes;
import java.lang.ref.SoftReference;
@@ -102,9 +104,9 @@ public class LazyASTTransformation extends AbstractASTTransformation {
}
if (soft instanceof ConstantExpression && ((ConstantExpression) soft).getValue().equals(true)) {
- createSoft(fieldNode, init);
+ createSoft(fieldNode, init, xform);
} else {
- create(fieldNode, init);
+ create(fieldNode, init, xform);
// @Lazy not meaningful with primitive so convert to wrapper if needed
if (ClassHelper.isPrimitiveType(fieldNode.getType())) {
fieldNode.setType(ClassHelper.getWrapper(fieldNode.getType()));
@@ -112,7 +114,7 @@ public class LazyASTTransformation extends AbstractASTTransformation {
}
}
- private static void create(FieldNode fieldNode, final Expression initExpr) {
+ private static void create(FieldNode fieldNode, final Expression initExpr, ErrorCollecting xform) {
final BlockStatement body = new BlockStatement();
if (fieldNode.isStatic()) {
addHolderClassIdiomBody(body, fieldNode, initExpr);
@@ -121,7 +123,7 @@ public class LazyASTTransformation extends AbstractASTTransformation {
} else {
addNonThreadSafeBody(body, fieldNode, initExpr);
}
- addMethod(fieldNode, body, fieldNode.getType());
+ addMethod(fieldNode, body, fieldNode.getType(), xform);
}
private static void addHolderClassIdiomBody(BlockStatement body, FieldNode fieldNode, Expression initExpr) {
@@ -170,26 +172,39 @@ public class LazyASTTransformation extends AbstractASTTransformation {
body.addStatement(ifElseS(notNullX(fieldExpr), stmt(fieldExpr), assignS(fieldExpr, initExpr)));
}
- private static void addMethod(FieldNode fieldNode, BlockStatement body, ClassNode type) {
+ private static void addMethod(FieldNode fieldNode, BlockStatement body, ClassNode type, ErrorCollecting xform) {
int visibility = ACC_PUBLIC;
if (fieldNode.isStatic()) visibility |= ACC_STATIC;
String propName = capitalize(fieldNode.getName().substring(1));
ClassNode declaringClass = fieldNode.getDeclaringClass();
- addGeneratedMethod(declaringClass, "get" + propName, visibility, type, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body);
+ addGeneratedMethodOrError(declaringClass, "get" + propName, visibility, type, body, xform, fieldNode);
if (ClassHelper.boolean_TYPE.equals(type)) {
- addGeneratedMethod(declaringClass, "is" + propName, visibility, type,
- Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, stmt(callThisX("get" + propName)));
+ addGeneratedMethodOrError(declaringClass, "is" + propName, visibility, type, stmt(callThisX("get" + propName)), xform, fieldNode);
}
+ // expect no setter
+ MethodNode existing = declaringClass.getDeclaredMethod("set" + propName, params(param(fieldNode.getType(), "value")));
+ if (existing != null && (existing.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0) {
+ xform.addError("Error during @Lazy processing: invalid explicit setter 'set" + propName + "' found", fieldNode);
+ }
+ }
+
+ private static void addGeneratedMethodOrError(ClassNode declaringClass, String name, int visibility, ClassNode type, Statement body, ErrorCollecting xform, FieldNode fieldNode) {
+ Parameter[] params = Parameter.EMPTY_ARRAY;
+ MethodNode existing = declaringClass.getDeclaredMethod(name, params);
+ if (existing != null && (existing.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0) {
+ xform.addError("Error during @Lazy processing: invalid explicit getter '" + name + "' found", fieldNode);
+ }
+ addGeneratedMethod(declaringClass, name, visibility, type, params, ClassNode.EMPTY_ARRAY, body);
}
- private static void createSoft(FieldNode fieldNode, Expression initExpr) {
+ private static void createSoft(FieldNode fieldNode, Expression initExpr, ErrorCollecting xform) {
final ClassNode type = fieldNode.getType();
fieldNode.setType(SOFT_REF);
- createSoftGetter(fieldNode, initExpr, type);
+ createSoftGetter(fieldNode, initExpr, type, xform);
createSoftSetter(fieldNode, type);
}
- private static void createSoftGetter(FieldNode fieldNode, Expression initExpr, ClassNode type) {
+ private static void createSoftGetter(FieldNode fieldNode, Expression initExpr, ClassNode type, ErrorCollecting xform) {
final BlockStatement body = new BlockStatement();
final Expression fieldExpr = varX(fieldNode);
final Expression resExpr = localVarX("_result", type);
@@ -214,7 +229,7 @@ public class LazyASTTransformation extends AbstractASTTransformation {
} else {
body.addStatement(mainIf);
}
- addMethod(fieldNode, body, type);
+ addMethod(fieldNode, body, type, xform);
}
private static void createSoftSetter(FieldNode fieldNode, ClassNode type) {
diff --git a/src/test/org/codehaus/groovy/transform/LazyTransformTest.groovy b/src/test/org/codehaus/groovy/transform/LazyTransformTest.groovy
index 1c6fb96..32f9faa 100644
--- a/src/test/org/codehaus/groovy/transform/LazyTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/LazyTransformTest.groovy
@@ -164,6 +164,30 @@ class LazyTransformTest extends GroovyShellTestCase {
assert message.contains("You cannot lazily initialize 'foo' from the abstract class 'Foo'")
}
+ void testClassWithExplicitGetterForLazyFieldShouldNotCompile() {
+ def message = shouldFail {
+ new GroovyShell().run('''
+ class Animal {
+ @Lazy String name = { 'sloth' }()
+ String getName() {}
+ }
+ ''', 'dummyFileName', [])
+ }
+ assert message.contains("Error during @Lazy processing: invalid explicit getter 'getName' found")
+ }
+
+ void testClassWithExplicitSetterForLazyFieldShouldNotCompile() {
+ def message = shouldFail {
+ new GroovyShell().run('''
+ class Animal {
+ @Lazy String name = { 'sloth' }()
+ void setName(String name) {}
+ }
+ ''', 'dummyFileName', [])
+ }
+ assert message.contains("Error during @Lazy processing: invalid explicit setter 'setName' found")
+ }
+
void testSoft() {
def res = evaluate("""
class X {