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/07/29 13:37:34 UTC
[groovy] 01/02: GROOVY-8487: SC: for-in loop over iterator
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 437ca6abf8e9386c0217a40c74d0950efb23d35c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Jul 28 16:35:49 2022 -0500
GROOVY-8487: SC: for-in loop over iterator
---
.../asm/sc/StaticTypesStatementWriter.java | 36 ++++++++++++----------
.../groovy/runtime/DefaultGroovyMethods.java | 3 +-
src/test/groovy/transform/stc/LoopsSTCTest.groovy | 22 +++++++++++++
.../groovy/transform/stc/MethodCallsSTCTest.groovy | 11 -------
4 files changed, 44 insertions(+), 28 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesStatementWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesStatementWriter.java
index a61d4a27b8..7334f99a97 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesStatementWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesStatementWriter.java
@@ -219,23 +219,27 @@ public class StaticTypesStatementWriter extends StatementWriter {
}
private void writeIteratorBasedForEachLoop(final ForStatement loop, final Expression collectionExpression, final ClassNode collectionType) {
- // GROOVY-10476: BaseStream provides an iterator() but does not implement Iterable
- MethodNode iterator = collectionType.getMethod("iterator", Parameter.EMPTY_ARRAY);
- if (iterator == null) {
- iterator = GeneralUtils.getInterfacesAndSuperInterfaces(collectionType).stream()
- .map(in -> in.getMethod("iterator", Parameter.EMPTY_ARRAY))
- .filter(Objects::nonNull).findFirst().orElse(null);
- }
- if (iterator != null && iterator.getReturnType().equals(ClassHelper.Iterator_TYPE)) {
- MethodCallExpression call = GeneralUtils.callX(collectionExpression, "iterator");
- call.setImplicitThis(false);
- call.setMethodTarget(iterator);
- call.setSafe(true);//GROOVY-8643
- call.visit(controller.getAcg());
+ if (GeneralUtils.isOrImplements(collectionType, ClassHelper.Iterator_TYPE)) {
+ collectionExpression.visit(controller.getAcg()); // GROOVY-8487: iterator supplied
} else {
- collectionExpression.visit(controller.getAcg());
- controller.getMethodVisitor().visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/DefaultGroovyMethods", "iterator", "(Ljava/lang/Object;)Ljava/util/Iterator;", false);
- controller.getOperandStack().replace(ClassHelper.Iterator_TYPE);
+ // GROOVY-10476: BaseStream provides an iterator() but does not implement Iterable
+ MethodNode iterator = collectionType.getMethod("iterator", Parameter.EMPTY_ARRAY);
+ if (iterator == null) {
+ iterator = GeneralUtils.getInterfacesAndSuperInterfaces(collectionType).stream()
+ .map(in -> in.getMethod("iterator", Parameter.EMPTY_ARRAY))
+ .filter(Objects::nonNull).findFirst().orElse(null);
+ }
+ if (iterator != null && iterator.getReturnType().equals(ClassHelper.Iterator_TYPE)) {
+ MethodCallExpression call = GeneralUtils.callX(collectionExpression, "iterator");
+ call.setImplicitThis(false);
+ call.setMethodTarget(iterator);
+ call.setSafe(true);//GROOVY-8643
+ call.visit(controller.getAcg());
+ } else {
+ collectionExpression.visit(controller.getAcg());
+ controller.getMethodVisitor().visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/DefaultGroovyMethods", "iterator", "(Ljava/lang/Object;)Ljava/util/Iterator;", false);
+ controller.getOperandStack().replace(ClassHelper.Iterator_TYPE);
+ }
}
writeForInLoopControlAndBlock(loop);
}
diff --git a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index f9260d6b66..9402610ac8 100644
--- a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -18158,7 +18158,8 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
* @see org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation#asCollection(java.lang.Object)
* @since 1.0
*/
- public static Iterator iterator(Object o) {
+ public static Iterator iterator(final Object o) {
+ if (o instanceof Iterator) return (Iterator)o;
return DefaultTypeTransformation.asCollection(o).iterator();
}
diff --git a/src/test/groovy/transform/stc/LoopsSTCTest.groovy b/src/test/groovy/transform/stc/LoopsSTCTest.groovy
index 123232a179..70039d5b55 100644
--- a/src/test/groovy/transform/stc/LoopsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/LoopsSTCTest.groovy
@@ -215,6 +215,17 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-10476
+ void testForInLoopOnStream() {
+ assertScript '''
+ def list = []
+ for (item in ['a','b','c'].stream()) {
+ list.add(item.toUpperCase())
+ }
+ assert list == ['A','B','C']
+ '''
+ }
+
// GROOVY-8882
void testForInLoopOnString() {
assertScript '''
@@ -227,6 +238,17 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-8487
+ void testForInLoopOnIterator() {
+ assertScript '''
+ def list = []
+ for (item in ['a','b','c'].iterator()) {
+ list.add(item)
+ }
+ assert list.join('') == 'abc'
+ '''
+ }
+
// GROOVY-6123
void testForInLoopOnEnumeration() {
assertScript '''
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index 792b8e3b7d..01c3d1d27d 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -1196,17 +1196,6 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
'Cannot call closure that accepts [java.lang.String, java.lang.String, java.lang.String] with '
}
- // GROOVY-10476
- void testForInLoop() {
- assertScript '''
- def list = []
- for (item in ['a','b','c'].stream()) {
- list.add(item.toUpperCase())
- }
- assert list == ['A', 'B', 'C']
- '''
- }
-
void testBoxingShouldCostMore() {
assertScript '''
int foo(int x) { 1 }