Skip to content

Commit 5a0f8f7

Browse files
committed
GROOVY-10200
#1292
1 parent 248b14e commit 5a0f8f7

File tree

7 files changed

+120
-24
lines changed

7 files changed

+120
-24
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2009-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.eclipse.jdt.groovy.core.tests.xform;
17+
18+
import org.eclipse.jdt.groovy.core.tests.basic.GroovyCompilerTestSuite;
19+
import org.junit.Test;
20+
21+
/**
22+
* Test cases for {@link groovy.lang.Mixin}.
23+
*/
24+
public final class MixinTests extends GroovyCompilerTestSuite {
25+
26+
@Test
27+
public void testMixin1() {
28+
//@formatter:off
29+
String[] sources = {
30+
"Main.groovy",
31+
"class A {\n" +
32+
" def getB() {\n" +
33+
" 'works'\n" +
34+
" }\n" +
35+
"}\n" +
36+
"@Mixin(A)\n" +
37+
"class C {\n" +
38+
" void test() {\n" +
39+
" print b\n" +
40+
" }\n" +
41+
"}\n" +
42+
"new C().test()\n",
43+
};
44+
//@formatter:on
45+
46+
runConformTest(sources, "works");
47+
}
48+
49+
@Test // GROOVY-10200
50+
public void testMixin2() {
51+
//@formatter:off
52+
String[] sources = {
53+
"Main.groovy",
54+
"class A {\n" +
55+
" def getB() {\n" +
56+
" 'works'\n" +
57+
" }\n" +
58+
"}\n" +
59+
"class C {\n" +
60+
" @Mixin(A)\n" +
61+
" static class D {\n" +
62+
" void test() {\n" +
63+
" print b\n" +
64+
" }\n" +
65+
" }\n" +
66+
"}\n" +
67+
"new C.D().test()\n",
68+
};
69+
//@formatter:on
70+
71+
runConformTest(sources, "works");
72+
}
73+
}

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

-5
Original file line numberDiff line numberDiff line change
@@ -2893,11 +2893,6 @@ public void testCompileStatic9043_staticInnerToPackage2() {
28932893
"1. ERROR in Main.groovy (at line 6)\n" +
28942894
"\tprint value\n" +
28952895
"\t ^^^^^\n" +
2896-
"Groovy:Apparent variable 'value' was found in a static scope but doesn't refer to a local variable, static field or class.\n" +
2897-
"----------\n" +
2898-
"2. ERROR in Main.groovy (at line 6)\n" +
2899-
"\tprint value\n" +
2900-
"\t ^^^^^\n" +
29012896
"Groovy:[Static type checking] - The variable [value] is undeclared.\n" +
29022897
"----------\n");
29032898
}

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/package.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<li>@groovy.lang.Grapes</li>
1313
</ul>
1414
<li>@groovy.lang.Lazy</li>
15-
<li>@groovy.lang.Mixin</li>
15+
<li>@groovy.lang.Mixin&nbsp;&#x2713;</li>
1616
<li>@groovy.lang.Newify</li>
1717
<li>@groovy.lang.Singleton&nbsp;&#x2713;</li>
1818

base/org.codehaus.groovy25/src/org/codehaus/groovy/classgen/VariableScopeVisitor.java

+15-6
Original file line numberDiff line numberDiff line change
@@ -233,23 +233,32 @@ private Variable findVariableDeclaration(final String name) {
233233
ClassNode node = scope.getClassScope();
234234
if (node != null) {
235235
Variable member = findClassMember(node, name);
236+
/* GRECLIPSE edit -- GROOVY-5364, GROOVY-10200
236237
while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
237238
crossingStaticContext = (crossingStaticContext || isStatic(node.getModifiers()));
238239
member = findClassMember((node = node.getOuterClass()), name);
239240
}
240241
if (member != null) {
241242
boolean staticScope = (crossingStaticContext || inSpecialConstructorCall), staticMember = member.isInStaticContext();
242243
// prevent a static context (e.g. a static method) from accessing a non-static variable (e.g. a non-static field)
243-
/* GRECLIPSE edit -- GROOVY-5364
244244
if (!(staticScope && !staticMember)) {
245-
*/
246-
if (!(staticScope ? !staticMember : node.isScript())) {
247-
// GRECLIPSE end
248245
variable = member;
249246
}
250247
}
251-
// GROOVY-5961
252-
if (!isAnonymous(scope.getClassScope())) break;
248+
*/
249+
boolean requireStatic = (crossingStaticContext || inSpecialConstructorCall);
250+
while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
251+
requireStatic = requireStatic || isStatic(node.getModifiers());
252+
member = findClassMember((node = node.getOuterClass()), name);
253+
}
254+
if (member != null) {
255+
// prevent a static context (e.g. a static method) from accessing a non-static member (e.g. a non-static field)
256+
if (requireStatic ? member.isInStaticContext() : !node.isScript()) {
257+
variable = member;
258+
}
259+
}
260+
// GRECLIPSE end
261+
if (!isAnonymous(scope.getClassScope())) break; // GROOVY-5961
253262
}
254263
scope = scope.getParent();
255264
}

