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 6e5b36fa2d7e1962b8c71a6b912c27bccb3e2ae8 Author: Eric Milles <[email protected]> AuthorDate: Fri Jul 23 14:24:04 2021 -0500 GROOVY-10179: STC: for-in collection type: consider instanceof flow-type --- .../transform/stc/StaticTypeCheckingVisitor.java | 7 ++- src/test/groovy/transform/stc/LoopsSTCTest.groovy | 66 ++++++++++++++++++++- .../classgen/asm/sc/bugs/Groovy6240Bug.groovy | 69 ---------------------- 3 files changed, 69 insertions(+), 73 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 795b0ba..897e5ba 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -1872,7 +1872,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { super.visitForLoop(forLoop); } else { collectionExpression.visit(this); - ClassNode collectionType = getType(collectionExpression); + ClassNode collectionType; + if (collectionExpression instanceof VariableExpression && hasInferredReturnType(collectionExpression)) { + collectionType = getInferredReturnType(collectionExpression); + } else { + collectionType = getType(collectionExpression); + } ClassNode forLoopVariableType = forLoop.getVariableType(); ClassNode componentType; if (Character_TYPE.equals(getWrapper(forLoopVariableType)) && STRING_TYPE.equals(collectionType)) { diff --git a/src/test/groovy/transform/stc/LoopsSTCTest.groovy b/src/test/groovy/transform/stc/LoopsSTCTest.groovy index 6a9bff6..2798cfb 100644 --- a/src/test/groovy/transform/stc/LoopsSTCTest.groovy +++ b/src/test/groovy/transform/stc/LoopsSTCTest.groovy @@ -128,9 +128,9 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase { } // GROOVY-5587 - void testMapEntryInForInLoop() { + void testForInLoopOnMap1() { assertScript ''' - @ASTTest(phase=INSTRUCTION_SELECTION, value= { + @ASTTest(phase=INSTRUCTION_SELECTION, value={ lookup('forLoop').each { assert it instanceof org.codehaus.groovy.ast.stmt.ForStatement def collection = it.collectionExpression // MethodCallExpression @@ -157,6 +157,67 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase { ''' } + // GROOVY-6240 + void testForInLoopOnMap2() { + assertScript ''' + Map<String, Integer> map = [foo: 123, bar: 456] + for (entry in map) { + assert entry.key.reverse() in ['oof','rab'] + assert entry.value * 2 in [246, 912] + } + ''' + } + + void testForInLoopOnMap3() { + assertScript ''' + class MyMap extends LinkedHashMap<String,Integer> { + } + def map = new MyMap([foo: 123, bar: 456]) + for (entry in map) { + assert entry.key.reverse() in ['oof','rab'] + assert entry.value * 2 in [246, 912] + } + ''' + } + + // GROOVY-10179 + void testForInLoopOnMap4() { + assertScript ''' + void test(args) { + if (args instanceof Map) { + for (e in args) { + print "$e.key $e.value" + } + } + } + test(a:1,b:2,c:3.14) + ''' + } + + // GROOVY-6123 + void testForInLoopOnEnumeration() { + assertScript ''' + Vector<String> v = new Vector<>() + v.add('ooo') + def en = v.elements() + for (e in en) { + assert e.toUpperCase() == 'OOO' + } + v.add('groovy') + en = v.elements() + for (e in en) { + assert e.toUpperCase() == 'OOO' + break + } + + en = v.elements() + for (e in en) { + assert e.toUpperCase() in ['OOO','GROOVY'] + if (e=='ooo') continue + } + ''' + } + void testShouldNotInferSoftReferenceAsComponentType() { assertScript '''import java.lang.reflect.Field import org.codehaus.groovy.ast.stmt.ForStatement @@ -233,4 +294,3 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase { ''' } } - diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6240Bug.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6240Bug.groovy deleted file mode 100644 index f263a44..0000000 --- a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6240Bug.groovy +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.codehaus.groovy.classgen.asm.sc.bugs - -import groovy.transform.stc.StaticTypeCheckingTestCase -import org.codehaus.groovy.classgen.asm.sc.StaticCompilationTestSupport - -class Groovy6240Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport { - void testGroovyAllowsIteratingOnMapDirectlyWithForEachLoop() { - assertScript ''' - Map<String, Integer> map = [foo: 123, bar: 456] - for (entry in map) { - assert entry.key.reverse() in ['oof','rab'] - assert entry.value * 2 in [246, 912] - } - ''' - } - - void testGroovyAllowsIteratingOnMapDirectlyWithForEachLoopCustomMapType() { - assertScript ''' - class MyMap extends LinkedHashMap<String,Integer>{} - def map = new MyMap([foo: 123, bar: 456]) - for (entry in map) { - assert entry.key.reverse() in ['oof','rab'] - assert entry.value * 2 in [246, 912] - } - ''' - } - - // GROOVY-6123 - void testGroovyAllowsIteratingOnEnumerationDirectlyWithForEachLoop() { - assertScript ''' - Vector<String> v = new Vector<>() - v.add('ooo') - def en = v.elements() - for (e in en) { - assert e.toUpperCase() == 'OOO' - } - v.add('groovy') - en = v.elements() - for (e in en) { - assert e.toUpperCase() == 'OOO' - break - } - - en = v.elements() - for (e in en) { - assert e.toUpperCase() in ['OOO','GROOVY'] - if (e=='ooo') continue - } - ''' - } -}
