Repository: groovy
Updated Branches:
  refs/heads/native-lambda [created] d746dd7ff


Support very basic native lambda


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/d746dd7f
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/d746dd7f
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/d746dd7f

Branch: refs/heads/native-lambda
Commit: d746dd7ff222abad8e61aefd7d5b153bb9c28250
Parents: 3e167cc
Author: sunlan <[email protected]>
Authored: Thu Jan 11 15:35:02 2018 +0800
Committer: sunlan <[email protected]>
Committed: Thu Jan 11 15:35:02 2018 +0800

----------------------------------------------------------------------
 .../codehaus/groovy/ast/GroovyCodeVisitor.java  |   5 +
 .../groovy/ast/expr/LambdaExpression.java       |   5 +
 .../groovy/classgen/AsmClassGenerator.java      |  10 +
 .../classgen/asm/DelegatingController.java      |   7 +-
 .../groovy/classgen/asm/LambdaWriter.java       |  31 +++
 .../groovy/classgen/asm/WriterController.java   |   6 +
 .../classgen/asm/sc/StaticInvocationWriter.java |   4 +
 .../asm/sc/StaticTypesLambdaWriter.java         | 122 +++++++++
 .../asm/sc/StaticTypesWriterController.java     |  11 +
 src/test/groovy/transform/stc/LambdaTest.groovy |  56 ++++
 .../apache/groovy/parser/antlr4/AstBuilder.java | 273 ++++++++++++++++++-
 11 files changed, 527 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java 
b/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
index 12787c0..db793cc 100644
--- a/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
@@ -34,6 +34,7 @@ import org.codehaus.groovy.ast.expr.DeclarationExpression;
 import org.codehaus.groovy.ast.expr.ElvisOperatorExpression;
 import org.codehaus.groovy.ast.expr.FieldExpression;
 import org.codehaus.groovy.ast.expr.GStringExpression;
+import org.codehaus.groovy.ast.expr.LambdaExpression;
 import org.codehaus.groovy.ast.expr.ListExpression;
 import org.codehaus.groovy.ast.expr.MapEntryExpression;
 import org.codehaus.groovy.ast.expr.MapExpression;
@@ -138,6 +139,10 @@ public interface GroovyCodeVisitor {
 
     void visitClosureExpression(ClosureExpression expression);
 
+    default void visitLambdaExpression(LambdaExpression expression) {
+        visitClosureExpression(expression);
+    }
+
     void visitTupleExpression(TupleExpression expression);
 
     void visitMapExpression(MapExpression expression);

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/main/java/org/codehaus/groovy/ast/expr/LambdaExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/LambdaExpression.java 
b/src/main/java/org/codehaus/groovy/ast/expr/LambdaExpression.java
index f4f1001..ab30513 100644
--- a/src/main/java/org/codehaus/groovy/ast/expr/LambdaExpression.java
+++ b/src/main/java/org/codehaus/groovy/ast/expr/LambdaExpression.java
@@ -20,6 +20,7 @@
 package org.codehaus.groovy.ast.expr;
 
 import org.codehaus.groovy.ast.AstToTextHelper;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.stmt.Statement;
 
@@ -35,6 +36,10 @@ public class LambdaExpression extends ClosureExpression {
         super(parameters, code);
     }
 
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitLambdaExpression(this);
+    }
+
     @Override
     public String getText() {
         String paramText = 
AstToTextHelper.getParametersText(this.getParameters());

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java 
b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 099bc9c..7721260 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -55,6 +55,7 @@ import org.codehaus.groovy.ast.expr.EmptyExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.FieldExpression;
 import org.codehaus.groovy.ast.expr.GStringExpression;
+import org.codehaus.groovy.ast.expr.LambdaExpression;
 import org.codehaus.groovy.ast.expr.ListExpression;
 import org.codehaus.groovy.ast.expr.MapEntryExpression;
 import org.codehaus.groovy.ast.expr.MapExpression;
@@ -717,6 +718,11 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getClosureWriter().writeClosure(expression);
     }
 
+    @Override
+    public void visitLambdaExpression(LambdaExpression expression) {
+        controller.getLambdaWriter().writeLambda(expression);
+    }
+
     /**
      * Loads either this object or if we're inside a closure then load the top 
level owner
      */
