This is an automated email from the ASF dual-hosted git repository.
emilles 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 642a7532d7 GROOVY-10687: SC: replace access bridge methods with direct
method calls
642a7532d7 is described below
commit 642a7532d71a7bce3eba411c7fa865c57195ccca
Author: Eric Milles <[email protected]>
AuthorDate: Tue Sep 24 14:12:57 2024 -0500
GROOVY-10687: SC: replace access bridge methods with direct method calls
---
.../groovy/classgen/asm/InvocationWriter.java | 7 +-
.../classgen/asm/sc/StaticInvocationWriter.java | 136 ++++++---------------
.../transform/sc/StaticCompilationVisitor.java | 18 ++-
.../transform/stc/StaticTypeCheckingVisitor.java | 17 +--
.../classgen/asm/sc/BugsStaticCompileTest.groovy | 2 +-
.../asm/sc/MethodCallsStaticCompilationTest.groovy | 1 +
.../groovy/classgen/asm/sc/bugs/Groovy7276.groovy | 37 ++++--
7 files changed, 88 insertions(+), 130 deletions(-)
diff --git
a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
index 89eac79c99..7d5141f870 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
@@ -331,11 +331,8 @@ public class InvocationWriter {
}
}
}
- if (containsSpreadExpression) return false;
- if (origin instanceof MethodCallExpression) {
- MethodCallExpression mce = (MethodCallExpression) origin;
- if (mce.getMethodTarget() != null)
- return writeDirectMethodCall(mce.getMethodTarget(),
implicitThis, receiver, makeArgumentList(arguments));
+ if (!containsSpreadExpression && origin instanceof
MethodCallExpression) {
+ return writeDirectMethodCall(((MethodCallExpression)
origin).getMethodTarget(), implicitThis, receiver, makeArgumentList(arguments));
}
return false;
}
diff --git
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
index e9198ca39e..cffa427daa 100644
---
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
+++
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
@@ -54,7 +54,6 @@ import org.codehaus.groovy.classgen.asm.OperandStack;
import org.codehaus.groovy.classgen.asm.TypeChooser;
import org.codehaus.groovy.classgen.asm.VariableSlotLoader;
import org.codehaus.groovy.classgen.asm.WriterController;
-import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.syntax.SyntaxException;
import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
import org.codehaus.groovy.transform.sc.StaticCompilationVisitor;
@@ -75,9 +74,9 @@ import java.util.stream.Collectors;
import static org.apache.groovy.ast.tools.ClassNodeUtils.formatTypeName;
import static org.apache.groovy.ast.tools.ClassNodeUtils.isSubtype;
-import static org.apache.groovy.ast.tools.ClassNodeUtils.samePackageName;
import static org.apache.groovy.ast.tools.ExpressionUtils.isNullConstant;
import static org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression;
+import static org.apache.groovy.ast.tools.ExpressionUtils.isThisExpression;
import static org.apache.groovy.ast.tools.ExpressionUtils.isThisOrSuper;
import static org.codehaus.groovy.ast.ClassHelper.isGStringType;
import static org.codehaus.groovy.ast.ClassHelper.isGeneratedFunction;
@@ -88,8 +87,8 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
import static org.codehaus.groovy.ast.tools.GeneralUtils.attrX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage;
import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
@@ -105,24 +104,6 @@ import static org.objectweb.asm.Opcodes.INVOKESTATIC;
public class StaticInvocationWriter extends InvocationWriter {
- private static final ClassNode INVOKERHELPER_CLASSNODE =
ClassHelper.make(InvokerHelper.class);
- private static final MethodNode INVOKERHELPER_INVOKEMETHOD =
INVOKERHELPER_CLASSNODE.getMethod(
- "invokeMethodSafe",
- new Parameter[]{
- new Parameter(ClassHelper.OBJECT_TYPE, "object"),
- new Parameter(ClassHelper.STRING_TYPE, "name"),
- new Parameter(ClassHelper.OBJECT_TYPE, "args")
- }
- );
- private static final MethodNode INVOKERHELPER_INVOKESTATICMETHOD =
INVOKERHELPER_CLASSNODE.getMethod(
- "invokeStaticMethod",
- new Parameter[]{
- new Parameter(ClassHelper.CLASS_Type, "clazz"),
- new Parameter(ClassHelper.STRING_TYPE, "name"),
- new Parameter(ClassHelper.OBJECT_TYPE, "args")
- }
- );
-
private final AtomicInteger labelCounter = new AtomicInteger();
private MethodCallExpression currentCall;
@@ -166,7 +147,7 @@ public class StaticInvocationWriter extends
InvocationWriter {
MethodNode bridge = null;
if (call.getNodeMetaData(StaticTypesMarker.PV_METHODS_ACCESS)
!= null) {
Map<MethodNode, MethodNode> bridgeMethods =
declaringClass.getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_BRIDGE_METHODS);
- bridge = bridgeMethods != null ? bridgeMethods.get(cn) :
null;
+ if (bridgeMethods != null) bridge = bridgeMethods.get(cn);
}
if (bridge instanceof ConstructorNode) {
ArgumentListExpression newArgs = args(nullX());
@@ -293,14 +274,15 @@ public class StaticInvocationWriter extends
InvocationWriter {
protected boolean writeDirectMethodCall(final MethodNode target, final
boolean implicitThis, final Expression receiver, final TupleExpression args) {
if (target == null) return false;
- ClassNode classNode = controller.getClassNode();
+ ClassNode enclosingClass = controller.getClassNode();
+ ClassNode declaringClass = target.getDeclaringClass();
if (target instanceof ExtensionMethodNode) {
ExtensionMethodNode emn = (ExtensionMethodNode) target;
MethodVisitor mv = controller.getMethodVisitor();
- MethodNode node = emn.getExtensionMethodNode();
- Parameter[] parameters = node.getParameters();
- ClassNode returnType = node.getReturnType();
+ MethodNode mn = emn.getExtensionMethodNode();
+ Parameter[] parameters = mn.getParameters();
+ ClassNode returnType = mn.getReturnType();
List<Expression> argumentList = new ArrayList<>();
if (emn.isStaticExtension()) {
@@ -308,12 +290,12 @@ public class StaticInvocationWriter extends
InvocationWriter {
} else if (!isThisOrSuper(receiver) ||
!controller.isInGeneratedFunction()) {
argumentList.add(receiver);
} else {
- argumentList.add(thisObjectExpression(classNode,
target.getDeclaringClass()));
+ argumentList.add(thisObjectExpression(enclosingClass,
declaringClass));
}
argumentList.addAll(args.getExpressions());
loadArguments(argumentList, parameters);
- String owner =
BytecodeHelper.getClassInternalName(node.getDeclaringClass());
+ String owner =
BytecodeHelper.getClassInternalName(mn.getDeclaringClass());
String desc = BytecodeHelper.getMethodDescriptor(returnType,
parameters);
mv.visitMethodInsn(INVOKESTATIC, owner, target.getName(), desc,
false);
controller.getOperandStack().remove(argumentList.size());
@@ -326,65 +308,42 @@ public class StaticInvocationWriter extends
InvocationWriter {
return true;
}
- if (target == StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS) {
- // wrap arguments into an array
- Expression arr = new ArrayExpression(ClassHelper.OBJECT_TYPE,
args.getExpressions());
- return super.writeDirectMethodCall(target, implicitThis, receiver,
args(arr));
+ if (target == StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS) { // wrap
arguments in an array
+ Expression array = new ArrayExpression(ClassHelper.OBJECT_TYPE,
args.getExpressions());
+ return super.writeDirectMethodCall(target, implicitThis, receiver,
args(array));
}
- if (!target.isPublic()
- && controller.isInGeneratedFunction()
- && target.getDeclaringClass() != classNode) {
- if (!tryBridgeMethod(target, receiver, implicitThis, args,
classNode)) {
- // replace call with an invoker helper call
- MethodNode methodNode = target.isStatic() ?
INVOKERHELPER_INVOKESTATICMETHOD : INVOKERHELPER_INVOKEMETHOD;
- MethodCallExpression mce = callX(
- classX(INVOKERHELPER_CLASSNODE),
- methodNode.getName(),
- args(
- target.isStatic() ?
classX(target.getDeclaringClass()) : receiver,
- constX(target.getName()),
- new ArrayExpression(ClassHelper.OBJECT_TYPE,
args.getExpressions())
- )
- );
- mce.setMethodTarget(methodNode);
- mce.visit(controller.getAcg());
- }
- return true;
- }
-
- if (target.isPrivate() && tryPrivateMethod(target, implicitThis,
receiver, args, classNode)) {
- return true;
- }
+ ClassNode receiverType = receiver == null ? ClassHelper.OBJECT_TYPE :
controller.getTypeChooser().resolveType(receiver, controller.getThisType());
- Expression fixedReceiver = receiver;
- boolean fixedImplicitThis = implicitThis;
- if (target.isPackageScope()) { // GROOVY-11373
- if (!samePackageName(target.getDeclaringClass(), classNode)) {
- writeMethodAccessError(target, receiver != null ? receiver :
args);
- }
- } else if (target.isProtected()) {
- ClassNode node = receiver == null ? ClassHelper.OBJECT_TYPE :
controller.getTypeChooser().resolveType(receiver, classNode);
- if (!implicitThis && !isThisOrSuper(receiver) &&
!samePackageName(node, classNode)
- &&
StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node,
target.getDeclaringClass())) {
- writeMethodAccessError(target, receiver != null ? receiver :
args);
- } else if (!isSubtype(target.getDeclaringClass(), node) &&
tryBridgeMethod(target, receiver, implicitThis, args, classNode)) {
- return true;
+ if
(AsmClassGenerator.isMemberDirectlyAccessible(target.getModifiers(),
declaringClass, enclosingClass)
+ && !(target.isProtected() && !inSamePackage(declaringClass,
enclosingClass) && !isSubtype(receiverType, enclosingClass))) { // GROOVY-7325
+ boolean isThisImplicit = implicitThis;
+ Expression theReceiver = receiver;
+ if (implicitThis && isThisExpression(receiver)
+ && !isSubtype(declaringClass, enclosingClass)) {
+ if (target.isStatic()) {
+ theReceiver = classX(declaringClass);
+ } else if (!controller.isInGeneratedFunction()) {
+ theReceiver = propX(classX(declaringClass), "this");
+ } else {
+ theReceiver = thisObjectExpression(enclosingClass,
declaringClass);
+ }
+ if (!(theReceiver instanceof VariableExpression))
isThisImplicit = false;
+ theReceiver.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE,
declaringClass);
}
- } else if (target.isPublic() && receiver != null) {
- if (implicitThis
- && controller.isInGeneratedFunction()
- && !isSubtype(target.getDeclaringClass(), classNode)) {
- fixedReceiver = thisObjectExpression(classNode,
target.getDeclaringClass());
- if (!(fixedReceiver instanceof VariableExpression))
fixedImplicitThis = false;
+ if (theReceiver != null && !isSuperExpression(receiver) &&
!isClassWithSuper(receiver)
+ &&
currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER) == null) {
+ // call CHECKCAST in order to avoid calls to castToType (aka
dynamic behaviour)
+ theReceiver = new CheckcastReceiverExpression(theReceiver,
target);
}
+ return super.writeDirectMethodCall(target, isThisImplicit,
theReceiver, args);
+
+ } else if (tryBridgeMethod(target, receiver, implicitThis, args,
enclosingClass)) {
+ return true;
+ } else {
+ writeMethodAccessError(target, receiver != null ? receiver : args);
+ return false;
}
- if (receiver != null && !isSuperExpression(receiver) &&
!isClassWithSuper(receiver)) {
- // in order to avoid calls to castToType, which is the dynamic
behaviour, make sure that we call CHECKCAST instead then replace the top
operand type
- if
(currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER) == null)
fixedReceiver = new CheckcastReceiverExpression(fixedReceiver, target);
- return super.writeDirectMethodCall(target, fixedImplicitThis,
fixedReceiver, args);
- }
- return super.writeDirectMethodCall(target, implicitThis, receiver,
args);
}
private void writeMethodAccessError(final MethodNode target, final
Expression origin) {
@@ -405,21 +364,6 @@ public class StaticInvocationWriter extends
InvocationWriter {
return false;
}
- private boolean tryPrivateMethod(final MethodNode target, final boolean
implicitThis, final Expression receiver, final TupleExpression args, final
ClassNode classNode) {
- ClassNode declaringClass = target.getDeclaringClass();
- if ((isPrivateBridgeMethodsCallAllowed(declaringClass, classNode) ||
isPrivateBridgeMethodsCallAllowed(classNode, declaringClass))
- &&
declaringClass.getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_BRIDGE_METHODS)
!= null
- && !declaringClass.equals(classNode)) {
- if (tryBridgeMethod(target, receiver, implicitThis, args,
classNode)) {
- return true;
- }
- }
- if (declaringClass != classNode) {
- writeMethodAccessError(target, receiver);
- }
- return false;
- }
-
protected static boolean isPrivateBridgeMethodsCallAllowed(final ClassNode
receiver, final ClassNode caller) {
if (receiver == null) return false;
if (receiver.redirect() == caller) return true;
diff --git
a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
index 462e49c3d0..5b05fcc0ba 100644
---
a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
@@ -483,11 +483,9 @@ public class StaticCompilationVisitor extends
StaticTypeCheckingVisitor {
}
/**
- * Adds "bridge" methods for private methods of an inner/outer class so
that
- * the outer class is capable of calling them. It does basically the same
- * job as access$000 like methods in Java.
- *
- * @param node an inner/outer class node for which to generate bridge
methods
+ * Adds bridge methods for private or protected methods of a class so that
+ * any nestmate is capable of calling them. It does basically the same job
+ * as access$000 like methods in Java.
*/
private static void addPrivateBridgeMethods(final ClassNode node) {
Set<ASTNode> accessedMethods = node.getNodeMetaData(PV_METHODS_ACCESS);
@@ -496,20 +494,19 @@ public class StaticCompilationVisitor extends
StaticTypeCheckingVisitor {
methods.addAll(node.getDeclaredConstructors());
Map<MethodNode, MethodNode> privateBridgeMethods =
node.getNodeMetaData(PRIVATE_BRIDGE_METHODS);
if (privateBridgeMethods != null) {
- // private bridge methods already added
+ // bridge methods already added
return;
}
privateBridgeMethods = new HashMap<>();
int i = -1;
- final int access = ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC;
for (MethodNode method : methods) {
if (accessedMethods.contains(method)) {
- List<String> methodSpecificGenerics =
methodSpecificGenerics(method);
i += 1;
ClassNode declaringClass = method.getDeclaringClass();
Map<String, ClassNode> genericsSpec = createGenericsSpec(node);
genericsSpec = addMethodGenerics(method, genericsSpec);
extractSuperClassGenerics(node, declaringClass, genericsSpec);
+ List<String> methodSpecificGenerics =
methodSpecificGenerics(method);
Parameter[] methodParameters = method.getParameters();
Parameter[] newParams = new Parameter[methodParameters.length
+ 1];
for (int j = 1; j < newParams.length; j += 1) {
@@ -520,7 +517,7 @@ public class StaticCompilationVisitor extends
StaticTypeCheckingVisitor {
);
}
Expression arguments;
- if (method.getParameters() == null ||
method.getParameters().length == 0) {
+ if (methodParameters.length == 0) {
arguments = ArgumentListExpression.EMPTY_ARGUMENTS;
} else {
List<Expression> args = new ArrayList<>();
@@ -553,7 +550,8 @@ public class StaticCompilationVisitor extends
StaticTypeCheckingVisitor {
ExpressionStatement body = new ExpressionStatement(call);
bridge = node.addMethod(
- "access$" + i, access,
+ "access$" + i,
+ ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
correctToGenericsSpecRecurse(genericsSpec,
method.getReturnType(), methodSpecificGenerics),
newParams,
method.getExceptions(),
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 87ed4596a2..9bec90bd6e 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -579,11 +579,6 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
}
- private static void addPrivateFieldOrMethodAccess(final Expression source,
final ClassNode cn, final StaticTypesMarker key, final ASTNode accessedMember) {
- cn.getNodeMetaData(key, x -> new
LinkedHashSet<>()).add(accessedMember);
- source.putNodeMetaData(key, accessedMember);
- }
-
/**
* Checks for private field access from closure or nestmate.
*/
@@ -604,17 +599,17 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
ClassNode declaringClass = mn.getDeclaringClass();
ClassNode enclosingClass = typeCheckingContext.getEnclosingClassNode();
if (declaringClass != enclosingClass ||
typeCheckingContext.getEnclosingClosure() != null) {
- if (mn.isPrivate()
- && declaringClass.getModule() ==
enclosingClass.getModule()) {
- addPrivateFieldOrMethodAccess(source, declaringClass,
PV_METHODS_ACCESS, mn);
- } else if (mn.isProtected()
- && !inSamePackage(enclosingClass, declaringClass)
+ if (mn.isPrivate() && getNestHost(declaringClass) ==
getNestHost(enclosingClass)) {
+ if (mn.isConstructor())
declaringClass.getNodeMetaData(PV_METHODS_ACCESS, k -> new
LinkedHashSet<MethodNode>()).add(mn);
+ source.putNodeMetaData(PV_METHODS_ACCESS, mn);
+ } else if (mn.isProtected() && !inSamePackage(enclosingClass,
declaringClass)
&& (!implementsInterfaceOrIsSubclassOf(enclosingClass,
declaringClass)
||
typeCheckingContext.getEnclosingClosure() != null)) {
ClassNode cn = enclosingClass;
do {
if (implementsInterfaceOrIsSubclassOf(cn, declaringClass))
{
- addPrivateFieldOrMethodAccess(source, cn,
PV_METHODS_ACCESS, mn);
+ cn.getNodeMetaData(PV_METHODS_ACCESS, k -> new
LinkedHashSet<MethodNode>()).add(mn);
+ source.putNodeMetaData(PV_METHODS_ACCESS, mn);
break;
}
} while ((cn = cn.getOuterClass()) != null);
diff --git
a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
index 4e99b8c489..0c4b08bb26 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
@@ -680,7 +680,7 @@ final class BugsStaticCompileTest extends BugsSTCTest
implements StaticCompilati
class Bottom extends Top {
private int bar = 666
private class InnerBottom {
- int bar() { bar } // name clash for fpaccess$0
+ int bar() { bar }
}
}
new Bottom()
diff --git
a/src/test/org/codehaus/groovy/classgen/asm/sc/MethodCallsStaticCompilationTest.groovy
b/src/test/org/codehaus/groovy/classgen/asm/sc/MethodCallsStaticCompilationTest.groovy
index e80c6586e3..18c8fac981 100644
---
a/src/test/org/codehaus/groovy/classgen/asm/sc/MethodCallsStaticCompilationTest.groovy
+++
b/src/test/org/codehaus/groovy/classgen/asm/sc/MethodCallsStaticCompilationTest.groovy
@@ -53,5 +53,6 @@ public class MethodCallsStaticCompilationTest extends
MethodCallsSTCTest impleme
}
assert new Foo().a() == 123
'''
+ assert astTrees['Foo$Bar$Baz'][1].contains('INVOKEVIRTUAL Foo.d ()I')
}
}
diff --git
a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276.groovy
b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276.groovy
index e2d46247c1..bb11fb4892 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276.groovy
@@ -23,7 +23,7 @@ import
org.codehaus.groovy.classgen.asm.sc.StaticCompilationTestSupport
final class Groovy7276 extends StaticTypeCheckingTestCase implements
StaticCompilationTestSupport {
- void testShouldGoThroughPrivateBridgeMethod1() {
+ void testNoPrivateAccessMethod1() {
for (it in ['i', 'i++']) {
assertScript """
class Foo {
@@ -32,11 +32,14 @@ final class Groovy7276 extends StaticTypeCheckingTestCase
implements StaticCompi
}
assert new Foo().m() == 1
"""
+ String closure = astTrees['Foo$_m_closure1'][1]
+ assert closure.contains('GETFIELD Foo.i')
+ assert !closure.contains('pfaccess$')
}
}
// GROOVY-7304
- void testShouldGoThroughPrivateBridgeMethod2() {
+ void testNoPrivateAccessMethod2() {
for (it in ['i', 'i++']) {
assertScript """
class Foo {
@@ -47,10 +50,13 @@ final class Groovy7276 extends StaticTypeCheckingTestCase
implements StaticCompi
}
assert new Bar().m() == 1
"""
+ String closure = astTrees['Foo$_m_closure1'][1]
+ assert closure.contains('GETFIELD Foo.i')
+ assert !closure.contains('pfaccess$')
}
}
- void testShouldGoThroughPrivateBridgeMethod3() {
+ void testNoPrivateAccessMethod3() {
for (it in ['++i', 'i+=1', 'i=i+1']) {
assertScript """
class Foo {
@@ -59,11 +65,14 @@ final class Groovy7276 extends StaticTypeCheckingTestCase
implements StaticCompi
}
assert new Foo().m() == 2
"""
+ String closure = astTrees['Foo$_m_closure1'][1]
+ assert closure.contains('GETFIELD Foo.i')
+ assert !closure.contains('pfaccess$')
}
}
// GROOVY-7304
- void testShouldGoThroughPrivateBridgeMethod4() {
+ void testNoPrivateAccessMethod4() {
for (it in ['++i', 'i+=1', 'i=i+1']) {
assertScript """
class Foo {
@@ -74,10 +83,14 @@ final class Groovy7276 extends StaticTypeCheckingTestCase
implements StaticCompi
}
assert new Bar().m() == 2
"""
+ String closure = astTrees['Foo$_m_closure1'][1]
+ assert closure.contains('GETFIELD Foo.i')
+ assert !closure.contains('pfaccess$')
}
}
- void testShouldGoThroughPrivateBridgeMethod5() {
+ // GROOVY-10687
+ void testNoPrivateAccessMethod5() {
assertScript '''
class Foo {
private int i = 1
@@ -86,9 +99,13 @@ final class Groovy7276 extends StaticTypeCheckingTestCase
implements StaticCompi
}
assert new Foo().m() == 1
'''
+ String closure = astTrees['Foo$_m_closure1'][1]
+ assert closure.contains('INVOKEVIRTUAL Foo.pvI ()I')
+ assert !closure.contains('access$')
}
- void testShouldGoThroughPrivateBridgeMethod6() {
+ // GROOVY-10687
+ void testNoPrivateAccessMethod6() {
assertScript '''
class Foo {
private int i = 1
@@ -99,15 +116,19 @@ final class Groovy7276 extends StaticTypeCheckingTestCase
implements StaticCompi
}
assert new Bar().m() == 1
'''
+ String closure = astTrees['Foo$_m_closure1'][1]
+ assert closure.contains('INVOKEVIRTUAL Foo.pvI ()I')
+ assert !closure.contains('access$')
}
+ // GROOVY-10687
void testPrivateAccessInInnerClass() {
assertScript '''
class Outer {
private static class Inner {
private Set<String> variablesToCheck = []
private void checkAssertions(String name) {
- Runnable r = {
+ Runnable r = { ->
def candidates = variablesToCheck.findAll { it ==
name }
}
r.run()
@@ -119,5 +140,7 @@ final class Groovy7276 extends StaticTypeCheckingTestCase
implements StaticCompi
}
Outer.test()
'''
+ assert astTrees['Outer'][1].contains('INVOKEVIRTUAL
Outer$Inner.checkAssertions (Ljava/lang/String;)V')
+ assert
astTrees['Outer$Inner$_checkAssertions_closure1'][1].contains('GETFIELD
Outer$Inner.variablesToCheck')
}
}