You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2025/04/14 02:18:15 UTC

(groovy) branch GROOVY-11611 updated (d35ef2b30a -> d6a92f725f)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch GROOVY-11611
in repository https://gitbox.apache.org/repos/asf/groovy.git


 discard d35ef2b30a GROOVY-11611: outer class super method invocation
     new d6a92f725f GROOVY-11611: outer class super method invocation

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (d35ef2b30a)
            \
             N -- N -- N   refs/heads/GROOVY-11611 (d6a92f725f)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../ginq/provider/collection/GinqAstWalker.groovy  | 88 +++++++++++-----------
 1 file changed, 44 insertions(+), 44 deletions(-)


(groovy) 01/01: GROOVY-11611: outer class super method invocation

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY-11611
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit d6a92f725fdd70eb884bca46ef6eac5cd05a1c1a
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Apr 13 20:25:41 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 +++---
 src/test/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/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 0d72798d9b..d834cb11e3 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/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)