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/03/11 18:19:32 UTC
[groovy] 01/02: GROOVY-10180: STC: method lookup: try instanceof type(s) before declared
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit d4eee1057af17d5f8d007859f1eecb3ffce219d2
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Jul 23 17:40:13 2021 -0500
GROOVY-10180: STC: method lookup: try instanceof type(s) before declared
- better match for "each" using Map vs. Object:
void test(obj) { if (obj instanceof Map) obj.each { e -> } }
---
.../transform/stc/StaticTypeCheckingVisitor.java | 54 +++++++--------
.../stc/ClosureParamTypeInferenceSTCTest.groovy | 79 ++++++++++++----------
2 files changed, 71 insertions(+), 62 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 2c67eca..4e294c6 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3779,40 +3779,40 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
protected List<Receiver<String>> makeOwnerList(final Expression objectExpression) {
ClassNode receiver = getType(objectExpression);
List<Receiver<String>> owners = new ArrayList<>();
- if (isClassClassNodeWrappingConcreteType(receiver)) {
- ClassNode staticType = receiver.getGenericsTypes()[0].getType();
- owners.add(Receiver.make(staticType)); // Type from Class<Type>
- addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
- owners.add(Receiver.make(receiver)); // Class<Type>
- } else {
- owners.add(Receiver.make(receiver));
- if (receiver.isInterface()) {
- owners.add(Receiver.make(OBJECT_TYPE));
- }
- addSelfTypes(receiver, owners);
- addTraitType(receiver, owners);
- }
- if (!typeCheckingContext.temporaryIfBranchTypeInformation.isEmpty()) {
- List<ClassNode> potentialReceiverType = getTemporaryTypesForExpression(objectExpression);
- if (potentialReceiverType != null && !potentialReceiverType.isEmpty()) {
- for (ClassNode node : potentialReceiverType) {
- owners.add(Receiver.make(node));
- }
- }
- }
- if (typeCheckingContext.lastImplicitItType != null
- && objectExpression instanceof VariableExpression
- && ((VariableExpression) objectExpression).getName().equals("it")) {
- owners.add(Receiver.make(typeCheckingContext.lastImplicitItType));
- }
if (typeCheckingContext.delegationMetadata != null
&& objectExpression instanceof VariableExpression
&& ((VariableExpression) objectExpression).getName().equals("owner")
&& /*isNested:*/typeCheckingContext.delegationMetadata.getParent() != null) {
- owners.clear();
List<Receiver<String>> enclosingClass = Collections.singletonList(
Receiver.make(typeCheckingContext.getEnclosingClassNode()));
addReceivers(owners, enclosingClass, typeCheckingContext.delegationMetadata.getParent(), "owner.");
+ } else {
+ if (!typeCheckingContext.temporaryIfBranchTypeInformation.isEmpty()) {
+ List<ClassNode> potentialReceiverType = getTemporaryTypesForExpression(objectExpression);
+ if (potentialReceiverType != null && !potentialReceiverType.isEmpty()) {
+ for (ClassNode node : potentialReceiverType) {
+ owners.add(Receiver.make(node));
+ }
+ }
+ }
+ if (typeCheckingContext.lastImplicitItType != null
+ && objectExpression instanceof VariableExpression
+ && ((VariableExpression) objectExpression).getName().equals("it")) {
+ owners.add(Receiver.make(typeCheckingContext.lastImplicitItType));
+ }
+ if (isClassClassNodeWrappingConcreteType(receiver)) {
+ ClassNode staticType = receiver.getGenericsTypes()[0].getType();
+ owners.add(Receiver.make(staticType)); // Type from Class<Type>
+ addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
+ owners.add(Receiver.make(receiver)); // Class<Type>
+ } else {
+ owners.add(Receiver.make(receiver));
+ addSelfTypes(receiver, owners);
+ addTraitType(receiver, owners);
+ if (receiver.isInterface()) {
+ owners.add(Receiver.make(OBJECT_TYPE));
+ }
+ }
}
return owners;
}
diff --git a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index bc0ac8a..d2d86a9 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -22,22 +22,41 @@ package groovy.transform.stc
* Unit tests for static type checking : closure parameter type inference.
*/
class ClosureParamTypeInferenceSTCTest extends StaticTypeCheckingTestCase {
- void testInferenceForDGM_CollectUsingExplicitIt() {
+
+ void testInferenceForDGM_collectUsingExplicitIt() {
assertScript '''
['a','b'].collect { it -> it.toUpperCase() }
'''
- }
-
- void testInferenceForDGM_CollectUsingExplicitItAndIncorrectType() {
shouldFailWithMessages '''
['a','b'].collect { Date it -> it.toUpperCase() }
''', 'Expected parameter of type java.lang.String but got java.util.Date'
}
- void testInferenceForDGM_CollectUsingImplicitIt() {
+ void testInferenceForDGM_collectUsingImplicitIt() {
assertScript '''
['a','b'].collect { it.toUpperCase() }
'''
+ assertScript '''
+ def items = []
+ ['a','b','c'].collect(items) { it.toUpperCase() }
+ '''
+ assertScript '''
+ String[] array = ['foo', 'bar', 'baz']
+ assert array.collect { it.startsWith('ba') } == [false, true, true]
+ '''
+ assertScript '''
+ List<Boolean> answer = [true]
+ String[] array = ['foo', 'bar', 'baz']
+ array.collect(answer){it.startsWith('ba')}
+ assert answer == [true, false, true, true]
+ '''
+ assertScript '''
+ Iterator<String> iter = ['foo', 'bar', 'baz'].iterator()
+ assert iter.collect { it.startsWith('ba') } == [false, true, true]
+ '''
+ assertScript '''
+ assert [1234, 3.14].collect { it.intValue() } == [1234,3]
+ '''
}
void testInferenceForDGM_eachUsingExplicitIt() {
@@ -52,12 +71,6 @@ class ClosureParamTypeInferenceSTCTest extends StaticTypeCheckingTestCase {
'''
}
- void testInferenceForDGM_CollectUsingImplicitItAndLUB() {
- assertScript '''
- assert [1234, 3.14].collect { it.intValue() } == [1234,3]
- '''
- }
-
void testInferenceForDGM_countUsingFirstSignature() {
assertScript '''
def src = [a: 1, b:2, c:3]
@@ -103,13 +116,6 @@ assert result == ['b', 'r', 'e', 'a', 'd', 'b', 'u', 't', 't', 'e', 'r']
'''
}
- void testInferenceForDGM_Collect2() {
- assertScript '''
-def items = []
-['a','b','c'].collect(items) { it.toUpperCase() }
-'''
- }
-
void testInferenceForDGM_CollectMap() {
assertScript '''
assert [a: 'foo',b:'bar'].collect { k,v -> k+v } == ['afoo','bbar']
@@ -221,23 +227,6 @@ def items = []
'''
}
- void testDGM_collectOnArray() {
- assertScript '''
- String[] arr = ['foo', 'bar', 'baz']
- assert arr.collect { it.startsWith('ba') } == [false, true, true]
- List<Boolean> answer = [true]
- arr.collect(answer) { it.startsWith('ba') }
- assert answer == [true, false, true, true]
- '''
- }
-
- void testDGM_collectOnIterator() {
- assertScript '''
- Iterator<String> itr = ['foo', 'bar', 'baz'].iterator()
- assert itr.collect { it.startsWith('ba') } == [false, true, true]
- '''
- }
-
void testInferenceOnNonExtensionMethod() {
assertScript '''import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FirstParam
@@ -1497,4 +1486,24 @@ method()
assert iterable.collect { it.prop } == ['x', 'y', 'z']
'''
}
+
+ void testGroovy10180() {
+ assertScript '''
+ void test(args) {
+ if (args instanceof Map) {
+ args.each { e ->
+ def k = e.key, v = e.value
+ }
+ }
+ }
+ '''
+ assertScript '''
+ void test(args) {
+ if (args instanceof Map) {
+ args.each { k, v ->
+ }
+ }
+ }
+ '''
+ }
}