Skip to content

Commit a31fd15

Browse files
committed
GROOVY-11877: anon. inner class is never static
1 parent 86477dc commit a31fd15

2 files changed

Lines changed: 52 additions & 2 deletions

File tree

src/main/java/org/codehaus/groovy/ast/InnerClassNode.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
import org.objectweb.asm.Opcodes;
2222

23+
import java.util.Collections;
24+
2325
/**
2426
* Represents an inner class definition.
2527
*/
@@ -75,11 +77,31 @@ public void setVariableScope(VariableScope scope) {
7577
this.scope = scope;
7678
}
7779

80+
@Override
81+
public boolean isSealed() {
82+
return !isAnonymous() && super.isSealed(); // JLS 15.9.5
83+
}
84+
7885
public boolean isAnonymous() {
7986
return anonymous;
8087
}
8188

82-
public void setAnonymous(boolean anonymous) {
83-
this.anonymous = anonymous;
89+
public void setAnonymous(final boolean anonymous) {
90+
if (this.anonymous != anonymous) {
91+
if (anonymous) { // JLS 15.9.5
92+
this.anonymous = true;
93+
94+
// GROOVY-11877
95+
int modifiers = getModifiers();
96+
modifiers &= ~Opcodes.ACC_STATIC;
97+
modifiers &= ~Opcodes.ACC_ABSTRACT;
98+
if (!isEnum()) modifiers &= ~Opcodes.ACC_FINAL;
99+
setModifiers(modifiers);
100+
101+
setPermittedSubclasses(Collections.emptyList());
102+
} else {
103+
throw new IllegalArgumentException("cannot demote anon. inner class");
104+
}
105+
}
84106
}
85107
}

src/test/groovy/gls/innerClass/InnerClassTest.groovy

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,34 @@ final class InnerClassTest {
8989
'''
9090
}
9191

92+
// GROOVY-11877
93+
@Test
94+
void testInnerAIC2() {
95+
assertScript '''import java.lang.reflect.Modifier
96+
interface I {
97+
def bar = new Object[1]
98+
def foo = new Runnable() {
99+
@Override
100+
void run() {
101+
bar[0] = true
102+
}
103+
}
104+
}
105+
106+
def obj = I.foo
107+
assert !I.bar[0]
108+
obj.run()
109+
assert I.bar[0]
110+
111+
def aic = obj.getClass()
112+
assert aic.getName() == 'I$1'
113+
assert aic.getEnclosingClass().getName() == 'I'
114+
assert !Modifier.isFinal (aic.getModifiers())
115+
assert !Modifier.isStatic (aic.getModifiers())
116+
assert !Modifier.isAbstract(aic.getModifiers())
117+
'''
118+
}
119+
92120
// GROOVY-11854
93121
@Test
94122
void testScriptAIC() {

0 commit comments

Comments
 (0)