This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
new 5e82e1e42c GROOVY-11711: restore outer class generics after inner
class visit
5e82e1e42c is described below
commit 5e82e1e42c806623bdcc7c6aa5a4391ecc256718
Author: Eric Milles <[email protected]>
AuthorDate: Tue Jul 8 08:40:32 2025 -0500
GROOVY-11711: restore outer class generics after inner class visit
3_0_X backport
---
.../codehaus/groovy/control/ResolveVisitor.java | 26 ++++++++++++----------
src/test/gls/innerClass/InnerClassTest.groovy | 21 ++++++++++++++++-
2 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index e440d4ee8c..541cde99b8 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -1408,24 +1408,23 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
@Override
public void visitClass(final ClassNode node) {
- ClassNode oldNode = currentClass;
-
- currentClass = node;
-
+ ClassNode oldNode = currentClass; currentClass = node;
+ Map<GenericsTypeName, GenericsType> outerNames = null;
if (node instanceof InnerClassNode) {
- if (Modifier.isStatic(node.getModifiers())) {
- genericParameterNames = new HashMap<>();
+ outerNames = genericParameterNames;
+ genericParameterNames = new HashMap<>();
+ if (!Modifier.isStatic(node.getModifiers())) {
+ genericParameterNames.putAll(outerNames); // outer names
visible
}
-
- InnerClassNode innerClassNode = (InnerClassNode) node;
- if (innerClassNode.isAnonymous()) {
- MethodNode enclosingMethod =
innerClassNode.getEnclosingMethod();
- if (null != enclosingMethod) {
+ InnerClassNode innerClass = (InnerClassNode) node;
+ if (innerClass.isAnonymous()) {
+ MethodNode enclosingMethod = innerClass.getEnclosingMethod();
+ if (enclosingMethod != null) {
resolveGenericsHeader(enclosingMethod.getGenericsTypes());
}
}
} else {
- genericParameterNames = new HashMap<>();
+ genericParameterNames.clear(); // outer class: new generic
namespace
}
resolveGenericsHeader(node.getGenericsTypes());
@@ -1493,6 +1492,9 @@ public class ResolveVisitor extends
ClassCodeExpressionTransformer {
resolveOuterNestedClassFurther(node);
+ if (outerNames != null) // GROOVY-11711
+ genericParameterNames = outerNames;
+
currentClass = oldNode;
}
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy
b/src/test/gls/innerClass/InnerClassTest.groovy
index 74dbf5c20b..42d2cf60a0 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -1133,12 +1133,31 @@ final class InnerClassTest {
assert err =~ /No enclosing instance passed in constructor call of a
non-static inner class/
}
+ // GROOVY-11711
+ @Test
+ void testUsageOfOuterType6() {
+ assertScript '''
+ class Foo<T> {
+ static class Bar {
+ }
+ /*non-static*/ class Baz
+ implements java.util.concurrent.Callable<T> {
+ T call() {
+ }
+ }
+ }
+ def foo = new Foo<Short>()
+ def baz = new Foo.Baz(foo)
+ assert baz.call() == null
+ '''
+ }
+
@Test
void testClassOutputOrdering() {
// this does actually not do much, but before this
// change the inner class was tried to be executed
// because a class ordering bug. The main method
- // makes the Foo class executeable, but Foo$Bar is
+ // makes the Foo class executable, but Foo$Bar is
// not. So if Foo$Bar is returned, asserScript will
// fail. If Foo is returned, asserScript will not
// fail.