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 b7711d8511 GROOVY-11611: outer class super method invocation
b7711d8511 is described below
commit b7711d8511da7d9eb55af7a4a9a66e736cc8b914
Author: Eric Milles <[email protected]>
AuthorDate: Tue Apr 15 08:15:55 2025 -0500
GROOVY-11611: outer class super method invocation
---
.../groovy/classgen/AsmClassGenerator.java | 11 +--
.../groovy/classgen/asm/InvocationWriter.java | 14 +++-
.../classgen/asm/indy/InvokeDynamicWriter.java | 23 +++---
.../groovy/gls/innerClass/InnerClassTest.groovy | 24 ++++++
.../ginq/provider/collection/GinqAstWalker.groovy | 88 +++++++++++-----------
5 files changed, 96 insertions(+), 64 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 9bd884ca42..10564ecfcc 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -1122,11 +1122,12 @@ public class AsmClassGenerator extends ClassGenerator {
String propertyName = pexp.getPropertyAsString();
Expression objectExpression = pexp.getObjectExpression();
- if (objectExpression instanceof ClassExpression &&
"this".equals(propertyName)) {
- // we have something like A.B.this, and need to make it
- // into this.this$0.this$0, where this.this$0 returns
- // A.B and this.this$0.this$0 return A.
- ClassNode type = objectExpression.getType();
+ ClassNode type = objectExpression.getType();
+ if (objectExpression instanceof ClassExpression && !type.isInterface()
+ && ("this".equals(propertyName) ||
"super".equals(propertyName))) {
+ // we have something like A.B.this and need to make it
+ // into this.this$0.this$0, where this.this$0 produces
+ // A.B and this.this$0.this$0 produces A.
if (controller.getCompileStack().isInSpecialConstructorCall() &&
type.equals(classNode.getOuterClass())) {
// Outer.this in a special constructor call
ConstructorNode ctor = controller.getConstructorNode();
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 d5aaa39723..32d1981085 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
@@ -248,7 +248,7 @@ public class InvocationWriter {
return true;
}
- private boolean callSuperDefault(ClassNode enclosingClass, MethodNode
target, Expression receiver) {
+ private boolean callSuperDefault(final ClassNode enclosingClass, final
MethodNode target, final Expression receiver) {
ClassNode declaringClass = target.getDeclaringClass();
if (declaringClass.isInterface() &&
enclosingClass.implementsInterface(declaringClass)) {
return isClassWithSuper(receiver);
@@ -256,7 +256,7 @@ public class InvocationWriter {
return false;
}
- private boolean isClassWithSuper(Expression exp) {
+ private boolean isClassWithSuper(final Expression exp) {
if (exp instanceof PropertyExpression) {
PropertyExpression pexp = (PropertyExpression) exp;
return pexp.getObjectExpression() instanceof ClassExpression &&
"super".equals(pexp.getPropertyAsString());
@@ -264,6 +264,14 @@ public class InvocationWriter {
return false;
}
+ private boolean isOuterClassSuper(final Expression exp) {
+ if (isClassWithSuper(exp)) {
+ PropertyExpression pexp = (PropertyExpression) exp;
+ return !pexp.getObjectExpression().getType().isInterface();
+ }
+ return false;
+ }
+
/**
* Supplements {@link
org.apache.groovy.ast.tools.ExpressionUtils#isThisExpression isThisExpression}
* with the ability to see into {@code CheckcastReceiverExpression}.
@@ -481,7 +489,7 @@ public class InvocationWriter {
if (isFunctionalInterface(type)) call =
transformToRealMethodCall(call, type);
}
MethodCallerMultiAdapter adapter = invokeMethod;
- if (isSuperExpression(receiver)) {
+ if (isSuperExpression(receiver) || isOuterClassSuper(receiver)) { //
GROOVY-11611
adapter = invokeMethodOnSuper;
} else if (isThisExpression(receiver)) {
adapter = invokeMethodOnCurrent;
diff --git
a/src/main/java/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
b/src/main/java/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
index 4316ddc5a7..0e8245ac5c 100644
---
a/src/main/java/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
+++
b/src/main/java/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
@@ -132,7 +132,7 @@ public class InvokeDynamicWriter extends InvocationWriter {
private void makeIndyCall(final MethodCallerMultiAdapter adapter, final
Expression origReceiver, final boolean implicitThis, final boolean safe, final
String methodName, final Expression arguments) {
OperandStack operandStack = controller.getOperandStack();
- Expression receiver = correctReceiverForInterfaceCall(origReceiver,
operandStack);
+ Expression receiver = correctReceiverForInterfaceCall(origReceiver);
StringBuilder sig = new StringBuilder(prepareIndyCall(receiver,
implicitThis));
Label end = null;
@@ -167,7 +167,6 @@ public class InvokeDynamicWriter extends InvocationWriter {
String callSiteName = METHOD.getCallSiteName();
if (adapter == null) callSiteName = INIT.getCallSiteName();
- // receiver != origReceiver interface default method call
if (receiver != origReceiver) callSiteName =
INTERFACE.getCallSiteName();
int flags = getMethodCallFlags(adapter, false,
containsSpreadExpression);
@@ -177,19 +176,19 @@ public class InvokeDynamicWriter extends InvocationWriter
{
if (end != null) controller.getMethodVisitor().visitLabel(end);
}
- private Expression correctReceiverForInterfaceCall(Expression exp,
OperandStack operandStack) {
- if (exp instanceof PropertyExpression) {
- PropertyExpression pexp = (PropertyExpression) exp;
- if (pexp.getObjectExpression() instanceof ClassExpression &&
"super".equals(pexp.getPropertyAsString())) {
- return bytecodeX(pexp.getObjectExpression().getType(), mv ->
mv.visitIntInsn(Opcodes.ALOAD, 0));
- } else if (pexp.getObjectExpression() instanceof ClassExpression
&& "this".equals(pexp.getPropertyAsString())) {
- ClassExpression ce = (ClassExpression)
pexp.getObjectExpression();
- if (ce.getType().isInterface()) {
- return bytecodeX(pexp.getObjectExpression().getType(), mv
-> mv.visitIntInsn(Opcodes.ALOAD, 0));
+ private Expression correctReceiverForInterfaceCall(final Expression
receiver) {
+ if (receiver instanceof PropertyExpression) {
+ PropertyExpression pexp = (PropertyExpression) receiver;
+ if (pexp.getObjectExpression() instanceof ClassExpression
+ && pexp.getProperty() instanceof ConstantExpression) {
+ String name = pexp.getProperty().getText();
+ ClassNode type = pexp.getObjectExpression().getType();
+ if ((name.equals("this") || name.equals("super")) &&
type.isInterface()) {
+ return bytecodeX(type, mv ->
mv.visitIntInsn(Opcodes.ALOAD, 0)); // load this with type
}
}
}
- return exp;
+ return receiver;
}
private static int getMethodCallFlags(final MethodCallerMultiAdapter
adapter, final boolean safe, final boolean spread) {
diff --git a/src/test/groovy/gls/innerClass/InnerClassTest.groovy
b/src/test/groovy/gls/innerClass/InnerClassTest.groovy
index 0d72798d9b..d834cb11e3 100644
--- a/src/test/groovy/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/groovy/gls/innerClass/InnerClassTest.groovy
@@ -1272,6 +1272,30 @@ final class InnerClassTest {
'''
}
+ // GROOVY-11611
+ @Test
+ void testUsageOfOuterMethodOverridden3() {
+ assertScript '''
+ class C {
+ String value() { 'C' }
+ static class D extends C {
+ @Override
+ String value() {
+ super.value() + 'D'
+ }
+ final class B {
+ def m() {
+ 'B' + D.super.value()
+ }
+ }
+ }
+ }
+ def d = new C.D()
+ def b = new C.D.B(d)
+ assert b.m() == 'BC'
+ '''
+ }
+
@Test
void testUsageOfOuterType() {
assertScript '''
diff --git
a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
index ce13e92b6c..a658b96ac6 100644
---
a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
+++
b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
@@ -18,7 +18,6 @@
*/
package org.apache.groovy.ginq.provider.collection
-import groovy.transform.CompileStatic
import org.apache.groovy.ginq.GinqGroovyMethods
import org.apache.groovy.ginq.dsl.GinqAstBaseVisitor
import org.apache.groovy.ginq.dsl.GinqAstBuilder
@@ -107,7 +106,6 @@ import static
org.codehaus.groovy.ast.tools.GeneralUtils.varX
*
* @since 4.0.0
*/
-@CompileStatic
class GinqAstWalker implements GinqAstVisitor<Expression>,
SyntaxErrorReportable {
GinqAstWalker(SourceUnit sourceUnit) {
@@ -129,12 +127,12 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
DataSourceExpression resultDataSourceExpression
MethodCallExpression resultMethodCallReceiver
- FromExpression fromExpression = currentGinqExpression.fromExpression
+ FromExpression fromExpression =
getCurrentGinqExpression().fromExpression
resultDataSourceExpression = fromExpression
MethodCallExpression fromMethodCallExpression =
visitFromExpression(fromExpression)
resultMethodCallReceiver = fromMethodCallExpression
- for (JoinExpression joinExpression :
currentGinqExpression.joinExpressionList) {
+ for (JoinExpression joinExpression :
getCurrentGinqExpression().joinExpressionList) {
joinExpression.putNodeMetaData(__METHOD_CALL_RECEIVER,
resultMethodCallReceiver)
joinExpression.dataSourceExpression = resultDataSourceExpression
@@ -142,7 +140,7 @@ class GinqAstWalker implements GinqAstVisitor<Expression>,
SyntaxErrorReportable
resultMethodCallReceiver = visitJoinExpression(joinExpression)
}
- WhereExpression whereExpression = currentGinqExpression.whereExpression
+ WhereExpression whereExpression =
getCurrentGinqExpression().whereExpression
if (whereExpression) {
whereExpression.dataSourceExpression = resultDataSourceExpression
whereExpression.putNodeMetaData(__METHOD_CALL_RECEIVER,
resultMethodCallReceiver)
@@ -151,7 +149,7 @@ class GinqAstWalker implements GinqAstVisitor<Expression>,
SyntaxErrorReportable
}
addDummyGroupExpressionIfNecessary()
- GroupExpression groupExpression = currentGinqExpression.groupExpression
+ GroupExpression groupExpression =
getCurrentGinqExpression().groupExpression
if (groupExpression) {
groupExpression.dataSourceExpression = resultDataSourceExpression
groupExpression.putNodeMetaData(__METHOD_CALL_RECEIVER,
resultMethodCallReceiver)
@@ -159,7 +157,7 @@ class GinqAstWalker implements GinqAstVisitor<Expression>,
SyntaxErrorReportable
resultMethodCallReceiver = groupMethodCallExpression
}
- OrderExpression orderExpression = currentGinqExpression.orderExpression
+ OrderExpression orderExpression =
getCurrentGinqExpression().orderExpression
if (orderExpression) {
orderExpression.dataSourceExpression = resultDataSourceExpression
orderExpression.putNodeMetaData(__METHOD_CALL_RECEIVER,
resultMethodCallReceiver)
@@ -167,7 +165,7 @@ class GinqAstWalker implements GinqAstVisitor<Expression>,
SyntaxErrorReportable
resultMethodCallReceiver = orderMethodCallExpression
}
- LimitExpression limitExpression = currentGinqExpression.limitExpression
+ LimitExpression limitExpression =
getCurrentGinqExpression().limitExpression
if (limitExpression) {
limitExpression.dataSourceExpression = resultDataSourceExpression
limitExpression.putNodeMetaData(__METHOD_CALL_RECEIVER,
resultMethodCallReceiver)
@@ -175,7 +173,7 @@ class GinqAstWalker implements GinqAstVisitor<Expression>,
SyntaxErrorReportable
resultMethodCallReceiver = limitMethodCallExpression
}
- SelectExpression selectExpression =
currentGinqExpression.selectExpression
+ SelectExpression selectExpression =
getCurrentGinqExpression().selectExpression
selectExpression.putNodeMetaData(__METHOD_CALL_RECEIVER,
resultMethodCallReceiver)
selectExpression.dataSourceExpression = resultDataSourceExpression
MethodCallExpression selectMethodCallExpression =
visitSelectExpression(selectExpression)
@@ -280,12 +278,12 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
}
private void addDummyGroupExpressionIfNecessary() {
- if (currentGinqExpression.groupExpression) {
+ if (getCurrentGinqExpression().groupExpression) {
return
}
boolean hasAggFunctionInSelect = false
- SelectExpression selectExpression =
currentGinqExpression.selectExpression
+ SelectExpression selectExpression =
getCurrentGinqExpression().selectExpression
selectExpression.projectionExpr.visit(new GinqAstBaseVisitor() {
@Override
void visitMethodCallExpression(MethodCallExpression call) {
@@ -306,7 +304,7 @@ class GinqAstWalker implements GinqAstVisitor<Expression>,
SyntaxErrorReportable
})
if (hasAggFunctionInSelect) {
- currentGinqExpression.groupExpression =
+ getCurrentGinqExpression().groupExpression =
new GroupExpression(
new ArgumentListExpression(
Collections.singletonList(
@@ -672,7 +670,7 @@ class GinqAstWalker implements GinqAstVisitor<Expression>,
SyntaxErrorReportable
@Override
MethodCallExpression visitSelectExpression(SelectExpression
selectExpression) {
- currentGinqExpression.putNodeMetaData(__VISITING_SELECT, true)
+ getCurrentGinqExpression().putNodeMetaData(__VISITING_SELECT, true)
Expression selectMethodReceiver =
selectExpression.getNodeMetaData(__METHOD_CALL_RECEIVER)
DataSourceExpression dataSourceExpression =
selectExpression.dataSourceExpression
Expression projectionExpr = selectExpression.getProjectionExpr()
@@ -824,13 +822,13 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
List<Expression> extra = []
if (enableCount || rowNumberUsed) {
- currentGinqExpression.putNodeMetaData(__RN_USED, true)
+ getCurrentGinqExpression().putNodeMetaData(__RN_USED, true)
extra << callX(varX(rowNumberName), 'getAndIncrement')
}
def selectMethodCallExpression = callXWithLambda(selectMethodReceiver,
"select", dataSourceExpression, parallel, lambdaCode, extra,
param(dynamicType(), getWindowQueryableName()))
- currentGinqExpression.putNodeMetaData(__VISITING_SELECT, false)
+ getCurrentGinqExpression().putNodeMetaData(__VISITING_SELECT, false)
return selectMethodCallExpression
}
@@ -975,13 +973,13 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
}
}
- private int windowQueryableNameSeq = 0
+ private int windowQueryableNameSeq
private String getWindowQueryableName() {
- String name = (String)
currentGinqExpression.getNodeMetaData(__WINDOW_QUERYABLE_NAME)
+ String name = (String)
getCurrentGinqExpression().getNodeMetaData(__WINDOW_QUERYABLE_NAME)
if (!name) {
name = "${__WINDOW_QUERYABLE_NAME}${windowQueryableNameSeq++}"
- currentGinqExpression.putNodeMetaData(__WINDOW_QUERYABLE_NAME,
name)
+
getCurrentGinqExpression().putNodeMetaData(__WINDOW_QUERYABLE_NAME, name)
}
return name
@@ -1074,7 +1072,7 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
}
def nameListExpression = new ListExpression(nameExpressionList)
- currentGinqExpression.putNodeMetaData(metaDataKey, nameListExpression)
+ getCurrentGinqExpression().putNodeMetaData(metaDataKey,
nameListExpression)
ConstructorCallExpression namedRecordCtorCallExpression =
ctorX(NAMED_RECORD_TYPE,
@@ -1086,37 +1084,37 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
return namedRecordCtorCallExpression
}
- private int metaDataMapNameSeq = 0
+ private int metaDataMapNameSeq
private String getMetaDataMapName() {
- String name = (String)
currentGinqExpression.getNodeMetaData(__META_DATA_MAP_NAME_PREFIX)
+ String name = (String)
getCurrentGinqExpression().getNodeMetaData(__META_DATA_MAP_NAME_PREFIX)
if (!name) {
name = "${__META_DATA_MAP_NAME_PREFIX}${metaDataMapNameSeq++}"
- currentGinqExpression.putNodeMetaData(__META_DATA_MAP_NAME_PREFIX,
name)
+
getCurrentGinqExpression().putNodeMetaData(__META_DATA_MAP_NAME_PREFIX, name)
}
return name
}
- private int rowNumberNameSeq = 0
+ private int rowNumberNameSeq
private String getRowNumberName() {
- String name = (String)
currentGinqExpression.getNodeMetaData(__ROW_NUMBER_NAME_PREFIX)
+ String name = (String)
getCurrentGinqExpression().getNodeMetaData(__ROW_NUMBER_NAME_PREFIX)
if (!name) {
name = "${__ROW_NUMBER_NAME_PREFIX}${rowNumberNameSeq++}"
- currentGinqExpression.putNodeMetaData(__ROW_NUMBER_NAME_PREFIX,
name)
+
getCurrentGinqExpression().putNodeMetaData(__ROW_NUMBER_NAME_PREFIX, name)
}
return name
}
- private int supplyAsyncLambdaParamNameSeq = 0
+ private int supplyAsyncLambdaParamNameSeq
private String getSupplyAsyncLambdaParamName() {
- String name = (String)
currentGinqExpression.getNodeMetaData(SUPPLY_ASYNC_LAMBDA_PARAM_NAME_PREFIX)
+ String name = (String)
getCurrentGinqExpression().getNodeMetaData(SUPPLY_ASYNC_LAMBDA_PARAM_NAME_PREFIX)
if (!name) {
name =
"${SUPPLY_ASYNC_LAMBDA_PARAM_NAME_PREFIX}${supplyAsyncLambdaParamNameSeq++}"
-
currentGinqExpression.putNodeMetaData(SUPPLY_ASYNC_LAMBDA_PARAM_NAME_PREFIX,
name)
+
getCurrentGinqExpression().putNodeMetaData(SUPPLY_ASYNC_LAMBDA_PARAM_NAME_PREFIX,
name)
}
return name
@@ -1131,11 +1129,11 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
}
private ListExpression getSelectNameListExpression() {
- (ListExpression)
(currentGinqExpression.getNodeMetaData(MD_SELECT_NAME_LIST) ?: [])
+ (ListExpression)
(getCurrentGinqExpression().getNodeMetaData(MD_SELECT_NAME_LIST) ?: [])
}
private ListExpression getGroupNameListExpression() {
- (ListExpression)
(currentGinqExpression.getNodeMetaData(MD_GROUP_NAME_LIST) ?: [])
+ (ListExpression)
(getCurrentGinqExpression().getNodeMetaData(MD_GROUP_NAME_LIST) ?: [])
}
private List<String> getGroupNameList() {
@@ -1156,8 +1154,8 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
private List<String> getDataSourceAliasList() {
List<DataSourceExpression> dataSourceExpressionList = []
- dataSourceExpressionList << currentGinqExpression.fromExpression
-
dataSourceExpressionList.addAll(currentGinqExpression.joinExpressionList)
+ dataSourceExpressionList << getCurrentGinqExpression().fromExpression
+
dataSourceExpressionList.addAll(getCurrentGinqExpression().joinExpressionList)
dataSourceExpressionList.stream().map(e ->
e.aliasExpr.text).collect(Collectors.toList())
}
@@ -1362,8 +1360,6 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
expression
}
- private final Deque<String> visitingAggregateFunctionStack = new
ArrayDeque<>()
-
@Override
Expression visit(AbstractGinqExpression expression) {
expression.accept(this)
@@ -1420,7 +1416,7 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
)
}
- private int lambdaParamSeq = 0
+ private int lambdaParamSeq
private String generateLambdaParamName() {
"__t_${lambdaParamSeq++}"
}
@@ -1489,19 +1485,19 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
}
private boolean isGroupByVisited() {
- return currentGinqExpression.getNodeMetaData(__GROUPBY_VISITED) ?:
false
+ getCurrentGinqExpression().getNodeMetaData(__GROUPBY_VISITED)
}
private boolean isVisitingSelect() {
- currentGinqExpression.getNodeMetaData(__VISITING_SELECT) ?: false
+ getCurrentGinqExpression().getNodeMetaData(__VISITING_SELECT)
}
private boolean isVisitingWindowFunction() {
- currentGinqExpression.getNodeMetaData(__VISITING_WINDOW_FUNCTION) ?:
false
+ getCurrentGinqExpression().getNodeMetaData(__VISITING_WINDOW_FUNCTION)
}
private boolean isRowNumberUsed() {
- currentGinqExpression.getNodeMetaData(__RN_USED) ?: false
+ getCurrentGinqExpression().getNodeMetaData(__RN_USED)
}
private static MethodCallExpression callXWithLambda(Expression receiver,
String methodName, LambdaExpression lambdaExpression) {
@@ -1512,20 +1508,24 @@ class GinqAstWalker implements
GinqAstVisitor<Expression>, SyntaxErrorReportable
)
}
+
//--------------------------------------------------------------------------
+
final SourceUnit sourceUnit
- private Map<String, String> configuration
- @Override
- void setConfiguration(Map<String, String> configuration) {
- this.configuration = configuration
- }
+ private Map<String,String> configuration
@Override
Map<String, String> getConfiguration() {
return configuration
}
+ @Override
+ void setConfiguration(Map<String, String> configuration) {
+ this.configuration = configuration
+ }
private final Deque<GinqExpression> ginqExpressionStack = new
ArrayDeque<>()
+ private final Deque<String> visitingAggregateFunctionStack = new
ArrayDeque<>()
+
private static final ClassNode MAPS_TYPE = makeWithoutCaching(Maps.class)
private static final ClassNode QUERYABLE_TYPE =
makeWithoutCaching(Queryable.class)
private static final ClassNode ORDER_TYPE =
makeWithoutCaching(Queryable.Order.class)