"Fossies" - the Fresh Open Source Software Archive

Member "groovy-3.0.9/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy" (3 Sep 2021, 18141 Bytes) of package /linux/misc/apache-groovy-src-3.0.9.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Java source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "ArraysAndCollectionsSTCTest.groovy": 3.0.9_vs_4.0.0-rc-1.

    1 /*
    2  *  Licensed to the Apache Software Foundation (ASF) under one
    3  *  or more contributor license agreements.  See the NOTICE file
    4  *  distributed with this work for additional information
    5  *  regarding copyright ownership.  The ASF licenses this file
    6  *  to you under the Apache License, Version 2.0 (the
    7  *  "License"); you may not use this file except in compliance
    8  *  with the License.  You may obtain a copy of the License at
    9  *
   10  *    http://www.apache.org/licenses/LICENSE-2.0
   11  *
   12  *  Unless required by applicable law or agreed to in writing,
   13  *  software distributed under the License is distributed on an
   14  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15  *  KIND, either express or implied.  See the License for the
   16  *  specific language governing permissions and limitations
   17  *  under the License.
   18  */
   19 package groovy.transform.stc
   20 
   21 /**
   22  * Unit tests for static type checking : arrays and collections.
   23  */
   24 class ArraysAndCollectionsSTCTest extends StaticTypeCheckingTestCase {
   25 
   26     void testArrayAccess() {
   27         assertScript '''
   28             String[] strings = ['a','b','c']
   29             String str = strings[0]
   30             assert str == 'a'
   31         '''
   32     }
   33 
   34     void testArrayElementTypeInference() {
   35         shouldFailWithMessages '''
   36             String[] strings = ['a','b','c']
   37             int str = strings[0]
   38         ''', 'Cannot assign value of type java.lang.String to variable of type int'
   39     }
   40 
   41     void testWrongComponentTypeInArray() {
   42         shouldFailWithMessages '''
   43             int[] intArray = ['a']
   44         ''', 'Cannot assign value of type java.lang.String into array of type int[]'
   45     }
   46 
   47     // GROOVY-9985, GROOVY-9994
   48     void testWrongComponentTypeInArrayInitializer() {
   49         shouldFailWithMessages '''
   50             new int['a']
   51         ''', 'Cannot convert from java.lang.String to int'
   52         shouldFailWithMessages '''
   53             new int[]{'a'}
   54         ''', 'Cannot convert from java.lang.String to int'
   55         shouldFailWithMessages '''
   56             new Integer[]{new Object(),1}
   57         ''', 'Cannot convert from java.lang.Object to java.lang.Integer'
   58     }
   59 
   60     // GROOVY-10111
   61     void testBoundedComponentTypeInArrayInitializer() {
   62         assertScript '''
   63             class C<X, Y> {
   64             }
   65             def <X extends C<Number, String>> X[] m() {
   66                 new X[]{new C<Number, String>()}
   67             }
   68         '''
   69     }
   70 
   71     void testConvertibleTypesInArrayInitializer() {
   72         assertScript '''
   73             def strings = new String[]{1,(long)2,(short)3}
   74             assert strings.every { it.class == String }
   75             assert strings.toString() == '[1, 2, 3]'
   76         '''
   77     }
   78 
   79     void testAssignValueInArrayWithCorrectType() {
   80         assertScript '''
   81             int[] arr2 = [1, 2, 3]
   82             arr2[1] = 4
   83         '''
   84     }
   85 
   86     void testAssignValueInArrayWithWrongType() {
   87         shouldFailWithMessages '''
   88             int[] arr2 = [1, 2, 3]
   89             arr2[1] = "One"
   90         ''', 'Cannot assign value of type java.lang.String to variable of type int'
   91     }
   92 
   93     void testBidimensionalArray() {
   94         assertScript '''
   95             int[][] arr2 = new int[1][]
   96             arr2[0] = [1,2]
   97         '''
   98     }
   99 
  100     void testBidimensionalArrayWithInitializer() {
  101         shouldFailWithMessages '''
  102             int[][] arr2 = new Object[1][]
  103         ''', 'Cannot assign value of type java.lang.Object[][] to variable of type int[][]'
  104     }
  105 
  106     void testBidimensionalArrayWithWrongSubArrayType() {
  107         shouldFailWithMessages '''
  108             int[][] arr2 = new int[1][]
  109             arr2[0] = ['1']
  110         ''', 'Cannot assign value of type java.lang.String into array of type int[]'
  111     }
  112 
  113     void testForLoopWithArrayAndUntypedVariable() {
  114         assertScript '''
  115             String[] arr = ['1','2','3']
  116             for (i in arr) { }
  117         '''
  118     }
  119 
  120     void testForLoopWithArrayAndWrongVariableType() {
  121         shouldFailWithMessages '''
  122             String[] arr = ['1','2','3']
  123             for (int i in arr) { }
  124         ''', 'Cannot loop with element of type int with collection of type java.lang.String[]'
  125     }
  126 
  127     void testJava5StyleForLoopWithArray() {
  128         assertScript '''
  129             String[] arr = ['1','2','3']
  130             for (String i : arr) { }
  131         '''
  132     }
  133 
  134     void testJava5StyleForLoopWithArrayAndIncompatibleType() {
  135         shouldFailWithMessages '''
  136             String[] arr = ['1','2','3']
  137             for (int i : arr) { }
  138         ''', 'Cannot loop with element of type int with collection of type java.lang.String[]'
  139     }
  140 
  141     void testForEachLoopOnString() {
  142         assertScript '''
  143             String name = 'Guillaume'
  144             for (String s in name) {
  145                 println s
  146             }
  147         '''
  148     }
  149 
  150     void testSliceInference() {
  151         assertScript '''
  152         List<String> foos = ['aa','bb','cc']
  153         foos[0].substring(1)
  154         def bars = foos[0..1]
  155         println bars[0].substring(1)
  156         '''
  157 
  158         assertScript '''
  159         def foos = ['aa','bb','cc']
  160         foos[0].substring(1)
  161         def bars = foos[0..1]
  162         println bars[0].substring(1)
  163         '''
  164 
  165         // GROOVY-5608
  166         assertScript '''
  167             List<Integer> a = [1, 3, 5]
  168 
  169             @ASTTest(phase = INSTRUCTION_SELECTION, value = {
  170                 def type = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
  171                 assert type == make(List)
  172                 assert type.genericsTypes.length == 1
  173                 assert type.genericsTypes[0].type == Integer_TYPE
  174             })
  175             List<Integer> b = a[1..2]
  176 
  177             List<Integer> c = (List<Integer>)a[1..2]
  178          '''
  179 
  180         // check that it also works for custom getAt methods
  181         assertScript '''
  182             class SpecialCollection {
  183                 List<Date> getAt(IntRange irange) {
  184                     return [new Date(), new Date()+1]
  185                 }
  186             }
  187 
  188             def sc = new SpecialCollection()
  189 
  190             @ASTTest(phase = INSTRUCTION_SELECTION, value = {
  191                 def type = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
  192                 assert type == make(List)
  193                 assert type.genericsTypes.length == 1
  194                 assert type.genericsTypes[0].type == make(Date)
  195             })
  196             List<Date> dates = sc[1..3]
  197         '''
  198     }
  199 
  200     void testListStarProperty() {
  201         assertScript '''
  202             List list = ['a','b','c']
  203             @ASTTest(phase=INSTRUCTION_SELECTION, value={
  204                 def iType = node.getNodeMetaData(INFERRED_TYPE)
  205                 assert iType == make(List)
  206                 assert iType.isUsingGenerics()
  207                 assert iType.genericsTypes[0].type == CLASS_Type
  208             })
  209             List classes = list*.class
  210             assert classes == [String,String,String]
  211             @ASTTest(phase=INSTRUCTION_SELECTION, value={
  212                 assert node.getNodeMetaData(INFERRED_TYPE) == CLASS_Type
  213             })
  214             def listClass = list.class
  215             assert listClass == ArrayList
  216         '''
  217     }
  218 
  219     void testListStarMethod() {
  220         assertScript '''
  221             List list = ['a','b','c']
  222             List classes = list*.toUpperCase()
  223             assert classes == ['A','B','C']
  224         '''
  225     }
  226 
  227     void testInferredMapDotProperty() {
  228         assertScript '''
  229             def map = [:]
  230             map['a'] = 1
  231             map.b = 2
  232         '''
  233     }
  234 
  235     void testInlineMap() {
  236 
  237         assertScript '''
  238             Map map = [a:1, b:2]
  239         '''
  240 
  241         assertScript '''
  242             def map = [a:1, b:2]
  243             map = [b:2, c:3]
  244         '''
  245 
  246         assertScript '''
  247             Map map = ['a':1, 'b':2]
  248         '''
  249     }
  250 
  251     void testAmbiguousCallWithVargs() {
  252         assertScript '''
  253             int sum(int x) { 1 }
  254             int sum(int... args) {
  255                 0
  256             }
  257             assert sum(1) == 1
  258         '''
  259     }
  260 
  261     void testAmbiguousCallWithVargs2() {
  262         assertScript '''
  263             int sum(int x) { 1 }
  264             int sum(int y, int... args) {
  265                 0
  266             }
  267             assert sum(1) == 1
  268         '''
  269     }
  270 
  271     void testCollectMethodCallOnList() {
  272         assertScript '''
  273             [1,2,3].collect { it.toString() }
  274         '''
  275     }
  276 
  277     void testForInLoop() {
  278         assertScript '''
  279             class A {
  280                 String name = 'foo'
  281             }
  282             List<A> myList = [new A(name:'Cedric'), new A(name:'Yakari')] as LinkedList<A>
  283             for (element in myList) {
  284                 element.name.toUpperCase()
  285             }
  286         '''
  287     }
  288 
  289     void testForInLoopWithDefaultListType() {
  290         assertScript '''
  291             class A {
  292                 String name = 'foo'
  293             }
  294             List<A> myList = [new A(name:'Cedric'), new A(name:'Yakari')]
  295             for (element in myList) {
  296                 element.name.toUpperCase()
  297             }
  298         '''
  299     }
  300 
  301     void testForInLoopWithRange() {
  302         assertScript '''
  303             for (int i in 1..10) { i*2 }
  304         '''
  305     }
  306 
  307     void testForInLoopWithRangeUsingVariable() {
  308         assertScript '''
  309             int n = 10
  310             for (int i in 1..n) {
  311                 @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  312                     assert node.getNodeMetaData(DECLARATION_INFERRED_TYPE) == int_TYPE
  313                 })
  314                 def k = i
  315             }
  316         '''
  317     }
  318 
  319     void testForInLoopWithRangeUsingComputedBound() {
  320         assertScript '''
  321             int n = 10
  322             for (int i in 1..(n-1)) {
  323                 @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  324                     assert node.getNodeMetaData(DECLARATION_INFERRED_TYPE) == int_TYPE
  325                 })
  326                 def k = i
  327             }
  328         '''
  329     }
  330 
  331     void testForInLoopWithRangeUsingListOfInts() {
  332         assertScript '''
  333             int n = 10
  334             for (int i in [-1,1]) {
  335                 @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  336                     assert node.getNodeMetaData(DECLARATION_INFERRED_TYPE) == int_TYPE
  337                 })
  338                 def k = i
  339             }
  340         '''
  341     }
  342 
  343     // GROOVY-5177
  344     void testShouldNotAllowArrayAssignment() {
  345         shouldFailWithMessages '''
  346             class Foo {
  347                 def say() {
  348                     FooAnother foo1 = new Foo[13] // but FooAnother foo1 = new Foo() reports a STC                        Error
  349                 }
  350             }
  351             class FooAnother {
  352 
  353             }
  354         ''', 'Cannot assign value of type Foo[] to variable of type FooAnother'
  355     }
  356 
  357     // GROOVY-9517
  358     void testShouldAllowArrayAssignment() {
  359         assertScript '''
  360             void test(File directory) {
  361                 File[] files = directory.listFiles()
  362                 files = files?.sort { it.name }
  363                 for (file in files) {
  364                     // ...
  365                 }
  366             }
  367             println 'works'
  368         '''
  369     }
  370 
  371     void testListPlusEquals() {
  372         assertScript '''
  373             List<String> list = ['a','b']
  374             list += ['c']
  375             assert list == ['a','b','c']
  376         '''
  377 
  378         assertScript '''
  379             Collection<String> list = ['a','b']
  380             list += 'c'
  381             assert list == ['a','b','c']
  382         '''
  383     }
  384 
  385     void testObjectArrayGet() {
  386         assertScript '''
  387             Object[] arr = [new Object()]
  388             arr.getAt(0)
  389         '''
  390     }
  391 
  392     void testStringArrayGet() {
  393         assertScript '''
  394             String[] arr = ['abc']
  395             arr.getAt(0)
  396         '''
  397     }
  398 
  399     void testObjectArrayPut() {
  400         assertScript '''
  401             Object[] arr = [new Object()]
  402             arr.putAt(0, new Object())
  403         '''
  404     }
  405 
  406     void testObjectArrayPutWithNull() {
  407         assertScript '''
  408             Object[] arr = [new Object()]
  409             arr.putAt(0, null)
  410         '''
  411     }
  412 
  413     void testStringArrayPut() {
  414         assertScript '''
  415             String[] arr = ['abc']
  416             arr.putAt(0, 'def')
  417         '''
  418     }
  419 
  420     void testStringArrayPutWithNull() {
  421         assertScript '''
  422             String[] arr = ['abc']
  423             arr.putAt(0, null)
  424         '''
  425     }
  426 
  427     void testStringArrayPutWithWrongType() {
  428         shouldFailWithMessages '''
  429             String[] arr = ['abc']
  430             arr.putAt(0, new Object())
  431         ''', 'Cannot call <T,U extends T> java.lang.String[]#putAt(int, U) with arguments [int, java.lang.Object]'
  432     }
  433 
  434     void testStringArrayPutWithSubType() {
  435         assertScript '''
  436             Serializable[] arr = ['abc']
  437             arr.putAt(0, new Integer(1))
  438         '''
  439     }
  440 
  441     void testStringArrayPutWithSubTypeAsPrimitive() {
  442         assertScript '''
  443             Serializable[] arr = ['abc']
  444             arr.putAt(0, 1)
  445         '''
  446     }
  447 
  448     void testStringArrayPutWithIncorrectSubType() {
  449         shouldFailWithMessages '''
  450             Serializable[] arr = ['abc']
  451             arr.putAt(0, new groovy.xml.XmlSlurper())
  452         ''', 'Cannot call <T,U extends T> java.io.Serializable[]#putAt(int, U) with arguments [int, groovy.xml.XmlSlurper]'
  453     }
  454 
  455     void testArrayGetOnPrimitiveArray() {
  456         assertScript '''
  457             int m() {
  458                 int[] arr = [1,2,3]
  459                 arr.getAt(1)
  460             }
  461             assert m()==2
  462         '''
  463     }
  464 
  465     void testReturnTypeOfArrayGet() {
  466         assertScript '''
  467             Serializable m() {
  468                 String[] arr = ['1','2','3']
  469                 arr.getAt(1)
  470             }
  471             assert m()=='2'
  472         '''
  473     }
  474 
  475     void testInferredTypeWithListAndFind() {
  476         assertScript '''List<Integer> list = [ 1, 2, 3, 4 ]
  477 
  478         @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  479             assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
  480         })
  481         Integer j = org.codehaus.groovy.runtime.DefaultGroovyMethods.find(list) { int it -> it%2 == 0 }
  482 
  483         @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  484             assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
  485         })
  486         Integer i = list.find { int it -> it % 2 == 0 }
  487         '''
  488     }
  489 
  490     // GROOVY-5573
  491     void testArrayNewInstance() {
  492         assertScript '''import java.lang.reflect.Array
  493             @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  494                 assert node.rightExpression.getNodeMetaData(INFERRED_TYPE) == OBJECT_TYPE
  495             })
  496             def object = Array.newInstance(Integer.class, 10)
  497             Object[] joinedArray = (Object[]) object
  498             assert joinedArray.length == 10
  499         '''
  500     }
  501 
  502     // GROOVY-5683
  503     void testArrayLengthOnMultidimensionalArray() {
  504         assertScript '''
  505             @ASTTest(phase=INSTRUCTION_SELECTION, value={
  506                 assert node.getNodeMetaData(INFERRED_TYPE) == int_TYPE.makeArray().makeArray()
  507             })
  508             int[][] array = [[1]] as int[][]
  509             array[0].length
  510         '''
  511     }
  512 
  513     // GROOVY-5797
  514     void testShouldAllowExpressionAsMapPropertyKey() {
  515         assertScript '''
  516         def m( Map param ) {
  517           def map = [ tim:4 ]
  518           map[ param.key ]
  519         }
  520 
  521         assert m( [ key: 'tim' ] ) == 4
  522         '''
  523     }
  524 
  525     // GROOVY-5793
  526     void testShouldNotForceAsTypeWhenListOfNullAssignedToArray() {
  527         assertScript '''
  528             Integer[] m() {
  529                 Integer[] array = [ null, null ]
  530                 return array
  531             }
  532             assert m().length == 2
  533         '''
  534     }
  535 
  536     void testShouldNotForceAsTypeWhenListOfNullAssignedToArrayUnlessPrimitive() {
  537         shouldFailWithMessages '''
  538             int[] m() {
  539                 int[] array = [ null, null ]
  540                 return array
  541             }
  542         ''', 'Cannot assign value of type java.lang.Object into array of type int[]'
  543     }
  544 
  545     // GROOVY-6131
  546     void testArraySetShouldGenerateBytecode() {
  547         shouldFailWithMessages '''
  548             void addToCollection(Collection coll, int index, val) {
  549                 coll[index] = val
  550             }
  551             def list = ['a']
  552             addToCollection(list, 0, 'b')
  553             assert list == ['b']
  554         ''', 'Cannot find matching method java.util.Collection#putAt(int, java.lang.Object)'
  555     }
  556 
  557     // GROOVY-6266
  558     void testMapKeyGenerics() {
  559         assertScript """
  560             HashMap<String,List<List>> AR=new HashMap<String,List<List>>()
  561             AR.get('key',[['val1'],['val2']])
  562             assert AR.'key'[0] == ['val1']
  563         """
  564     }
  565 
  566     // GROOVY-6311
  567     void testSetSpread() {
  568         assertScript """
  569             class Inner {Set<String> strings}
  570             class Outer {Set<Inner> inners}
  571             Outer outer = new Outer(inners: [ new Inner(strings: ['abc', 'def'] as Set), new Inner(strings: ['ghi'] as Set) ] as Set)
  572             def res = outer.inners*.strings
  573             assert res[1].contains('ghi')
  574             assert res[0].contains('abc')
  575             assert res[0].contains('def')
  576         """
  577     }
  578 
  579     // GROOVY-6241
  580     void testAsImmutable() {
  581         assertScript """
  582             List<Integer> list = [1, 2, 3]
  583             List<Integer> immutableList = [1, 2, 3].asImmutable()
  584             Map<String, Integer> map = [foo: 123, bar: 456]
  585             Map<String, Integer> immutableMap = [foo: 123, bar: 456].asImmutable()
  586         """
  587     }
  588 
  589     // GROOVY-6350
  590     void testListPlusList() {
  591         assertScript """
  592             def foo = [] + []
  593             assert foo==[]
  594         """
  595     }
  596 
  597     // GROOVY-7122
  598     void testIterableLoop() {
  599         assertScript '''
  600             int countIt(Iterable<Integer> list) {
  601                 int count = 0
  602                 for (Integer obj : list) {count ++}
  603                 return count
  604             }
  605             countIt([1,2,3])==3
  606         '''
  607     }
  608 
  609     // GROOVY-8033
  610     void testSetSpreadPropertyInStaticContext() {
  611         assertScript '''
  612             class Foo {
  613                 String name
  614             }
  615             static List<String> meth() {
  616                 Set<Foo> foos = [new Foo(name: 'pls'), new Foo(name: 'bar')].toSet()
  617                 foos*.name
  618             }
  619             assert meth().toSet() == ['pls', 'bar'].toSet()
  620         '''
  621     }
  622 }