@@ -2174,4 +2180,8 @@ public class AsmClassGenerator extends ClassGenerator {
         mn.getUnit().addGeneratedInnerClass((InnerClassNode)innerClass);
         return innerClasses.add(innerClass);
     }
+
+    public ClassVisitor getClassVisitor() {
+        return cv;
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
index 22acbaa..3553a82 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
@@ -112,7 +112,12 @@ public class DelegatingController extends WriterController 
{
     @Override
     public ClosureWriter getClosureWriter() {
         return delegationController.getClosureWriter();
-    } 
+    }
+
+    @Override
+    public LambdaWriter getLambdaWriter() {
+        return delegationController.getLambdaWriter();
+    }
     
     @Override
     public CompileStack getCompileStack() {

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java
new file mode 100644
index 0000000..3a39688
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.classgen.asm;
+
+import org.codehaus.groovy.ast.expr.LambdaExpression;
+
+public class LambdaWriter extends ClosureWriter {
+    public LambdaWriter(WriterController wc) {
+        super(wc);
+    }
+
+    public void writeLambda(LambdaExpression expression) {
+        super.writeClosure(expression);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
index 3c9d843..fe7a21e 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
@@ -55,6 +55,7 @@ public class WriterController {
     private CallSiteWriter callSiteWriter;
     private ClassVisitor cv;
     private ClosureWriter closureWriter;
+    private LambdaWriter lambdaWriter;
     private String internalClassName;
     private InvocationWriter invocationWriter;
     private BinaryExpressionHelper binaryExpHelper, fastPathBinaryExpHelper;
@@ -120,6 +121,7 @@ public class WriterController {
         this.operandStack = new OperandStack(this);
         this.assertionWriter = new AssertionWriter(this);
         this.closureWriter = new ClosureWriter(this);
+        this.lambdaWriter = new LambdaWriter(this);
         this.internalBaseClassName = 
BytecodeHelper.getClassInternalName(classNode.getSuperClass());
         this.acg = asmClassGenerator;
         this.sourceUnit = acg.getSourceUnit();
@@ -197,6 +199,10 @@ public class WriterController {
         return closureWriter;
     }
 
+    public LambdaWriter getLambdaWriter() {
+        return lambdaWriter;
+    }
+
     public ClassVisitor getCv() {
         return cv;
     }

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
----------------------------------------------------------------------
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 d2b5bc7..22482e5 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
@@ -102,6 +102,7 @@ public class StaticInvocationWriter extends 
InvocationWriter {
                     new Parameter(ClassHelper.OBJECT_TYPE, "args")
             }
     );
+    public static final String PARAMETER_TYPE = "_parameter_type";
 
     private final AtomicInteger labelCounter = new AtomicInteger();
 
@@ -435,6 +436,7 @@ public class StaticInvocationWriter extends 
InvocationWriter {
             // first parameters as usual
             for (int i = 0; i < para.length - 1; i++) {
                 Expression expression = argumentList.get(i);
+                expression.putNodeMetaData(PARAMETER_TYPE, para[i].getType());
                 expression.visit(acg);
                 if (!isNullConstant(expression)) {
                     operandStack.doGroovyCast(para[i].getType());
@@ -460,6 +462,7 @@ public class StaticInvocationWriter extends 
InvocationWriter {
         } else if (argumentListSize == para.length) {
             for (int i = 0; i < argumentListSize; i++) {
                 Expression expression = argumentList.get(i);
+                expression.putNodeMetaData(PARAMETER_TYPE, para[i].getType());
                 expression.visit(acg);
                 if (!isNullConstant(expression)) {
                     operandStack.doGroovyCast(para[i].getType());
@@ -491,6 +494,7 @@ public class StaticInvocationWriter extends 
InvocationWriter {
             }
             for (int i = 0; i < arguments.length; i++) {
                 Expression expression = arguments[i];
+                expression.putNodeMetaData(PARAMETER_TYPE, para[i].getType());
                 expression.visit(acg);
                 if (!isNullConstant(expression)) {
                     operandStack.doGroovyCast(para[i].getType());

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
new file mode 100644
index 0000000..6feaba5
--- /dev/null
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
@@ -0,0 +1,122 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.codehaus.groovy.classgen.asm.sc;
+
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.ClosureExpression;
+import org.codehaus.groovy.ast.expr.LambdaExpression;
+import org.codehaus.groovy.classgen.AsmClassGenerator;
+import org.codehaus.groovy.classgen.asm.BytecodeHelper;
+import org.codehaus.groovy.classgen.asm.LambdaWriter;
+import org.codehaus.groovy.classgen.asm.WriterController;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static 
org.apache.groovy.parser.antlr4.AstBuilder.LAMBDA_ENCLOSING_CLASSNODE;
+import static 
org.apache.groovy.parser.antlr4.AstBuilder.SYNTHETIC_LAMBDA_METHOD_NODE;
+import static 
org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.PARAMETER_TYPE;
+import static org.objectweb.asm.Opcodes.ACC_FINAL;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+
+/**
+ * Writer responsible for generating lambda classes in statically compiled 
mode.
+ *
+ */
+public class StaticTypesLambdaWriter extends LambdaWriter {
+    private StaticTypesClosureWriter staticTypesClosureWriter;
+    private WriterController controller;
+
+    public StaticTypesLambdaWriter(WriterController wc) {
+        super(wc);
+        this.staticTypesClosureWriter = new StaticTypesClosureWriter(wc);
+        this.controller = wc;
+    }
+
+    @Override
+    public void writeLambda(LambdaExpression expression) {
+        ClassNode parameterType = expression.getNodeMetaData(PARAMETER_TYPE);
+
+        List<MethodNode> abstractMethodNodeList =
+                parameterType.redirect().getMethods().stream()
+                        .filter(MethodNode::isAbstract)
+                        .collect(Collectors.toList());
+
+        if (abstractMethodNodeList.size() != 1) {
+            super.writeClosure(expression);
+            return;
+        }
+
+        MethodNode abstractMethodNode = abstractMethodNodeList.get(0);
+        String abstractMethodName = abstractMethodNode.getName();
+        String abstractMethodDesc = "()L" + 
parameterType.redirect().getPackageName().replace('.', '/') + "/" + 
parameterType.redirect().getNameWithoutPackage() + ";";
+
+
+        AsmClassGenerator acg = controller.getAcg();
+        ClassVisitor cw = acg.getClassVisitor();
+        cw.visitInnerClass(
+                "java/lang/invoke/MethodHandles$Lookup",
+                "java/lang/invoke/MethodHandles",
+                "Lookup",
+                ACC_PUBLIC + ACC_FINAL + ACC_STATIC);
+
+        MethodVisitor mv = controller.getMethodVisitor();
+        MethodNode syntheticLambdaMethodNode = 
expression.getNodeMetaData(SYNTHETIC_LAMBDA_METHOD_NODE);
+        ClassNode lambdaEnclosingClassNode = 
expression.getNodeMetaData(LAMBDA_ENCLOSING_CLASSNODE);
+
+        String syntheticLambdaMethodDesc = 
BytecodeHelper.getMethodDescriptor(syntheticLambdaMethodNode);
+
+        controller.getOperandStack().push(ClassHelper.OBJECT_TYPE);
+
+        mv.visitInvokeDynamicInsn(
+                abstractMethodName,
+                abstractMethodDesc,
+                new Handle(
+                        Opcodes.H_INVOKESTATIC,
+                        "java/lang/invoke/LambdaMetafactory",
+                        "metafactory",
+                        
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
+                        false),
+                new Object[] {
+                        Type.getType(syntheticLambdaMethodDesc),
+                        new Handle(
+                                Opcodes.H_INVOKESTATIC,
+                                lambdaEnclosingClassNode.getName(),
+                                syntheticLambdaMethodNode.getName(),
+                                syntheticLambdaMethodDesc,
+                                false),
+                        Type.getType(syntheticLambdaMethodDesc)
+                });
+
+    }
+
+    @Override
+    protected ClassNode createClosureClass(final ClosureExpression expression, 
final int mods) {
+        return staticTypesClosureWriter.createClosureClass(expression, mods);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
index 47ef3d4..15943e5 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
@@ -31,6 +31,7 @@ import org.codehaus.groovy.classgen.asm.CallSiteWriter;
 import org.codehaus.groovy.classgen.asm.ClosureWriter;
 import org.codehaus.groovy.classgen.asm.DelegatingController;
 import org.codehaus.groovy.classgen.asm.InvocationWriter;
+import org.codehaus.groovy.classgen.asm.LambdaWriter;
 import org.codehaus.groovy.classgen.asm.StatementWriter;
 import org.codehaus.groovy.classgen.asm.TypeChooser;
 import org.codehaus.groovy.classgen.asm.UnaryExpressionHelper;
@@ -60,6 +61,7 @@ public class StaticTypesWriterController extends 
DelegatingController {
     private BinaryExpressionMultiTypeDispatcher binaryExprHelper;
     private UnaryExpressionHelper unaryExpressionHelper;
     private ClosureWriter closureWriter;
+    private LambdaWriter lambdaWriter;
 
     public StaticTypesWriterController(WriterController normalController) {
         super(normalController);
@@ -74,6 +76,7 @@ public class StaticTypesWriterController extends 
DelegatingController {
         this.typeChooser = new StaticTypesTypeChooser();
         this.invocationWriter = new StaticInvocationWriter(this);
         this.closureWriter = new StaticTypesClosureWriter(this);
+        this.lambdaWriter = new StaticTypesLambdaWriter(this);
         this.unaryExpressionHelper = new 
StaticTypesUnaryExpressionHelper(this);
 
         CompilerConfiguration config = cn.getCompileUnit().getConfig();
@@ -183,4 +186,12 @@ public class StaticTypesWriterController extends 
DelegatingController {
         }
         return super.getClosureWriter();
     }
+
+    @Override
+    public LambdaWriter getLambdaWriter() {
+        if (isInStaticallyCheckedMethod) {
+            return lambdaWriter;
+        }
+        return super.getLambdaWriter();
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/src/test/groovy/transform/stc/LambdaTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy 
b/src/test/groovy/transform/stc/LambdaTest.groovy
new file mode 100644
index 0000000..0ee1ac3
--- /dev/null
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -0,0 +1,56 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package groovy.transform.stc
+
+class LambdaTest extends GroovyTestCase {
+    void testMethodCall() {
+        assertScript '''
+        import groovy.transform.CompileStatic
+        import java.util.stream.Collectors
+        import java.util.stream.Stream
+        
+        @CompileStatic
+        public class Test1 {
+            public static void main(String[] args) {
+                p1();
+        //        p2();
+        //        p3();
+            }
+        
+            public static void p1() {
+                assert [2, 3, 4] == Stream.of(1, 2, 3).map(e -> e + 
1).collect(Collectors.toList());
+            }
+        
+            /*
+            public static void p2() {
+                assert 13 == Stream.of(1, 2, 3).reduce(7, (r, e) -> r + e);
+            }
+            */
+            
+            /*
+            public static void p3() {
+                Stream.of(1, 2, 3).forEach(e -> { System.out.println(e + 1); 
});
+            }
+            */
+        }
+        '''
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/d746dd7f/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
----------------------------------------------------------------------
diff --git 
a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
 
b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 675255b..f808dde 100644
--- 
a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ 
b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -137,7 +137,212 @@ import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.*;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ADD;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AS;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AdditiveExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AndExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotatedQualifiedClassNameContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotationNameContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotationsOptContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AnonymousInnerClassDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ArgumentsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ArrayInitializerContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AssertStatementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AssertStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.AssignmentExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BlockContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.BlockStatementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.BlockStatementsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.BlockStatementsOptContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.BooleanLiteralAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.BreakStatementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.BreakStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.BuiltInTypeContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CASE;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.CastExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.CastParExpressionContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.CatchClauseContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.CatchTypeContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassBodyContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassBodyDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassNameContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceModifierContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceModifiersContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceModifiersOptContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceTypeContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassicalForControlContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClassifiedModifiersContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClosureContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ClosurePrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.CommandArgumentContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.CommandExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.CommandExpressionContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.CompilationUnitContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ConditionalExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ConditionalStatementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ConditionalStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ContinueStatementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ContinueStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.CreatedNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CreatorContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DEC;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DEF;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DEFAULT;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DimsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DimsOptContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.DoWhileStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.DynamicMemberNameContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValueArrayInitializerContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValueContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuePairContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuePairsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuesContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedArgumentListContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedArgumentListElementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedExpressionContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedForControlContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedStatementExpressionContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.EnumConstantContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.EnumConstantsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.EqualityExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ExclusiveOrExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionInParContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionListContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionListElementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.FieldDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.FinallyBlockContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.FloatingPointLiteralAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ForControlContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ForInitContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ForStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ForUpdateContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.FormalParameterContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.FormalParameterListContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.FormalParametersContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GE;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GT;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.GroovyParserRuleContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GstringContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.GstringPathContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.GstringPrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.GstringValueContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.IN;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.INC;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.INSTANCEOF;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.IdentifierContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.IdentifierPrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.IfElseStatementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ImportDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ImportStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.InclusiveOrExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.IndexPropertyArgsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.IntegerLiteralAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.KeywordsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LE;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LT;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.LabeledStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.LambdaBodyContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.LambdaPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ListContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ListPrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.LiteralPrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.LocalVariableDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.LocalVariableDeclarationStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.LogicalAndExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.LogicalOrExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.LoopStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapEntryContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MapEntryLabelContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MapEntryListContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MapPrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MemberDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MethodBodyContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MethodDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MethodDeclarationStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MethodNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ModifierContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ModifiersContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ModifiersOptContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MultipleAssignmentExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.MultiplicativeExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NOT_IN;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NOT_INSTANCEOF;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NamePartContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.NamedPropertyArgsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.NewPrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.NonWildcardTypeArgumentsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.NormalExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.NullLiteralAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PRIVATE;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.PackageDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ParExpressionContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ParenPrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.PathElementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.PathExpressionContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.PostfixExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.PostfixExpressionContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.PowerExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.PrimitiveTypeContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedClassNameContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedClassNameListContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedNameContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedStandardClassNameContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.RegexExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.RelationalExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ResourceContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ResourceListContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ResourcesContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ReturnStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ReturnTypeContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.STATIC;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SUB;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ShiftExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.StandardLambdaExpressionContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.StandardLambdaParametersContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.StatementsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.StringLiteralAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.StringLiteralContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.SuperPrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchBlockStatementGroupContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchLabelContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchStatementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.SynchronizedStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ThisFormalParameterContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ThisPrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.ThrowStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TryCatchStatementContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TryCatchStmtAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeArgumentContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeArgumentsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeArgumentsOrDiamondContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeBoundContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeDeclarationStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeListContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeNamePairContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeNamePairsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeParameterContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypeParametersContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.TypePrmrAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.UnaryAddExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.UnaryNotExprAltContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclarationContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclaratorContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclaratorIdContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclaratorsContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableInitializerContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableInitializersContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableModifierContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableModifiersContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableModifiersOptContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.VariableNamesContext;
+import static 
org.apache.groovy.parser.antlr4.GroovyLangParser.WhileStmtAltContext;
 import static 
org.apache.groovy.parser.antlr4.util.PositionConfigureUtils.configureAST;
 import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
 import static org.codehaus.groovy.runtime.DefaultGroovyMethods.last;
@@ -149,6 +354,7 @@ import static 
org.codehaus.groovy.runtime.DefaultGroovyMethods.last;
  *         Created on 2016/08/14
  */
 public class AstBuilder extends GroovyParserBaseVisitor<Object> implements 
GroovyParserVisitor<Object> {
+
     public AstBuilder(SourceUnit sourceUnit) {
         this.sourceUnit = sourceUnit;
         this.moduleNode = new ModuleNode(sourceUnit);
@@ -1060,9 +1266,49 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> implements Groov
             this.visitClassBodyDeclaration(e);
         });
 
+        genSyntheticLambdaMethodNode(classNode);
+
         return null;
     }
 
+    private void genSyntheticLambdaMethodNode(ClassNode classNode) {
+        if (null == classNode) {
+            classNode = moduleNode.getScriptClassDummy();
+        }
+
+        if (null == classNode) {
+            return;
+        }
+
+        List<LambdaExpression> lambdaExpressionList = 
lambdaExpressionRegistry.get(classNode);
+
+        if (null == lambdaExpressionList) {
+            return;
+        }
+
+        for (LambdaExpression lambdaExpression : lambdaExpressionList) {
+            String syntheticLambdaMethodNodeName = 
createSyntheticLambdaMethodNodeName();
+
+            Parameter[] parameters = lambdaExpression.getParameters();
+            if (parameters == null) {
+                parameters = Parameter.EMPTY_ARRAY;
+            }
+
+            MethodNode methodNode =
+                    classNode.addMethod(syntheticLambdaMethodNodeName, 
Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, 
ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, 
lambdaExpression.getCode());
+
+            lambdaExpression.putNodeMetaData(SYNTHETIC_LAMBDA_METHOD_NODE, 
methodNode);
+            lambdaExpression.putNodeMetaData(LAMBDA_ENCLOSING_CLASSNODE, 
classNode);
+
+            configureAST(methodNode, lambdaExpression);
+        }
+    }
+
+    private int syntheticLambdaMethodNodeCount = 0;
+    private String createSyntheticLambdaMethodNodeName() {
+        return "lambda$" + syntheticLambdaMethodNodeCount++;
+    }
+
     @Override
     public List<FieldNode> visitEnumConstants(EnumConstantsContext ctx) {
         ClassNode classNode = 
ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
@@ -3374,7 +3620,26 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> implements Groov
 
     @Override
     public LambdaExpression 
visitStandardLambdaExpression(StandardLambdaExpressionContext ctx) {
-        return configureAST(this.createLambda(ctx.standardLambdaParameters(), 
ctx.lambdaBody()), ctx);
+        LambdaExpression lambdaExpression = 
configureAST(this.createLambda(ctx.standardLambdaParameters(), 
ctx.lambdaBody()), ctx);
+
+        registerLambdaExpression(lambdaExpression);
+
+        return lambdaExpression;
+    }
+
+    private void registerLambdaExpression(LambdaExpression lambdaExpression) {
+        ClassNode classNode = classNodeStack.peek();
+
+        if (null == classNode) {
+            classNode = moduleNode.getScriptClassDummy();
+        }
+
+        List<LambdaExpression> lambdaExpressionList = 
lambdaExpressionRegistry.get(classNode);
+        if (null == lambdaExpressionList) {
+            lambdaExpressionList = new LinkedList<>();
+            lambdaExpressionRegistry.put(classNode, lambdaExpressionList);
+        }
+        lambdaExpressionList.add(lambdaExpression);
     }
 
     private LambdaExpression createLambda(StandardLambdaParametersContext 
standardLambdaParametersContext, LambdaBodyContext lambdaBodyContext) {
@@ -4282,6 +4547,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> implements Groov
             
scriptClassNode.setLastLineNumber(lastStatement.getLastLineNumber());
         }
 
+        genSyntheticLambdaMethodNode(scriptClassNode);
     }
 
     private boolean isTrue(NodeMetaDataHandler nodeMetaDataHandler, String 
key) {
@@ -4447,6 +4713,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> implements Groov
     private final List<ClassNode> classNodeList = new LinkedList<>();
     private final Deque<ClassNode> classNodeStack = new ArrayDeque<>();
     private final Deque<List<InnerClassNode>> 
anonymousInnerClassesDefinedInMethodStack = new ArrayDeque<>();
+    private final Map<ClassNode, List<LambdaExpression>> 
lambdaExpressionRegistry = new LinkedHashMap<>();
     private int anonymousInnerClassCounter = 1;
 
     private Tuple2<GroovyParserRuleContext, Exception> numberFormatError;
@@ -4505,4 +4772,6 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> implements Groov
     private static final String FLOATING_POINT_LITERAL_TEXT = 
"_FLOATING_POINT_LITERAL_TEXT";
 
     private static final String CLASS_NAME = "_CLASS_NAME";
+    public static final String LAMBDA_ENCLOSING_CLASSNODE = 
"_LAMBDA_ENCLOSING_CLASSNODE";
+    public static final String SYNTHETIC_LAMBDA_METHOD_NODE = 
"_SYNTHETIC_LAMBDA_METHOD_NODE";
 }

Reply via email to