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 2022/08/16 15:46:37 UTC
[groovy] branch master updated: GROOVY-8828: STC: `UnionTypeClassNode` plain node reference semantics
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 0d07740929 GROOVY-8828: STC: `UnionTypeClassNode` plain node reference semantics
0d07740929 is described below
commit 0d0774092977e93351182e32a1fd9349f0a2a23c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Aug 16 10:17:13 2022 -0500
GROOVY-8828: STC: `UnionTypeClassNode` plain node reference semantics
---
.../transform/stc/StaticTypeCheckingSupport.java | 27 +++++++++-------------
.../groovy/transform/stc/UnionTypeClassNode.java | 23 ++++++++++++------
.../transform/stc/TypeInferenceSTCTest.groovy | 16 +++++++++++++
3 files changed, 43 insertions(+), 23 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 1fcab91150..4d4090fc82 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -889,31 +889,26 @@ public abstract class StaticTypeCheckingSupport {
}
public static boolean implementsInterfaceOrIsSubclassOf(final ClassNode type, final ClassNode superOrInterface) {
- boolean result = (type.equals(superOrInterface)
+ if (type.isArray() && superOrInterface.isArray()) {
+ return implementsInterfaceOrIsSubclassOf(type.getComponentType(), superOrInterface.getComponentType());
+ }
+ if (type == UNKNOWN_PARAMETER_TYPE // aka null
|| type.isDerivedFrom(superOrInterface)
- || type.implementsInterface(superOrInterface)
- || type == UNKNOWN_PARAMETER_TYPE);
- if (result) {
+ || type.implementsInterface(superOrInterface)) {
return true;
}
if (superOrInterface instanceof WideningCategories.LowestUpperBoundClassNode) {
- WideningCategories.LowestUpperBoundClassNode cn = (WideningCategories.LowestUpperBoundClassNode) superOrInterface;
- result = implementsInterfaceOrIsSubclassOf(type, cn.getSuperClass());
- if (result) {
- for (ClassNode interfaceNode : cn.getInterfaces()) {
- result = type.implementsInterface(interfaceNode);
- if (!result) break;
- }
+ if (implementsInterfaceOrIsSubclassOf(type, superOrInterface.getSuperClass())
+ && Arrays.stream(superOrInterface.getInterfaces()).allMatch(type::implementsInterface)) {
+ return true;
}
- if (result) return true;
} else if (superOrInterface instanceof UnionTypeClassNode) {
for (ClassNode delegate : ((UnionTypeClassNode) superOrInterface).getDelegates()) {
- if (implementsInterfaceOrIsSubclassOf(type, delegate)) return true;
+ if (implementsInterfaceOrIsSubclassOf(type, delegate)) {
+ return true;
+ }
}
}
- if (type.isArray() && superOrInterface.isArray()) {
- return implementsInterfaceOrIsSubclassOf(type.getComponentType(), superOrInterface.getComponentType());
- }
if (isGroovyObjectType(superOrInterface) && isBeingCompiled(type) && !type.isInterface()) {//TODO: !POJO !Trait
return true;
}
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/UnionTypeClassNode.java b/src/main/java/org/codehaus/groovy/transform/stc/UnionTypeClassNode.java
index 1513421c27..7d79463d8d 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/UnionTypeClassNode.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/UnionTypeClassNode.java
@@ -43,6 +43,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.StringJoiner;
/**
* This class node type is very special and should only be used by the static type checker
@@ -57,18 +58,17 @@ import java.util.Set;
class UnionTypeClassNode extends ClassNode {
private final ClassNode[] delegates;
- public UnionTypeClassNode(ClassNode... classNodes) {
- super("<UnionType:" + asArrayDescriptor(classNodes) + ">", 0, ClassHelper.OBJECT_TYPE);
+ UnionTypeClassNode(final ClassNode... classNodes) {
+ super(makeName(classNodes), 0, ClassHelper.OBJECT_TYPE);
delegates = classNodes == null ? ClassNode.EMPTY_ARRAY : classNodes;
}
- private static String asArrayDescriptor(ClassNode... nodes) {
- StringBuilder sb = new StringBuilder();
+ private static String makeName(final ClassNode[] nodes) {
+ StringJoiner sj = new StringJoiner("+", "<UnionType:", ">");
for (ClassNode node : nodes) {
- if (sb.length() > 0) sb.append("+");
- sb.append(node.getText());
+ sj.add(node.getText());
}
- return sb.toString();
+ return sj.toString();
}
public ClassNode[] getDelegates() {
@@ -306,6 +306,15 @@ class UnionTypeClassNode extends ClassNode {
return nodes;
}
+ @Override
+ public ClassNode getPlainNodeReference(final boolean skipPrimitives) {
+ int n = delegates.length; ClassNode[] plainNodes = new ClassNode[n];
+ for (int i = 0; i < n; i += 1) {
+ plainNodes[i] = delegates[i].getPlainNodeReference(skipPrimitives);
+ }
+ return new UnionTypeClassNode(plainNodes);
+ }
+
@Override
public List<PropertyNode> getProperties() {
List<PropertyNode> nodes = new LinkedList<PropertyNode>();
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index c172240660..372cc054c8 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -396,6 +396,22 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
}
}
+ // GROOVY-8828
+ void testMultipleInstanceOf7() {
+ assertScript '''
+ interface Foo { }
+ interface Bar { String name() }
+
+ Map<String, Foo> map = [:]
+ map.values().each { foo ->
+ if (foo instanceof Bar) {
+ String name = foo.name() // method available through Bar
+ map.put(name, foo) // second parameter expects Foo
+ }
+ }
+ '''
+ }
+
// GROOVY-8523
void testNotInstanceof1() {
assertScript '''