You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2023/02/02 16:23:41 UTC
[groovy] branch master updated: GROOVY-10922: STC: forthcoming generated property method stub
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 282ba5cd6d GROOVY-10922: STC: forthcoming generated property method stub
282ba5cd6d is described below
commit 282ba5cd6d74acbe7f8aa57244a82730d0aae2d5
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Feb 2 10:11:46 2023 -0600
GROOVY-10922: STC: forthcoming generated property method stub
---
.../transform/stc/StaticTypeCheckingVisitor.java | 31 ++++++++++++----------
.../groovy/transform/stc/MethodCallsSTCTest.groovy | 26 ++++++++++++++++++
2 files changed, 43 insertions(+), 14 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 9e0d5b9351..7971299de2 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4742,7 +4742,7 @@ out: if (mn.size() != 1) {
return methods;
}
- private static List<MethodNode> addGeneratedMethods(final ClassNode receiver, final List<MethodNode> methods) {
+ private static List<MethodNode> addGeneratedMethods(final ClassNode receiver, final List<? extends MethodNode> methods) {
// using a comparator of parameters
List<MethodNode> result = new LinkedList<>();
for (MethodNode method : methods) {
@@ -4802,7 +4802,7 @@ out: if (mn.size() != 1) {
List<MethodNode> methods;
if ("<init>".equals(name) && !receiver.isInterface()) {
- methods = addGeneratedMethods(receiver, new ArrayList<>(receiver.getDeclaredConstructors()));
+ methods = addGeneratedMethods(receiver, receiver.getDeclaredConstructors());
if (methods.isEmpty()) {
MethodNode node = new ConstructorNode(Opcodes.ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
node.setDeclaringClass(receiver);
@@ -4835,8 +4835,8 @@ out: if (mn.size() != 1) {
if (methods.isEmpty()) {
addArrayMethods(methods, receiver, name, args);
}
- if (methods.isEmpty() && (args == null || args.length == 0)) {
- // check if it's a property
+ if (args == null || args.length == 0) {
+ // check for property accessor
String pname = extractPropertyNameFromMethodName("get", name);
if (pname == null) {
pname = extractPropertyNameFromMethodName("is", name);
@@ -4855,24 +4855,27 @@ out: if (mn.size() != 1) {
}
}
}
- if (property != null) {
- int mods = Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0);
- MethodNode node = new MethodNode(name, mods, property.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
+ if (property != null && property.getDeclaringClass().getGetterMethod(name) == null) {
+ MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0),
+ property.getOriginType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
node.setDeclaringClass(property.getDeclaringClass());
- return Collections.singletonList(node);
+ node.setSynthetic(true);
+ methods.add(node);
}
- } else if (methods.isEmpty() && args.length == 1) {
- // maybe we are looking for a setter ?
+ } else if (args.length == 1 && (methods.isEmpty()
+ || methods.stream().allMatch(MethodNode::isAbstract))) { // GROOVY-10922
+ // check for property mutator
String pname = extractPropertyNameFromMethodName("set", name);
if (pname != null) {
PropertyNode property = findProperty(receiver, pname);
- if (property != null && !Modifier.isFinal(property.getModifiers())) {
+ if (property != null && !property.isFinal()) {
ClassNode type = property.getOriginType();
if (implementsInterfaceOrIsSubclassOf(wrapTypeIfNecessary(args[0]), wrapTypeIfNecessary(type))) {
- int mods = Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0);
- MethodNode node = new MethodNode(name, mods, VOID_TYPE, new Parameter[]{new Parameter(type, name)}, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
+ MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0),
+ VOID_TYPE, new Parameter[]{new Parameter(type, name)}, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
node.setDeclaringClass(property.getDeclaringClass());
- return Collections.singletonList(node);
+ node.setSynthetic(true);
+ methods.add(node);
}
}
}
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index 9fb1c016dd..2838725971 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -330,6 +330,32 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
'Default method m(T) requires qualified super'
}
+ // GROOVY-10922
+ void testCallToSuperGenerated() {
+ assertScript '''
+ interface Foo {
+ String getString()
+ void setString(String s)
+ }
+ class Bar implements Foo {
+ String string
+ }
+ class Baz extends Bar {
+ String object
+ @Override
+ void setString(String string) {
+ super.setString(string)
+ object = string
+ }
+ }
+;
+ def obj = new Baz()
+ obj.setString('xx')
+ assert obj.object == 'xx'
+ assert obj.string == 'xx'
+ '''
+ }
+
void testMethodCallFromSuperOwner() {
assertScript '''
class Child extends groovy.transform.stc.MethodCallsSTCTest.GroovyPage {