Skip to content

Commit 50e0e97

Browse files
committed
GROOVY-4320, GROOVY-4516
1 parent 058310c commit 50e0e97

File tree

5 files changed

+619
-15
lines changed

5 files changed

+619
-15
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/DelegateTests.java

+78-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2019 the original author or authors.
2+
* Copyright 2009-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,21 +27,90 @@ public final class DelegateTests extends GroovyCompilerTestSuite {
2727
public void testDelegate1() {
2828
//@formatter:off
2929
String[] sources = {
30-
"Bar.groovy",
31-
"class Foo { @Delegate URL myUrl }\n" +
30+
"Main.groovy",
31+
"class C { @Delegate URL myUrl }\n" +
3232
"\n" +
33-
"print Foo.class.getDeclaredMethod('getContent', Class[].class)\n",
33+
"print C.getDeclaredMethod('getContent', Class[].class)\n",
3434
};
3535
//@formatter:on
3636

37-
runConformTest(sources, "public final java.lang.Object Foo.getContent(java.lang.Class[]) throws java.io.IOException");
37+
runConformTest(sources, "public final java.lang.Object C.getContent(java.lang.Class[]) throws java.io.IOException");
38+
}
39+
40+
@Test // GROOVY-4320
41+
public void testDelegate2() {
42+
//@formatter:off
43+
String[] sources = {
44+
"Main.groovy",
45+
"interface I {\n" +
46+
" void event(String name)\n" +
47+
" void event(String name, List values)\n" +
48+
"}\n" +
49+
"class C implements I {\n" +
50+
" void event(String name, List values = []) {\n" +
51+
" print \"$name:$values\"\n" +
52+
" }\n" +
53+
"}\n" +
54+
"class D {\n" +
55+
" @Delegate private C c = new C()\n" + // The method with default parameters "..." defines a method "void event(java.lang.String)" that is already defined.
56+
"}\n" +
57+
"\n" +
58+
"new D().event('x')\n",
59+
};
60+
//@formatter:on
61+
62+
runConformTest(sources, "x:[]");
63+
}
64+
65+
@Test // GROOVY-4516
66+
public void testDelegate3() {
67+
//@formatter:off
68+
String[] sources = {
69+
"Main.groovy",
70+
"class C {\n" +
71+
" def m(boolean flag = true) {\n" +
72+
" flag\n" +
73+
" }\n" +
74+
"}\n" +
75+
"class D {\n" +
76+
" @Delegate private C c = new C()\n" +
77+
"}\n" +
78+
"print new D().m()\n" +
79+
"print new D().m(false)\n",
80+
};
81+
//@formatter:on
82+
83+
runConformTest(sources, "truefalse");
84+
}
85+
86+
@Test
87+
public void testDelegate4() {
88+
//@formatter:off
89+
String[] sources = {
90+
"Main.groovy",
91+
"class C {\n" +
92+
" def m(x = defaultValue()) {\n" +
93+
" x\n" +
94+
" }\n" +
95+
" private defaultValue() {\n" +
96+
" 'x'\n" +
97+
" }\n" +
98+
"}\n" +
99+
"class D {\n" +
100+
" @Delegate private C c = new C()\n" +
101+
"}\n" +
102+
"print new D().m()\n" +
103+
"print new D().m('y')\n",
104+
};
105+
//@formatter:on
106+
107+
runConformTest(sources, "xy");
38108
}
39109

40110
/**
41-
* Test code based on <a href="http://www.infoq.com/articles/groovy-1.5-new">article</a>.
42-
* The groups of tests are loosely based on the article contents, but what is
43-
* really exercised here is the accessibility of the described constructs
44-
* across the Java/Groovy divide.
111+
* Test code based on an <a href="http://www.infoq.com/articles/groovy-1.5-new">article</a>.
112+
* The groups of tests are loosely based on its contents, but what is really exercised
113+
* here is the accessibility of the described constructs across the Java/Groovy divide.
45114
*/
46115
@Test
47116
public void testDelegate_1731() {

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/DelegateASTTransformation.java

+33-2
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,37 @@ public void visit(ASTNode[] nodes, SourceUnit source) {
137137
". Delegation to own type not supported. Please use a different type.", parent);
138138
return;
139139
}
140-
final List<MethodNode> delegateMethods = getAllMethods(delegate.type);
140+
final List<MethodNode> delegateMethods = new java.util.LinkedList<>(getAllMethods(delegate.type));
141+
// GRECLIPSE add -- GROOVY-4320, GROOVY-4516
142+
for (java.util.ListIterator<MethodNode> it = delegateMethods.listIterator(); it.hasNext();) {
143+
MethodNode next = it.next();
144+
if (next.isPublic() && !next.isAbstract() && next.hasDefaultValue()) {
145+
int n = 0;
146+
for (Parameter p : next.getParameters())
147+
if (p.hasInitialExpression()) n += 1;
148+
for (int i = 1; i <= n; i += 1) { // from Verifier#addDefaultParameters
149+
Parameter[] params = new Parameter[next.getParameters().length - i];
150+
int index = 0, j = 1;
151+
for (Parameter parameter : next.getParameters()) {
152+
if (j > n - i && parameter.hasInitialExpression()) {
153+
j += 1;
154+
} else {
155+
params[index++] = parameter;
156+
if (parameter.hasInitialExpression()) j += 1;
157+
}
158+
}
159+
160+
if (delegateMethods.stream().noneMatch(mn -> mn.getName().equals(next.getName()) && org.codehaus.groovy.ast.tools.ParameterUtils.parametersEqual(mn.getParameters(), params))) {
161+
MethodNode mn = new MethodNode(next.getName(), next.getModifiers(), next.getReturnType(), params, next.getExceptions(), null);
162+
mn.setDeclaringClass(next.getDeclaringClass());
163+
mn.setGenericsTypes(next.getGenericsTypes());
164+
mn.addAnnotations(next.getAnnotations());
165+
it.add(mn);
166+
}
167+
}
168+
}
169+
}
170+
// GRECLIPSE end
141171
for (ClassNode next : delegate.type.getAllInterfaces()) {
142172
delegateMethods.addAll(getAllMethods(next));
143173
}
@@ -310,8 +340,9 @@ private void addDelegateMethod(DelegateDescription delegate, List<MethodNode> ow
310340
for (int i = 0; i < newParams.length; i++) {
311341
ClassNode newParamType = correctToGenericsSpecRecurse(genericsSpec, params[i].getType(), currentMethodGenPlaceholders);
312342
Parameter newParam = new Parameter(newParamType, getParamName(params, i, delegate.name));
343+
/* GRECLIPSE edit -- GROOVY-4320, GROOVY-4516
313344
newParam.setInitialExpression(params[i].getInitialExpression());
314-
345+
*/
315346
if (memberHasValue(delegate.annotation, MEMBER_PARAMETER_ANNOTATIONS, true)) {
316347
newParam.addAnnotations(copyAnnotatedNodeAnnotations(params[i], MY_TYPE_NAME));
317348
}

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/DelegateASTTransformation.java

+33-2
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,37 @@ public void visit(ASTNode[] nodes, SourceUnit source) {
141141
". Delegation to own type not supported. Please use a different type.", parent);
142142
return;
143143
}
144-
final List<MethodNode> delegateMethods = getAllMethods(delegate.type);
144+
final List<MethodNode> delegateMethods = new java.util.LinkedList<>(getAllMethods(delegate.type));
145+
// GRECLIPSE add -- GROOVY-4320, GROOVY-4516
146+
for (java.util.ListIterator<MethodNode> it = delegateMethods.listIterator(); it.hasNext();) {
147+
MethodNode next = it.next();
148+
if (next.isPublic() && !next.isAbstract() && next.hasDefaultValue()) {
149+
int n = 0;
150+
for (Parameter p : next.getParameters())
151+
if (p.hasInitialExpression()) n += 1;
152+
for (int i = 1; i <= n; i += 1) { // from Verifier#addDefaultParameters
153+
Parameter[] params = new Parameter[next.getParameters().length - i];
154+
int index = 0, j = 1;
155+
for (Parameter parameter : next.getParameters()) {
156+
if (j > n - i && parameter.hasInitialExpression()) {
157+
j += 1;
158+
} else {
159+
params[index++] = parameter;
160+
if (parameter.hasInitialExpression()) j += 1;
161+
}
162+
}
163+
164+
if (delegateMethods.stream().noneMatch(mn -> mn.getName().equals(next.getName()) && org.codehaus.groovy.ast.tools.ParameterUtils.parametersEqual(mn.getParameters(), params))) {
165+
MethodNode mn = new MethodNode(next.getName(), next.getModifiers(), next.getReturnType(), params, next.getExceptions(), null);
166+
mn.setDeclaringClass(next.getDeclaringClass());
167+
mn.setGenericsTypes(next.getGenericsTypes());
168+
mn.addAnnotations(next.getAnnotations());
169+
it.add(mn);
170+
}
171+
}
172+
}
173+
}
174+
// GRECLIPSE end
145175
for (ClassNode next : delegate.type.getAllInterfaces()) {
146176
delegateMethods.addAll(getAllMethods(next));
147177
}
@@ -349,8 +379,9 @@ private void addDelegateMethod(DelegateDescription delegate, List<MethodNode> ow
349379
for (int i = 0; i < newParams.length; i++) {
350380
ClassNode newParamType = correctToGenericsSpecRecurse(genericsSpec, params[i].getType(), currentMethodGenPlaceholders);
351381
Parameter newParam = new Parameter(newParamType, getParamName(params, i, delegate.name));
382+
/* GRECLIPSE edit -- GROOVY-4320, GROOVY-4516
352383
newParam.setInitialExpression(params[i].getInitialExpression());
353-
384+
*/
354385
if (memberHasValue(delegate.annotation, MEMBER_PARAMETER_ANNOTATIONS, true)) {
355386
newParam.addAnnotations(copyAnnotatedNodeAnnotations(params[i], MY_TYPE_NAME));
356387
}

base/org.codehaus.groovy40/.checkstyle

+1-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@
5656
<file-match-pattern match-pattern="groovy/transform/ASTTestTransformation.groovy" include-pattern="false" />
5757
<file-match-pattern match-pattern="groovy/transform/ASTTransformationCollectorCodeVisitor.java" include-pattern="false" />
5858
<file-match-pattern match-pattern="groovy/transform/ASTTransformationVisitor.java" include-pattern="false" />
59-
<file-match-pattern match-pattern="groovy/transform/FieldASTTransformation.java" include-pattern="false" />
60-
<file-match-pattern match-pattern="groovy/transform/LogASTTransformation.java" include-pattern="false" />
59+
<file-match-pattern match-pattern="groovy/transform/(Delegate|Field|Log)ASTTransformation.java" include-pattern="false" />
6160
<file-match-pattern match-pattern="groovy/transform/NotYetImplemented.java" include-pattern="false" />
6261
<file-match-pattern match-pattern="groovy/transform/sc/transformers/(Binary|MethodCall)ExpressionTransformer.java" include-pattern="false" />
6362
<file-match-pattern match-pattern="groovy/transform/stc/StaticTypeCheckingSupport.java" include-pattern="false" />

0 commit comments

Comments
 (0)