Skip to content

Commit 924898f

Browse files
authored
GROOVY-11993: Support serializable method reference (#2514)
1 parent 16ba916 commit 924898f

7 files changed

Lines changed: 2159 additions & 257 deletions

File tree

src/main/java/org/codehaus/groovy/classgen/asm/sc/AbstractFunctionalInterfaceWriter.java

Lines changed: 283 additions & 65 deletions
Large diffs are not rendered by default.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.codehaus.groovy.classgen.asm.sc;
20+
21+
/**
22+
* Internal AST node metadata keys used by the statically-compiled lambda and method-reference pipeline.
23+
*
24+
* @since 6.0.0
25+
*/
26+
enum StaticTypesFunctionalInterfaceMetadataKey {
27+
/**
28+
* Stores the shared {@code $deserializeLambda$} guard block on the enclosing class node.
29+
*/
30+
DESERIALIZE_LAMBDA_DISPATCHER,
31+
/**
32+
* Marks the synthetic constructor created for a generated lambda class.
33+
*/
34+
LAMBDA_GENERATED_CONSTRUCTOR,
35+
/**
36+
* Stores the captured shared variables prepared for a lambda expression.
37+
*/
38+
LAMBDA_SHARED_VARIABLES,
39+
/**
40+
* Marks the deserialize helper method that preloads a captured lambda receiver.
41+
*/
42+
LAMBDA_PRELOADED_RECEIVER,
43+
/**
44+
* Caches whether the analyzed lambda method touches enclosing-instance state.
45+
*/
46+
LAMBDA_ACCESSES_INSTANCE_MEMBERS,
47+
/**
48+
* Stores the synthetic deserialize helper name allocated for a method-reference expression so
49+
* repeated bytecode-generation visits can reuse the same helper slot.
50+
*/
51+
METHOD_REFERENCE_DESERIALIZE_METHOD_NAME
52+
}

src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaAnalyzer.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.util.List;
4141
import java.util.Map;
4242

43+
import static org.codehaus.groovy.classgen.asm.sc.StaticTypesFunctionalInterfaceMetadataKey.LAMBDA_ACCESSES_INSTANCE_MEMBERS;
4344
import static org.apache.groovy.util.BeanUtils.capitalize;
4445
import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
4546
import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DIRECT_METHOD_CALL_TARGET;
@@ -68,14 +69,14 @@ boolean isNonCapturing(final MethodNode lambdaMethod, final Parameter[] sharedVa
6869
}
6970

7071
boolean accessesInstanceMembers(final MethodNode lambdaMethod) {
71-
Boolean accessingInstanceMembers = lambdaMethod.getNodeMetaData(MetaDataKey.ACCESSES_INSTANCE_MEMBERS);
72+
Boolean accessingInstanceMembers = lambdaMethod.getNodeMetaData(LAMBDA_ACCESSES_INSTANCE_MEMBERS);
7273
if (accessingInstanceMembers != null) return accessingInstanceMembers;
7374

7475
InstanceMemberAccessFinder finder = new InstanceMemberAccessFinder(getOrCreateResolver(lambdaMethod));
7576
lambdaMethod.getCode().visit(finder);
7677

7778
accessingInstanceMembers = finder.isAccessingInstanceMembers();
78-
lambdaMethod.putNodeMetaData(MetaDataKey.ACCESSES_INSTANCE_MEMBERS, accessingInstanceMembers);
79+
lambdaMethod.putNodeMetaData(LAMBDA_ACCESSES_INSTANCE_MEMBERS, accessingInstanceMembers);
7980
return accessingInstanceMembers;
8081
}
8182

@@ -161,9 +162,7 @@ private Expression qualify(final VariableExpression expression) {
161162

162163
PropertyExpression qualifiedReference = new PropertyExpression(classX(owner), expression.getName());
163164
qualifiedReference.setImplicitThis(false);
164-
qualifiedReference.copyNodeMetaData(expression);
165-
setSourcePosition(qualifiedReference, expression);
166-
return qualifiedReference;
165+
return finishQualifiedReference(qualifiedReference, expression);
167166
}
168167

169168
private Expression qualify(final AttributeExpression expression) {
@@ -177,9 +176,7 @@ private Expression qualify(final AttributeExpression expression) {
177176
);
178177
qualifiedReference.setImplicitThis(false);
179178
qualifiedReference.setSpreadSafe(expression.isSpreadSafe());
180-
qualifiedReference.copyNodeMetaData(expression);
181-
setSourcePosition(qualifiedReference, expression);
182-
return qualifiedReference;
179+
return finishQualifiedReference(qualifiedReference, expression);
183180
}
184181

185182
private Expression qualify(final PropertyExpression expression) {
@@ -193,9 +190,7 @@ private Expression qualify(final PropertyExpression expression) {
193190
);
194191
qualifiedReference.setImplicitThis(false);
195192
qualifiedReference.setSpreadSafe(expression.isSpreadSafe());
196-
qualifiedReference.copyNodeMetaData(expression);
197-
setSourcePosition(qualifiedReference, expression);
198-
return qualifiedReference;
193+
return finishQualifiedReference(qualifiedReference, expression);
199194
}
200195

201196
private Expression qualify(final MethodCallExpression expression) {
@@ -212,6 +207,10 @@ private Expression qualify(final MethodCallExpression expression) {
212207
qualifiedReference.setSpreadSafe(expression.isSpreadSafe());
213208
qualifiedReference.setGenericsTypes(expression.getGenericsTypes());
214209
qualifiedReference.setMethodTarget(expression.getMethodTarget());
210+
return finishQualifiedReference(qualifiedReference, expression);
211+
}
212+
213+
private <T extends Expression> T finishQualifiedReference(final T qualifiedReference, final Expression expression) {
215214
qualifiedReference.copyNodeMetaData(expression);
216215
setSourcePosition(qualifiedReference, expression);
217216
return qualifiedReference;
@@ -394,10 +393,6 @@ private boolean isAccessingInstanceMembers() {
394393
}
395394
}
396395

397-
private enum MetaDataKey {
398-
ACCESSES_INSTANCE_MEMBERS
399-
}
400-
401396
private final SourceUnit sourceUnit;
402397
private final Map<MethodNode, OuterStaticMemberResolver> resolverCache = new HashMap<>();
403398
}

0 commit comments

Comments
 (0)