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 2018/08/23 03:19:04 UTC
groovy git commit: GROOVY-8758: @WithReadLock in inner class of
@CompileStatic class causes java.lang.VerifyError (closes #787)
Repository: groovy
Updated Branches:
refs/heads/master e63fec79e -> 52f82765b
GROOVY-8758: @WithReadLock in inner class of @CompileStatic class causes java.lang.VerifyError (closes #787)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/52f82765
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/52f82765
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/52f82765
Branch: refs/heads/master
Commit: 52f82765b5e7a426aa67610cb2c30fac11025ed9
Parents: e63fec7
Author: Paul King <pa...@asert.com.au>
Authored: Tue Aug 21 15:22:21 2018 +1000
Committer: Paul King <pa...@asert.com.au>
Committed: Thu Aug 23 13:17:55 2018 +1000
----------------------------------------------------------------------
.../ReadWriteLockASTTransformation.java | 33 ++++----
.../groovy/transform/ReadWriteLockTest.groovy | 89 ++++++++++++--------
2 files changed, 71 insertions(+), 51 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/52f82765/src/main/java/org/codehaus/groovy/transform/ReadWriteLockASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/transform/ReadWriteLockASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/ReadWriteLockASTTransformation.java
index 52bc58c..7ef8778 100644
--- a/src/main/java/org/codehaus/groovy/transform/ReadWriteLockASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/ReadWriteLockASTTransformation.java
@@ -28,6 +28,7 @@ import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.ast.stmt.TryCatchStatement;
import org.codehaus.groovy.control.CompilePhase;
@@ -49,8 +50,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
* Any method annotated with {@code @}WithReadLock will obtain a read lock and release it in a finally block.<br>
* Any method annotated with {@code @}WithWriteLock will obtain a write lock and release it in a finally block.<br>
* For more information see {@link WithReadLock} and {@link WithWriteLock}
- *
- * @author Hamlet D'Arcy
*/
@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
public class ReadWriteLockASTTransformation extends AbstractASTTransformation {
@@ -81,19 +80,19 @@ public class ReadWriteLockASTTransformation extends AbstractASTTransformation {
if (parent instanceof MethodNode) {
MethodNode mNode = (MethodNode) parent;
ClassNode cNode = mNode.getDeclaringClass();
- String lockExpr = determineLock(value, cNode, mNode.isStatic(), myTypeName);
+ FieldNode lockExpr = determineLock(value, cNode, mNode.isStatic(), myTypeName);
if (lockExpr == null) return;
// get lock type
- final Expression lockType;
- if (isWriteLock) {
- lockType = callX(varX(lockExpr, LOCK_TYPE), "writeLock");
- } else {
- lockType = callX(varX(lockExpr, LOCK_TYPE), "readLock");
- }
+ final MethodCallExpression lockType = callX(varX(lockExpr), isWriteLock ? "writeLock" : "readLock");
+ lockType.setImplicitThis(false);
+
+ MethodCallExpression acquireLock = callX(lockType, "lock");
+ acquireLock.setImplicitThis(false);
+
+ MethodCallExpression releaseLock = callX(lockType, "unlock");
+ releaseLock.setImplicitThis(false);
- Expression acquireLock = callX(lockType, "lock");
- Expression releaseLock = callX(lockType, "unlock");
Statement originalCode = mNode.getCode();
mNode.setCode(block(
@@ -102,7 +101,7 @@ public class ReadWriteLockASTTransformation extends AbstractASTTransformation {
}
}
- private String determineLock(String value, ClassNode targetClass, boolean isStatic, String myTypeName) {
+ private FieldNode determineLock(String value, ClassNode targetClass, boolean isStatic, String myTypeName) {
if (value != null && value.length() > 0 && !value.equalsIgnoreCase(DEFAULT_INSTANCE_LOCKNAME)) {
FieldNode existingLockField = targetClass.getDeclaredField(value);
if (existingLockField == null) {
@@ -113,28 +112,28 @@ public class ReadWriteLockASTTransformation extends AbstractASTTransformation {
addError("Error during " + myTypeName + " processing: lock field with name '" + value + "' should " + (isStatic ? "" : "not ") + "be static", existingLockField);
return null;
}
- return value;
+ return existingLockField;
}
if (isStatic) {
FieldNode field = targetClass.getDeclaredField(DEFAULT_STATIC_LOCKNAME);
if (field == null) {
int visibility = ACC_PRIVATE | ACC_STATIC | ACC_FINAL;
- targetClass.addField(DEFAULT_STATIC_LOCKNAME, visibility, LOCK_TYPE, createLockObject());
+ field = targetClass.addField(DEFAULT_STATIC_LOCKNAME, visibility, LOCK_TYPE, createLockObject());
} else if (!field.isStatic()) {
addError("Error during " + myTypeName + " processing: " + DEFAULT_STATIC_LOCKNAME + " field must be static", field);
return null;
}
- return DEFAULT_STATIC_LOCKNAME;
+ return field;
}
FieldNode field = targetClass.getDeclaredField(DEFAULT_INSTANCE_LOCKNAME);
if (field == null) {
int visibility = ACC_PRIVATE | ACC_FINAL;
- targetClass.addField(DEFAULT_INSTANCE_LOCKNAME, visibility, LOCK_TYPE, createLockObject());
+ field = targetClass.addField(DEFAULT_INSTANCE_LOCKNAME, visibility, LOCK_TYPE, createLockObject());
} else if (field.isStatic()) {
addError("Error during " + myTypeName + " processing: " + DEFAULT_INSTANCE_LOCKNAME + " field must not be static", field);
return null;
}
- return DEFAULT_INSTANCE_LOCKNAME;
+ return field;
}
private static Expression createLockObject() {
http://git-wip-us.apache.org/repos/asf/groovy/blob/52f82765/src/test/groovy/transform/ReadWriteLockTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/transform/ReadWriteLockTest.groovy b/src/test/groovy/transform/ReadWriteLockTest.groovy
index 3609235..2944f8e 100644
--- a/src/test/groovy/transform/ReadWriteLockTest.groovy
+++ b/src/test/groovy/transform/ReadWriteLockTest.groovy
@@ -23,12 +23,10 @@ import java.lang.reflect.Modifier
/**
* Unit test for WithReadLock and WithWriteLock annotations.
- *
- * @author Hamlet D'Arcy
*/
class ReadWriteLockTest extends GroovyTestCase {
- public void testLockFieldDefaultsForReadLock() {
+ void testLockFieldDefaultsForReadLock() {
def tester = new GroovyClassLoader().parseClass('''
class MyClass {
@groovy.transform.WithReadLock
@@ -44,7 +42,7 @@ class ReadWriteLockTest extends GroovyTestCase {
assert field.type == ReentrantReadWriteLock
}
- public void testLockFieldDefaultsForWriteLock() {
+ void testLockFieldDefaultsForWriteLock() {
def tester = new GroovyClassLoader().parseClass('''
class MyClass {
@groovy.transform.WithWriteLock
@@ -60,7 +58,7 @@ class ReadWriteLockTest extends GroovyTestCase {
assert field.type == ReentrantReadWriteLock
}
- public void testLockFieldDefaultsForStaticReadLock() {
+ void testLockFieldDefaultsForStaticReadLock() {
def tester = new GroovyClassLoader().parseClass('''
class MyClass {
@groovy.transform.WithReadLock
@@ -76,7 +74,7 @@ class ReadWriteLockTest extends GroovyTestCase {
assert field.type == ReentrantReadWriteLock
}
- public void testLockFieldDefaultsForStaticWriteLock() {
+ void testLockFieldDefaultsForStaticWriteLock() {
def tester = new GroovyClassLoader().parseClass('''
class MyClass {
@groovy.transform.WithWriteLock
@@ -92,7 +90,7 @@ class ReadWriteLockTest extends GroovyTestCase {
assert field.type == ReentrantReadWriteLock
}
- public void testLocking() {
+ void testLocking() {
def tester = new MyClass()
tester.readerMethod1()
@@ -111,7 +109,7 @@ class ReadWriteLockTest extends GroovyTestCase {
tester.readerMethod1()
}
- public void testStaticLocking() {
+ void testStaticLocking() {
def tester = new MyClass()
tester.staticReaderMethod1()
@@ -130,7 +128,7 @@ class ReadWriteLockTest extends GroovyTestCase {
tester.staticReaderMethod1()
}
- public void testDeadlockingDoesNotOccur() {
+ void testDeadlockingDoesNotOccur() {
def tester = new MyClass()
// this tests for deadlocks from not releaseing in finally block
@@ -145,7 +143,7 @@ class ReadWriteLockTest extends GroovyTestCase {
shouldFail { tester.namedReaderMethod1() }
}
- public void testCompileError_NamingConflict() {
+ void testCompileError_NamingConflict() {
shouldFail("lock field with name 'unknown' not found") {
'''
class MyClass {
@@ -175,6 +173,29 @@ class ReadWriteLockTest extends GroovyTestCase {
}
}
+ // GROOVY-8758
+ void testShouldBeAllowedInInnerClassWithCompileStatic() {
+ assertScript '''
+ import groovy.transform.*
+
+ @CompileStatic
+ class A {
+ private class B {
+ @WithReadLock
+ int getFoo() { 0 }
+ }
+
+ private B b
+
+ A() {
+ b = new B()
+ }
+ }
+
+ def a = new A()
+ '''
+ }
+
def shouldFail(String expectedText, Closure c) {
String script = c()
try {
@@ -198,54 +219,54 @@ class MyClass {
def staticWriterMethod2Called = false
def myLock = new ReentrantReadWriteLock()
- @groovy.transform.WithReadLock
- public void readerMethod1() {
+ @WithReadLock
+ void readerMethod1() {
readerMethod1Called = true
}
- @groovy.transform.WithReadLock
- public void readerMethod2() {
+ @WithReadLock
+ void readerMethod2() {
readerMethod2Called = true
}
- @groovy.transform.WithWriteLock
- public void writerMethod1() {
+ @WithWriteLock
+ void writerMethod1() {
writerMethod1Called = true
}
- @groovy.transform.WithWriteLock
- public void writerMethod2() {
+ @WithWriteLock
+ void writerMethod2() {
writerMethod2Called = true
}
- @groovy.transform.WithReadLock('myLock')
- public void namedReaderMethod1() {
+ @WithReadLock('myLock')
+ void namedReaderMethod1() {
throw new Exception()
}
- @groovy.transform.WithReadLock('myLock')
- public void namedReaderMethod2() {
+ @WithReadLock('myLock')
+ void namedReaderMethod2() {
throw new Exception()
}
- @groovy.transform.WithWriteLock('myLock')
- public void namedWriterMethod1() {
+ @WithWriteLock('myLock')
+ void namedWriterMethod1() {
throw new Exception()
}
- @groovy.transform.WithWriteLock('myLock')
- public void namedWriterMethod2() {
+ @WithWriteLock('myLock')
+ void namedWriterMethod2() {
throw new Exception()
}
- @groovy.transform.WithReadLock
- public void staticReaderMethod1() {
+ @WithReadLock
+ void staticReaderMethod1() {
staticReaderMethod1Called = true
}
- @groovy.transform.WithReadLock
- public void staticReaderMethod2() {
+ @WithReadLock
+ void staticReaderMethod2() {
staticReaderMethod2Called = true
}
- @groovy.transform.WithWriteLock
- public void staticWriterMethod1() {
+ @WithWriteLock
+ void staticWriterMethod1() {
staticWriterMethod1Called = true
}
- @groovy.transform.WithWriteLock
- public void staticWriterMethod2() {
+ @WithWriteLock
+ void staticWriterMethod2() {
staticWriterMethod2Called = true
}
}