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 17:23:59 UTC
[groovy] branch GROOVY_2_5_X 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 GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push:
new d40b7b9ac6 GROOVY-10922: STC: forthcoming generated property method stub
d40b7b9ac6 is described below
commit d40b7b9ac62b4520b30b42ef89e43aca80cbefc5
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Feb 2 10:11:46 2023 -0600
GROOVY-10922: STC: forthcoming generated property method stub
2_5_X backport
---
.../transform/stc/StaticTypeCheckingVisitor.java | 37 ++++++++++++++--------
.../groovy/transform/stc/MethodCallsSTCTest.groovy | 26 +++++++++++++++
2 files changed, 49 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 e560554a7a..f537530389 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4756,7 +4756,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
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<MethodNode>();
for (MethodNode method : methods) {
@@ -4812,12 +4812,19 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
return result;
}
+ private static boolean allAbstract(final List<? extends MethodNode> methods) {
+ for (MethodNode method : methods) {
+ if (!method.isAbstract()) return false;
+ }
+ return true;
+ }
+
protected List<MethodNode> findMethod(ClassNode receiver, final String name, final ClassNode... args) {
if (isPrimitiveType(receiver)) receiver = getWrapper(receiver);
List<MethodNode> methods;
if ("<init>".equals(name) && !receiver.isInterface()) {
- methods = addGeneratedMethods(receiver, new ArrayList<MethodNode>(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);
@@ -4841,33 +4848,35 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
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);
}
if (pname != null) {
PropertyNode property = findProperty(receiver, pname);
- 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 != null && args.length == 1) {
- // maybe we are looking for a setter ?
+ } else if (args.length == 1 && (methods.isEmpty() || allAbstract(methods))) { // 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())) {
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);
}
}
}
@@ -5518,7 +5527,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
params = ((ExtensionMethodNode) target).getExtensionMethodNode().getParameters();
} else if (!target.isStatic() && source.getExpression() instanceof ClassExpression) {
ClassNode thisType = ((ClassExpression) source.getExpression()).getType();
- // there is an implicit parameter for "String::length"
+ // there is an implicit parameter for "String.&length"
int n = target.getParameters().length;
params = new Parameter[n + 1];
params[0] = new Parameter(thisType, "");
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index 735fac4908..de4e7ef0ed 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -201,6 +201,32 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
''', 'Cannot call groovy.transform.stc.MethodCallsSTCTest$MyMethodCallTestClass2 <Integer>#identity(java.lang.Integer[]) with arguments [java.lang.String[]]'
}
+ // 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 {