base/org.codehaus.groovy30/src/org/codehaus/groovy/classgen/VariableScopeVisitor.java

+15-6
Original file line numberDiff line numberDiff line change
@@ -236,23 +236,32 @@ private Variable findVariableDeclaration(final String name) {
236236
ClassNode node = scope.getClassScope();
237237
if (node != null) {
238238
Variable member = findClassMember(node, name);
239+
/* GRECLIPSE edit -- GROOVY-5364, GROOVY-10200
239240
while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
240241
crossingStaticContext = (crossingStaticContext || isStatic(node.getModifiers()));
241242
member = findClassMember((node = node.getOuterClass()), name);
242243
}
243244
if (member != null) {
244245
boolean staticScope = (crossingStaticContext || inSpecialConstructorCall), staticMember = member.isInStaticContext();
245246
// prevent a static context (e.g. a static method) from accessing a non-static variable (e.g. a non-static field)
246-
/* GRECLIPSE edit -- GROOVY-5364
247247
if (!(staticScope && !staticMember)) {
248-
*/
249-
if (!(staticScope ? !staticMember : node.isScript())) {
250-
// GRECLIPSE end
251248
variable = member;
252249
}
253250
}
254-
// GROOVY-5961
255-
if (!isAnonymous(scope.getClassScope())) break;
251+
*/
252+
boolean requireStatic = (crossingStaticContext || inSpecialConstructorCall);
253+
while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
254+
requireStatic = requireStatic || isStatic(node.getModifiers());
255+
member = findClassMember((node = node.getOuterClass()), name);
256+
}
257+
if (member != null) {
258+
// prevent a static context (e.g. a static method) from accessing a non-static member (e.g. a non-static field)
259+
if (requireStatic ? member.isInStaticContext() : !node.isScript()) {
260+
variable = member;
261+
}
262+
}
263+
// GRECLIPSE end
264+
if (!isAnonymous(scope.getClassScope())) break; // GROOVY-5961
256265
}
257266
scope = scope.getParent();
258267
}

base/org.codehaus.groovy40/src/org/codehaus/groovy/classgen/VariableScopeVisitor.java

+15-6
Original file line numberDiff line numberDiff line change
@@ -236,23 +236,32 @@ private Variable findVariableDeclaration(final String name) {
236236
ClassNode node = scope.getClassScope();
237237
if (node != null) {
238238
Variable member = findClassMember(node, name);
239+
/* GRECLIPSE edit -- GROOVY-5364, GROOVY-10200
239240
while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
240241
crossingStaticContext = (crossingStaticContext || isStatic(node.getModifiers()));
241242
member = findClassMember((node = node.getOuterClass()), name);
242243
}
243244
if (member != null) {
244245
boolean staticScope = (crossingStaticContext || inSpecialConstructorCall), staticMember = member.isInStaticContext();
245246
// prevent a static context (e.g. a static method) from accessing a non-static variable (e.g. a non-static field)
246-
/* GRECLIPSE edit -- GROOVY-5364
247247
if (!(staticScope && !staticMember)) {
248-
*/
249-
if (!(staticScope ? !staticMember : node.isScript())) {
250-
// GRECLIPSE end
251248
variable = member;
252249
}
253250
}
254-
// GROOVY-5961
255-
if (!isAnonymous(scope.getClassScope())) break;
251+
*/
252+
boolean requireStatic = (crossingStaticContext || inSpecialConstructorCall);
253+
while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
254+
requireStatic = requireStatic || isStatic(node.getModifiers());
255+
member = findClassMember((node = node.getOuterClass()), name);
256+
}
257+
if (member != null) {
258+
// prevent a static context (e.g. a static method) from accessing a non-static member (e.g. a non-static field)
259+
if (requireStatic ? member.isInStaticContext() : !node.isScript()) {
260+
variable = member;
261+
}
262+
}
263+
// GRECLIPSE end
264+
if (!isAnonymous(scope.getClassScope())) break; // GROOVY-5961
256265
}
257266
scope = scope.getParent();
258267
}

ide-test/org.codehaus.groovy.alltests/src/org/codehaus/groovy/alltests/GroovyJDTTests.groovy

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import org.junit.runners.Suite
5050
org.eclipse.jdt.groovy.core.tests.xform.ImmutableTests,
5151
org.eclipse.jdt.groovy.core.tests.xform.InheritConstructorsTests,
5252
org.eclipse.jdt.groovy.core.tests.xform.LoggingTests,
53+
org.eclipse.jdt.groovy.core.tests.xform.MixinTests,
5354
org.eclipse.jdt.groovy.core.tests.xform.NamedVariantTests,
5455
org.eclipse.jdt.groovy.core.tests.xform.NullCheckTests,
5556
org.eclipse.jdt.groovy.core.tests.xform.PackageScopeTests,

0 commit comments

Comments
 (0)