"Fossies" - the Fresh Open Source Software Archive

Member "groovy-3.0.9/src/test/groovy/transform/stc/BugsSTCTest.groovy" (3 Sep 2021, 30523 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 "BugsSTCTest.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 import static groovy.test.GroovyAssert.isAtLeastJdk
   22 
   23 /**
   24  * Unit tests for static type checking : bug fixes.
   25  */
   26 class BugsSTCTest extends StaticTypeCheckingTestCase {
   27 
   28     // GROOVY-5456
   29     void testShouldNotAllowDivOnUntypedVariable() {
   30         shouldFailWithMessages '''
   31             def foo(Closure cls) {}
   32             def bar() { foo { it / 2 } }
   33         ''', 'Cannot find matching method java.lang.Object#div(int)'
   34     }
   35     void testShouldNotAllowDivBynUntypedVariable() {
   36         shouldFailWithMessages '''
   37             def foo(Closure cls) {}
   38             def bar() { foo { 2 / it } }
   39         ''', 'Cannot find matching method int#div(java.lang.Object)'
   40     }
   41     void testShouldNotAllowModOnUntypedVariable() {
   42         shouldFailWithMessages '''
   43             def foo(Closure cls) {}
   44             def bar() { foo { it % 2 } }
   45         ''', 'Cannot find matching method java.lang.Object#mod(int)'
   46     }
   47     void testShouldNotAllowModBynUntypedVariable() {
   48         shouldFailWithMessages '''
   49             def foo(Closure cls) {}
   50             def bar() { foo { 2 % it } }
   51         ''', 'Cannot find matching method int#mod(java.lang.Object)'
   52     }
   53     void testShouldNotAllowMulOnUntypedVariable() {
   54         shouldFailWithMessages '''
   55             def foo(Closure cls) {}
   56             def bar() { foo { it * 2 } }
   57         ''', 'Cannot find matching method java.lang.Object#multiply(int)'
   58     }
   59     void testShouldNotAllowMulBynUntypedVariable() {
   60         shouldFailWithMessages '''
   61             def foo(Closure cls) {}
   62             def bar() { foo { 2 * it } }
   63         ''', 'Cannot find matching method int#multiply(java.lang.Object)'
   64     }
   65     void testShouldNotAllowPlusOnUntypedVariable() {
   66         shouldFailWithMessages '''
   67             def foo(Closure cls) {}
   68             def bar() { foo { it + 2 } }
   69         ''', 'Cannot find matching method java.lang.Object#plus(int)'
   70     }
   71     void testShouldNotAllowPlusWithUntypedVariable() {
   72         shouldFailWithMessages '''
   73             def foo(Closure cls) {}
   74             def bar() { foo { 2 + it } }
   75         ''', 'Cannot find matching method int#plus(java.lang.Object)'
   76     }
   77     void testShouldNotAllowMinusOnUntypedVariable() {
   78         shouldFailWithMessages '''
   79             def foo(Closure cls) {}
   80             def bar() { foo { it - 2 } }
   81         ''', 'Cannot find matching method java.lang.Object#minus(int)'
   82     }
   83     void testShouldNotAllowMinusByUntypedVariable() {
   84         shouldFailWithMessages '''
   85             def foo(Closure cls) {}
   86             def bar() { foo { 2 - it } }
   87         ''', 'Cannot find matching method int#minus(java.lang.Object)'
   88     }
   89 
   90     // GROOVY-7929
   91     void testShouldDetectInvalidMethodUseWithinTraitWithCompileStaticAndSelfType() {
   92         shouldFailWithMessages '''
   93             class C {
   94                 def m() { }
   95             }
   96             @groovy.transform.CompileStatic
   97             @groovy.transform.SelfType(C)
   98             trait T {
   99                 void test() {
  100                     x()
  101                 }
  102             }
  103         ''', 'Cannot find matching method <UnionType:C+T>#x'
  104     }
  105 
  106     // GROOVY-10102
  107     void testShouldDetectValidMethodUseWithinTraitWithCompileStaticAndSelfType() {
  108         assertScript '''
  109             import groovy.transform.*
  110 
  111             trait A {
  112                 String foo = 'foo'
  113                 String m(String s, Closure x) {
  114                     s + x()
  115                 }
  116             }
  117             @SelfType(A)
  118             trait B {
  119             }
  120             @SelfType(B)
  121             trait C {
  122             }
  123             @CompileStatic
  124             @SelfType(C)
  125             trait D {
  126                 def test() {
  127                     String s = foo
  128                     m(s) {
  129                         s.toUpperCase()
  130                     }
  131                 }
  132             }
  133 
  134             class E implements A, B, C, D { }
  135             assert new E().test() == 'fooFOO'
  136         '''
  137     }
  138 
  139     // GROOVY-10106
  140     void testCallStaticOrPrivateMethodInTraitFieldInitializer() {
  141         ['private', 'static', 'private static'].each { mods ->
  142             assertScript """
  143                 class C {
  144                     String s
  145                 }
  146                 trait T {
  147                     final C c = new C().tap {
  148                         config(it)
  149                     }
  150                     $mods void config(C c) {
  151                         c.s = 'x'
  152                     }
  153                 }
  154                 class U implements T {
  155                 }
  156                 def c = new U().c
  157                 assert c.s == 'x'
  158             """
  159         }
  160 
  161         shouldFailWithMessages '''
  162             trait T {
  163                 def obj = new Object().tap {
  164                     config(it)
  165                 }
  166                 static void config(String s) {
  167                 }
  168             }
  169         ''',
  170         'Cannot find matching method T$Trait$Helper#config(java.lang.Class, java.lang.Object)'
  171     }
  172 
  173     void testGroovy5444() {
  174         assertScript '''
  175             def millis = { System.currentTimeMillis() }
  176 
  177             5.times {
  178                 @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  179                     assert node.getNodeMetaData(INFERRED_TYPE) == Long_TYPE
  180                 })
  181                 def t0 = millis()
  182                 1000.times {
  183                     "echo"
  184                 }
  185                 def elapsed = millis() - t0
  186             }
  187         '''
  188     }
  189 
  190     void testGroovy5487ReturnNull() {
  191         assertScript '''
  192         @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  193             assert node.getNodeMetaData(INFERRED_RETURN_TYPE) == null // null since 2.1.9
  194         })
  195         List getList() {
  196             null
  197         }
  198         '''
  199     }
  200 
  201     void testGroovy5487ReturnNullWithExplicitReturn() {
  202         assertScript '''
  203         @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  204             assert node.getNodeMetaData(INFERRED_RETURN_TYPE) == null // null since 2.1.9
  205         })
  206         List getList() {
  207             return null
  208         }
  209         '''
  210     }
  211 
  212     void testGroovy5487ReturnNullWithEmptyBody() {
  213         assertScript '''
  214         @ASTTest(phase=INSTRUCTION_SELECTION, value= {
  215             assert node.getNodeMetaData(INFERRED_RETURN_TYPE) == null // null since 2.1.9
  216         })
  217         List getList() {
  218         }
  219         '''
  220     }
  221 
  222     void testGroovy7477NullGenericsType() {
  223         assertScript '''
  224             class L<E> extends ArrayList<E> {
  225                 boolean removeIf(Comparator<? super E> filter) {
  226                 }
  227             }
  228             def items = ['foo', 'bar'] as L<String>
  229             items.removeIf({a, b -> 1} as Comparator<String>)
  230             assert items
  231         '''
  232 
  233         shouldFailWithMessages '''
  234             class L<E> extends ArrayList<E> {
  235                 boolean removeIf(Comparator<? super E> filter) {
  236                 }
  237             }
  238             L<String> items = ['foo', 'bar'] as L<String>
  239             items.removeIf({a, b -> 1} as Comparator<?>)
  240             assert items
  241         ''', 'Cannot call L <String>#removeIf(java.util.Comparator <? super java.lang.String>) with arguments [java.util.Comparator <?>]'
  242     }
  243 
  244     void testGroovy5482ListsAndFlowTyping() {
  245         assertScript '''
  246         class StaticGroovy2 {
  247             def bar() {
  248 
  249                 def foo = [new Date(), 1, new C()]
  250                 foo.add( 2 ) // Compiles
  251                 foo.add( new Date() )
  252                 foo.add( new C() )
  253 
  254                 foo = [new Date(), 1]
  255                 foo.add( 2 ) // Does not compile
  256             }
  257         }
  258         class C{
  259         }
  260         new StaticGroovy2()'''
  261     }
  262 
  263     void testClosureThisObjectDelegateOwnerProperty() {
  264         assertScript '''
  265             class C {
  266                 void m() {
  267                     C that = this;
  268 
  269                     { ->
  270                         @ASTTest(phase=INSTRUCTION_SELECTION, value={
  271                             assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'C'
  272                         })
  273                         def ref = thisObject
  274                         assert ref == that
  275                     }();
  276 
  277                     { ->
  278                         @ASTTest(phase=INSTRUCTION_SELECTION, value={
  279                             assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'C'
  280                         })
  281                         def ref = delegate
  282                         assert ref == that
  283                     }();
  284 
  285                     { ->
  286                         @ASTTest(phase=INSTRUCTION_SELECTION, value={
  287                             assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'C'
  288                         })
  289                         def ref = owner
  290                         assert ref == that
  291                     }();
  292                 }
  293             }
  294             new C().m()
  295         '''
  296     }
  297 
  298     void testClosureThisObjectDelegateOwnerAccessor() {
  299         assertScript '''
  300             class C {
  301                 void m() {
  302                     C that = this;
  303 
  304                     { ->
  305                         @ASTTest(phase=INSTRUCTION_SELECTION, value={
  306                             assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'C'
  307                         })
  308                         def ref = getThisObject()
  309                         assert ref == that
  310                     }();
  311 
  312                     { ->
  313                         @ASTTest(phase=INSTRUCTION_SELECTION, value={
  314                             assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'C'
  315                         })
  316                         def ref = getDelegate()
  317                         assert ref == that
  318                     }();
  319 
  320                     { ->
  321                         @ASTTest(phase=INSTRUCTION_SELECTION, value={
  322                             assert node.getNodeMetaData(INFERRED_TYPE)?.name == 'C'
  323                         })
  324                         def ref = getOwner()
  325                         assert ref == that
  326                     }();
  327                 }
  328             }
  329             new C().m()
  330         '''
  331     }
  332 
  333     // GROOVY-9604
  334     void testClosureResolveStrategy() {
  335         assertScript '''
  336             class C {
  337                 def m() {
  338                     return { ->
  339                         resolveStrategy + getResolveStrategy()
  340                     }();
  341                 }
  342             }
  343             assert new C().m() == 0
  344         '''
  345     }
  346 
  347     // GROOVY-5616
  348     void testAssignToGroovyObject() {
  349         assertScript '''
  350         class A {}
  351         GroovyObject obj = new A()
  352         '''
  353     }
  354 
  355     void testAssignJavaClassToGroovyObject() {
  356         shouldFailWithMessages '''
  357         GroovyObject obj = 'foo'
  358         ''', 'Cannot assign value of type java.lang.String to variable of type groovy.lang.GroovyObject'
  359     }
  360 
  361     void testCastToGroovyObject() {
  362         assertScript '''
  363         class A {}
  364         GroovyObject obj = new A()
  365         '''
  366     }
  367 
  368     void testAssignInnerClassToGroovyObject() {
  369         assertScript '''
  370         class A { static class B {} }
  371         GroovyObject obj = new A.B()
  372         '''
  373     }
  374     void testCastInnerClassToGroovyObject() {
  375         assertScript '''
  376         class A { static class B {} }
  377         GroovyObject obj = (GroovyObject)new A.B()
  378         '''
  379     }
  380 
  381     void testGroovyObjectInGenerics() {
  382         assertScript '''
  383         class A {}
  384         List<? extends GroovyObject> list = new LinkedList<? extends GroovyObject>()
  385         list.add(new A())
  386         '''
  387     }
  388 
  389     // GROOVY-5656
  390     void testShouldNotThrowAmbiguousMethodError() {
  391         assertScript '''import groovy.transform.*
  392 
  393         class Expr {}
  394         class VarExpr extends Expr {}
  395 
  396         class ArgList {
  397             ArgList(Expr e1) {  }
  398             ArgList(Expr[] es) {  }
  399         }
  400 
  401         class Bug4 {
  402             void test() {
  403                 new ArgList(new VarExpr())
  404             }
  405         }
  406 
  407         new Bug4().test()
  408         '''
  409     }
  410 
  411     // GROOVY-5793
  412     void testByteAsParameter() {
  413         assertScript '''
  414         void testMethod(java.lang.Byte param){
  415             println(param)
  416         }
  417 
  418         void execute(){
  419             testMethod(java.lang.Byte.valueOf("123"))
  420         }
  421 
  422         execute()'''
  423     }
  424 
  425     // GROOVY-5874 (pt.1)
  426     void testClosureSharedVariableInBinExp() {
  427         shouldFailWithMessages '''
  428             def sum = 0
  429             def cl1 = { sum = sum + 1 }
  430             def cl2 = { sum = new Date() }
  431 
  432         ''', 'A closure shared variable [sum] has been assigned with various types'
  433     }
  434 
  435     // GROOVY-5870
  436     void testShouldNotThrowErrorIfTryingToCastToInterface() {
  437         assertScript '''
  438             Set tmp = null
  439             List other = (List) tmp // should not complain because source and target are interfaces
  440         '''
  441     }
  442 
  443     // GROOVY-5889
  444     void testShouldNotGoIntoInfiniteLoop() {
  445         assertScript '''
  446         class Enclosing {
  447             static class FMessage {
  448                 static enum LogLevel { finest, finer, fine, config, info, warning, severe }
  449                 LogLevel logLevel
  450             }
  451         }
  452         new Enclosing()
  453         '''
  454     }
  455 
  456     // GROOVY-5959
  457     void testSwitchCaseShouldNotRemoveBreakStatements() {
  458         assertScript '''
  459         int test(Map<String, String> token) {
  460           switch(token.type) {
  461             case 'case one':
  462               1
  463               break
  464             case 'case two':
  465               2
  466               break
  467             default:
  468               3
  469               break
  470           }
  471         }
  472         assert test([type:'case one']) == 1
  473         assert test([type:'case two']) == 2
  474         assert test([type:'default']) == 3
  475         '''
  476     }
  477 
  478     void testShouldChooseFindMethodFromList() {
  479         assertScript '''
  480         class Mylist implements List<Object> {
  481 
  482             int size() { }
  483             boolean isEmpty() {}
  484             boolean contains(final Object o) {}
  485             Iterator iterator() {[].iterator()}
  486             Object[] toArray() {}
  487             Object[] toArray(final Object[] a) {}
  488             boolean add(final Object e) {}
  489             boolean remove(final Object o) {}
  490             boolean containsAll(final Collection<?> c) {}
  491             boolean addAll(final Collection c) {}
  492             boolean addAll(final int index, final Collection c) {}
  493             boolean removeAll(final Collection<?> c) {}
  494             boolean retainAll(final Collection<?> c) {}
  495             void clear() {}
  496             Object get(final int index) {}
  497             Object set(final int index, final Object element) {}
  498             void add(final int index, final Object element) {}
  499             Object remove(final int index) {}
  500             int indexOf(final Object o) {}
  501             int lastIndexOf(final Object o) {}
  502             ListIterator listIterator() {}
  503             ListIterator listIterator(final int index) {}
  504             List subList(final int fromIndex, final int toIndex) {}
  505         }
  506 
  507            def whatthe(Mylist a) {
  508                a.find { true }
  509            }
  510         whatthe(new Mylist())
  511         '''
  512     }
  513 
  514     // GROOVY-6050
  515     void testShouldAllowTypeConversion() {
  516         assertScript '''
  517             interface SomeInterface { void sayHello() }
  518             void foo(Writer writer) {
  519                 if (writer instanceof SomeInterface) {
  520                     ((SomeInterface)writer).sayHello()
  521                 }
  522             }
  523             foo(null)
  524         '''
  525     }
  526 
  527     // GROOVY-6099
  528     void testFlowTypingErrorWithIfElse() {
  529         assertScript '''
  530             def o = new Object()
  531             boolean b = true
  532             if (b) {
  533                 o = 1
  534             } else {
  535                 @ASTTest(phase=INSTRUCTION_SELECTION, value={
  536                     assert node.getNodeMetaData(INFERRED_TYPE) == OBJECT_TYPE
  537                 })
  538                 def o2 = o
  539                 println (o2.toString())
  540             }
  541         '''
  542     }
  543 
  544     // GROOVY-6104
  545     void testShouldResolveConstantFromInterfaceImplementedInSuperClass() {
  546         assertScript '''
  547             interface Foo {
  548                 public static int MY_CONST = 85
  549             }
  550             class FooImpl implements Foo {}
  551             class Bar extends FooImpl {
  552                 void bar() {
  553                     assert MY_CONST == 85
  554                 }
  555             }
  556             new Bar().bar()
  557         '''
  558     }
  559 
  560     // GROOVY-6098
  561     void testUnresolvedPropertyReferencingIsBooleanMethod() {
  562         assertScript '''
  563             boolean isFoo() { true }
  564             assert foo
  565         '''
  566     }
  567 
  568     // GROOVY-6119
  569     void testShouldCallConstructorWithMap() {
  570         assertScript '''
  571             class Foo {
  572                 String message
  573                 Foo(Map map) {
  574                     message = map.msg
  575                 }
  576             }
  577             def foo = new Foo(msg: 'bar')
  578             assert foo.message == 'bar'
  579         '''
  580     }
  581 
  582     // GROOVY-6119
  583     void testShouldCallConstructorWithHashMap() {
  584         assertScript '''
  585             class Foo {
  586                 String message
  587                 Foo(HashMap map) {
  588                     message = map.msg
  589                 }
  590             }
  591             def foo = new Foo(msg: 'bar')
  592             assert foo.message == 'bar'
  593         '''
  594     }
  595 
  596     // GROOVY-6162
  597     void testShouldConsiderThisInStaticContext() {
  598         assertScript '''
  599             class Foo {
  600                 static def staticMethod() {
  601                     @ASTTest(phase=INSTRUCTION_SELECTION,value={
  602                         def ift = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
  603                         assert ift == CLASS_Type
  604                         assert ift.isUsingGenerics()
  605                         assert ift.genericsTypes[0].type.name == 'Foo'
  606                     })
  607                     def foo = this
  608 
  609                     this.classLoader
  610                 }
  611             }
  612             assert Foo.staticMethod() instanceof ClassLoader
  613         '''
  614     }
  615 
  616     void testListToSet() {
  617         assertScript '''
  618             Set foo(List<Map.Entry> set) {
  619                 set.collect { Map.Entry entry -> entry.key }.toSet()
  620             }
  621         '''
  622     }
  623 
  624     void testConstructorNewInstance() {
  625         assertScript '''import java.lang.reflect.Constructor
  626 
  627 class Person {
  628     String name
  629     Person(String name) { this.name = name }
  630 }
  631 
  632 Constructor<Person> ctor = Person.getConstructor(String)
  633 def p = ctor.newInstance('Bob')
  634 assert p.name == 'Bob'
  635 '''
  636     }
  637 
  638     void testOuterDotThisNotation() {
  639         assertScript '''
  640 class Outer {
  641     int x
  642     class Inner {
  643         int foo() { 2*Outer.this.x }
  644     }
  645     int bar() {
  646         new Inner().foo()
  647     }
  648 }
  649 def o = new Outer(x:123)
  650 assert o.bar() == 2*o.x
  651 '''
  652     }
  653 
  654     // GROOVY-6965
  655     void testShouldNotFailWithClassCastExceptionDuringCompilation() {
  656         assertScript '''
  657 interface Job {
  658   Runnable getRunnable()
  659 }
  660 
  661 
  662 class Printer implements Job{
  663 
  664   protected void execute() {
  665     println "Printing"
  666   }
  667 
  668   public void acceptsRunnable(Runnable r){
  669     r.run()
  670   }
  671 
  672   public Runnable getRunnable(){
  673      acceptsRunnable(this.&execute) // OK
  674      return this.&execute           // compile error
  675   }
  676 }
  677 
  678 Printer
  679 '''
  680     }
  681 
  682     // GROOVY-6970
  683     void testShouldBeAbleToChooseBetweenTwoEquivalentInterfaceMethods1() {
  684         assertScript '''
  685             interface A { void m() }
  686             interface B { void m() }
  687             interface C extends A, B {}
  688 
  689             class D {
  690              D(C c) {
  691                c.m()
  692              }
  693             }
  694             class CImpl implements C {
  695                 void m() { }
  696             }
  697 
  698             new D(new CImpl())
  699         '''
  700     }
  701 
  702     void testShouldBeAbleToChooseBetweenTwoEquivalentInterfaceMethods2() {
  703         assertScript '''
  704             interface A { void m() }
  705             interface B { void m() }
  706             class C implements A,B {
  707                 void m() {}
  708             }
  709             class D {
  710              D(C c) {
  711                c.m()
  712              }
  713             }
  714 
  715             new D(new C())
  716         '''
  717     }
  718 
  719     void testShouldBeAbleToChooseBetweenTwoEquivalentInterfaceMethods3() {
  720         assertScript '''
  721             interface A { void m() }
  722             interface B { void m() }
  723             interface C extends A,B {}
  724             class CImpl implements C, A,B {
  725                 void m() {}
  726             }
  727             class D {
  728              D(C c) {
  729                c.m()
  730              }
  731             }
  732 
  733             new D(new CImpl())
  734         '''
  735     }
  736 
  737     // GROOVY-6849
  738     void testAmbiguousMethodResolution() {
  739         assertScript '''
  740             interface ObservableList<E> extends List<E> {
  741                 public boolean addAll(E... elements)
  742             }
  743             public <E> ObservableList<E> wrap(List<E> list) { list as ObservableList }
  744             ObservableList<String> tags = wrap(['groovy','programming'])
  745             tags.addAll('bug')
  746         '''
  747     }
  748 
  749     // GROOVY-7160
  750     void testAmbiguousMethodResolutionObjectVsEnums() {
  751         // Currently preferring JDK9+ Set.of(E, E, E, E, E, E) ahead of EnumSet.of(E, E[])
  752         // TODO clarify behavior for this edge case
  753         if (!isAtLeastJdk('9.0')) {
  754             assertScript '''
  755             import static java.nio.file.AccessMode.*
  756             def test() {
  757                 // more than 5 to match of(E first, E[] rest) variant
  758                 EnumSet.of(READ, WRITE, EXECUTE, READ, WRITE, EXECUTE)
  759             }
  760             assert test() == [READ, WRITE, EXECUTE].toSet()
  761             '''
  762         }
  763     }
  764 
  765     // GROOVY-7710
  766     void testAmbiguousMethodResolutionNoArgsOverload() {
  767         shouldFailWithMessages '''
  768             Arrays.sort()
  769         ''', 'Reference to method is ambiguous. Cannot choose between '
  770     }
  771 
  772     // GROOVY-7711
  773     void testAmbiguousMethodResolutionNoArgsCovariantOverride() {
  774         assertScript '''
  775             class A {}
  776             class B {
  777                 Object m(Object[] args) {
  778                     new Object()
  779                 }
  780             }
  781             class C extends B {
  782                 A m(Object[] args) {
  783                     new A()
  784                 }
  785             }
  786             C c = new C()
  787             A a = c.m()
  788         '''
  789     }
  790 
  791     // GROOVY-6911
  792     void testShouldNotThrowArrayIndexOfOutBoundsException() {
  793         assertScript '''
  794             class MyMap<T> extends LinkedHashMap<String, Object> { }
  795 
  796             class C {
  797                 MyMap bar() { new MyMap() }
  798             }
  799 
  800             Map<String, Object> m = new C().bar()
  801             List tmp = (List) m.get("some_key_here")
  802         '''
  803     }
  804 
  805     // GROOVY-7416
  806     void testMethodsFromInterfacesOfSuperClassesShouldBeVisible() {
  807         assertScript '''
  808             interface SomeInterface {
  809                 void someInterfaceMethod()
  810             }
  811 
  812             abstract class AbstractSuperClass implements SomeInterface {}
  813 
  814             abstract class AbstractSubClass extends AbstractSuperClass {
  815                 void someMethod() {
  816                     someInterfaceMethod()
  817                 }
  818             }
  819 
  820             assert AbstractSubClass.name == 'AbstractSubClass'
  821         '''
  822         assertScript '''
  823             interface SomeInterface { void foo() }
  824             interface SomeOtherInterface { void bar() }
  825             interface AnotherInterface extends SomeInterface, SomeOtherInterface {}
  826 
  827             abstract class Parent implements AnotherInterface {}
  828 
  829             abstract class Child extends Parent {
  830                 void baz() { foo(); bar() }
  831             }
  832 
  833             assert Child.name == 'Child'
  834         '''
  835     }
  836 
  837     // GROOVY-7315
  838     void testNamedArgConstructorSupportWithInnerClassesAndCS() {
  839         assertScript '''
  840             import groovy.transform.*
  841             @ToString
  842             class X {
  843                 int a
  844                 static X makeX() { new X(a:1) }
  845                 Y makeY() {
  846                     new Y(b:2)
  847                 }
  848                 @ToString
  849                 private class Y {
  850                     int b
  851                     @ToString
  852                     private class Z {
  853                         int c
  854                     }
  855                     Z makeZ() {
  856                         new Z(c:3)
  857                     }
  858                 }
  859             }
  860             assert X.makeX().toString() == 'X(1)'
  861             assert X.makeX().makeY().toString() == 'X$Y(2)'
  862             assert X.makeX().makeY().makeZ().toString() == 'X$Y$Z(3)'
  863         '''
  864     }
  865 
  866     // GROOVY-8255, GROOVY-8382
  867     void testTargetTypingEmptyCollectionLiterals() {
  868         assertScript '''
  869             class Foo {
  870                 List<List<String>> items = [['x']]
  871                 def bar() {
  872                     List<String> result = []
  873                     List<String> selections = items.size() ? (items.get(0) ?: []) : items.size() > 1 ? items.get(1) : []
  874                     for (String selection: selections) {
  875                         result << selection
  876                     }
  877                     result
  878                 }
  879             }
  880             assert new Foo().bar() == ['x']
  881         '''
  882         assertScript '''
  883             class Foo {
  884                 def bar() {
  885                     def items = [x:1]
  886                     Map<String, Integer> empty = [:]
  887                     Map<String, Integer> first = items ?: [:]
  888                     Map<String, Integer> second = first.isEmpty() ? [:] : [y:2]
  889                     [first, second]
  890                 }
  891             }
  892             assert new Foo().bar() == [[x:1], [y:2]]
  893         '''
  894         assertScript '''
  895             import groovy.transform.*
  896             @ToString(includeFields=true)
  897             class Foo {
  898                 List<String> propWithGen = ['propWithGen'] ?: []
  899                 List propNoGen = ['propNoGen'] ?: []
  900                 private Map<String, Integer> fieldGen = [fieldGen:42] ?: [:]
  901                 def bar() {
  902                     this.propNoGen = ['notDecl'] ?: [] // not applicable here
  903                     List<String> localVar = ['localVar'] ?: []
  904                     localVar
  905                 }
  906             }
  907             def foo = new Foo()
  908             assert foo.bar() == ['localVar']
  909             assert foo.toString() == 'Foo([propWithGen], [notDecl], [fieldGen:42])'
  910         '''
  911     }
  912 
  913     // GROOVY-8590
  914     void testNestedMethodCallInferredTypeInReturnStmt() {
  915         assertScript '''
  916             class Source {
  917                 Object getValue() { '32' }
  918             }
  919             int m(Source src) {
  920                 return Integer.parseInt((String) src.getValue())
  921             }
  922             assert m(new Source()) == 32
  923         '''
  924     }
  925 
  926     // GROOVY-9463
  927     void testMethodPointerUnknownReference() {
  928         shouldFailWithMessages '''
  929             def ptr = String.&toLowerCaseX
  930         ''', 'Cannot find matching method java.lang.String#toLowerCaseX.'
  931     }
  932 
  933     // GROOVY-9938
  934     void testInnerClassImplementsInterfaceMethod() {
  935         assertScript '''
  936             class Main {
  937                 interface I {
  938                     def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c)
  939                 }
  940                 static class C implements I {
  941                     def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c) {
  942                         new D().with(c)
  943                     }
  944                 }
  945                 static class D {
  946                     def f() {
  947                         return 'retval'
  948                     }
  949                 }
  950                 static main(args) {
  951                     def result = new C().m { f() }
  952                     assert result == 'retval'
  953                 }
  954             }
  955         '''
  956     }
  957     void testInnerClassImplementsInterfaceMethodWithTrait() {
  958         assertScript '''
  959             class Main {
  960                 interface I {
  961                     def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c)
  962                 }
  963                 trait T {
  964                     def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c) {
  965                         new D().with(c)
  966                     }
  967                 }
  968                 static class C implements T { // generates m(Closure) that delegates to T#m(Closure)
  969                 }
  970                 static class D {
  971                     def f() {
  972                         return 'retval'
  973                     }
  974                 }
  975                 static main(args) {
  976                     def result = new C().m { f() }
  977                     assert result == 'retval'
  978                 }
  979             }
  980         '''
  981     }
  982     void testInnerClassImplementsInterfaceMethodWithDelegate() {
  983         assertScript '''
  984             class Main {
  985                 interface I {
  986                     def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c)
  987                 }
  988                 static class T implements I {
  989                     def m(@DelegatesTo(value=D, strategy=Closure.DELEGATE_FIRST) Closure c) {
  990                         new D().with(c)
  991                     }
  992                 }
  993                 static class C implements I {
  994                     @Delegate(parameterAnnotations=true) T t = new T() // generates m(Closure) that delegates to T#m(Closure)
  995                 }
  996                 static class D {
  997                     def f() {
  998                         return 'retval'
  999                     }
 1000                 }
 1001                 static main(args) {
 1002                     def result = new C().m { f() }
 1003                     assert result == 'retval'
 1004                 }
 1005             }
 1006         '''
 1007     }
 1008 
 1009     // GROOVY-9951
 1010     void testInnerImmutable() {
 1011         assertScript '''
 1012             class Outer {
 1013                 @groovy.transform.Immutable
 1014                 static class Inner {
 1015                     String proper
 1016                 }
 1017             }
 1018 
 1019             def obj = new Outer.Inner('value')
 1020             assert obj.proper == 'value'
 1021         '''
 1022     }
 1023 }