Skip to content

Commit 81b1cc7

Browse files
committed
GROOVY-7994: Anonymous inner class believes protected method in parent's superclass returns Object
1 parent ad56669 commit 81b1cc7

File tree

2 files changed

+79
-2
lines changed

2 files changed

+79
-2
lines changed

src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,9 +1250,9 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean re
12501250
if (storeField(field, isThisExpression, pexp, receiver.getType(), visitor, receiver.getData(), !readMode))
12511251
return true;
12521252

1253-
MethodNode getter = current.getGetterMethod("get" + capName);
1253+
MethodNode getter = findGetter(current, "get" + capName, pexp.isImplicitThis());
12541254
getter = allowStaticAccessToMember(getter, staticOnly);
1255-
if (getter == null) getter = current.getGetterMethod("is" + capName);
1255+
if (getter == null) getter = findGetter(current, "is" + capName, pexp.isImplicitThis());
12561256
getter = allowStaticAccessToMember(getter, staticOnly);
12571257
final String setterName = "set" + capName;
12581258
List<MethodNode> setters = findSetters(current, setterName, false);
@@ -1362,6 +1362,14 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean re
13621362
return foundGetterOrSetter;
13631363
}
13641364

1365+
private MethodNode findGetter(ClassNode current, String name, boolean searchOuterClasses) {
1366+
MethodNode getterMethod = current.getGetterMethod(name);
1367+
if (getterMethod == null && searchOuterClasses && current instanceof InnerClassNode) {
1368+
return findGetter(current.getOuterClass(), name, true);
1369+
}
1370+
return getterMethod;
1371+
}
1372+
13651373
private ClassNode getTypeForSpreadExpression(ClassNode testClass, ClassNode objectExpressionType, PropertyExpression pexp) {
13661374
if (!pexp.isSpreadSafe()) return null;
13671375
MethodCallExpression mce = new MethodCallExpression(new VariableExpression("_", testClass), "iterator", ArgumentListExpression.EMPTY_ARGUMENTS);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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 groovy.bugs
20+
21+
class Groovy7994Bug extends GroovyTestCase {
22+
void testJavaBeanPropertiesAvailableInInnerClasses() {
23+
assertScript '''
24+
import groovy.transform.CompileStatic
25+
26+
@CompileStatic
27+
class Outer {
28+
String prop = 'wally'
29+
String getName() { "sally" }
30+
class Inner {
31+
String innerGo() { new Other(name).text + new Other(Outer.this.name).text + new Other(getName()).text }
32+
}
33+
String go() {
34+
new Other(name).text + new Other(getName()).text
35+
}
36+
def makeAIC() {
37+
new Object() {
38+
String aicGo() { new Other(name).text + new Other(Outer.this.name).text + new Other(getName()).text }
39+
String staticMethodGo() { Other.foo(name) + Other.foo(Outer.this.name) + Other.foo(getName()) }
40+
String instanceMethodGo() { new Other().bar(name) + new Other().bar(getName()) }
41+
String methodWithClosureGo() { new Other().with { bar(name) + bar(getName()) } }
42+
String propGo() { new Other(prop).text + new Other(getProp()).text }
43+
}
44+
}
45+
}
46+
47+
@CompileStatic
48+
class Other {
49+
public final String text
50+
static String foo(Object object) { "Object|$object:" }
51+
static String foo(String string) { "String|$string:" }
52+
String bar(Object object) { "Object|$object:" }
53+
String bar(String string) { "String|$string:" }
54+
Other(Object object) { text = "Object:$object|" }
55+
Other(String string) { text = "String:$string|" }
56+
Other() {}
57+
}
58+
59+
def o = new Outer()
60+
assert o.go() == 'String:sally|String:sally|'
61+
assert o.makeAIC().aicGo() == 'String:sally|String:sally|String:sally|'
62+
assert o.makeAIC().propGo() == 'String:wally|String:wally|'
63+
assert o.makeAIC().staticMethodGo() == 'String|sally:String|sally:String|sally:'
64+
assert o.makeAIC().instanceMethodGo() == 'String|sally:String|sally:'
65+
assert o.makeAIC().methodWithClosureGo() == 'String|sally:String|sally:'
66+
assert new Outer.Inner(o).innerGo() == 'String:sally|String:sally|String:sally|'
67+
'''
68+
}
69+
}

0 commit comments

Comments
 (0)