| /* |
| * 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 groovy.transform.stc |
| |
| /** |
| * Unit tests for static type checking : assignments. |
| */ |
| class STCAssignmentTest extends StaticTypeCheckingTestCase { |
| |
| void testAssignmentFailure() { |
| shouldFailWithMessages """ |
| int x = new Object() |
| """, "Cannot assign value of type java.lang.Object to variable of type int" |
| } |
| |
| void testAssignmentFailure2() { |
| shouldFailWithMessages """ |
| Set set = new Object() |
| """, "Cannot assign value of type java.lang.Object to variable of type java.util.Set" |
| } |
| |
| void testAssignmentFailure3() { |
| shouldFailWithMessages """ |
| Set set = new Integer(2) |
| """, "Cannot assign value of type java.lang.Integer to variable of type java.util.Set" |
| } |
| |
| void testIndirectAssignment() { |
| shouldFailWithMessages """ |
| def o = new Object() |
| int x = o |
| """, "Cannot assign value of type java.lang.Object to variable of type int" |
| } |
| |
| void testIndirectAssignment2() { |
| shouldFailWithMessages """ |
| def o = new Object() |
| Set set = o |
| """, "Cannot assign value of type java.lang.Object to variable of type java.util.Set" |
| } |
| |
| void testIndirectAssignment3() { |
| shouldFailWithMessages """ |
| int x = 2 |
| Set set = x |
| """, "Cannot assign value of type int to variable of type java.util.Set" |
| } |
| |
| void testAssignmentToEnum() { |
| assertScript """ |
| enum MyEnum { a, b, c } |
| MyEnum e = MyEnum.a |
| e = 'a' // string to enum is implicit |
| e = "${'a'}" // gstring to enum is implicit too |
| """ |
| } |
| |
| void testAssignmentToEnumFailure() { |
| shouldFailWithMessages """ |
| enum MyEnum { a, b, c } |
| MyEnum e = MyEnum.a |
| e = 1 |
| """, "Cannot assign value of type int to variable of type MyEnum" |
| } |
| |
| void testAssignmentToString() { |
| assertScript """ |
| String str = new Object() |
| """ |
| } |
| |
| void testAssignmentToBoolean() { |
| assertScript """ |
| boolean test = new Object() |
| """ |
| } |
| |
| void testAssignmentToBooleanClass() { |
| assertScript """ |
| Boolean test = new Object() |
| """ |
| } |
| |
| void testAssignmentToClass() { |
| assertScript """ |
| Class test = 'java.lang.String' |
| """ |
| } |
| |
| void testPlusEqualsOnInt() { |
| assertScript """ |
| int i = 0 |
| i += 1 |
| """ |
| } |
| |
| void testMinusEqualsOnInt() { |
| assertScript """ |
| int i = 0 |
| i -= 1 |
| """ |
| } |
| |
| void testIntPlusEqualsObject() { |
| shouldFailWithMessages """ |
| int i = 0 |
| i += new Object() |
| """, "Cannot find matching method int#plus(java.lang.Object)" |
| } |
| |
| void testIntMinusEqualsObject() { |
| shouldFailWithMessages """ |
| int i = 0 |
| i -= new Object() |
| """, "Cannot find matching method int#minus(java.lang.Object)" |
| } |
| |
| void testStringPlusEqualsString() { |
| assertScript """ |
| String str = 'test' |
| str+='test2' |
| """ |
| } |
| |
| void testPossibleLooseOfPrecision() { |
| shouldFailWithMessages ''' |
| long a = Long.MAX_VALUE |
| int b = a |
| ''', 'Possible loss of precision from long to int' |
| } |
| |
| void testPossibleLooseOfPrecision2() { |
| assertScript ''' |
| int b = 0L |
| ''' |
| } |
| |
| void testPossibleLooseOfPrecision3() { |
| assertScript ''' |
| byte b = 127 |
| ''' |
| } |
| |
| void testPossibleLooseOfPrecision4() { |
| shouldFailWithMessages ''' |
| byte b = 128 // will not fit in a byte |
| ''', 'Possible loss of precision from int to byte' |
| } |
| |
| void testPossibleLooseOfPrecision5() { |
| assertScript ''' |
| short b = 128 |
| ''' |
| } |
| |
| void testPossibleLooseOfPrecision6() { |
| shouldFailWithMessages ''' |
| short b = 32768 // will not fit in a short |
| ''', 'Possible loss of precision from int to short' |
| } |
| |
| void testPossibleLooseOfPrecision7() { |
| assertScript ''' |
| int b = 32768L // mark it as a long, but it fits into an int |
| ''' |
| } |
| |
| void testPossibleLooseOfPrecision8() { |
| assertScript ''' |
| int b = 32768.0f // mark it as a float, but it fits into an int |
| ''' |
| } |
| |
| void testPossibleLooseOfPrecision9() { |
| assertScript ''' |
| int b = 32768.0d // mark it as a double, but it fits into an int |
| ''' |
| } |
| |
| void testPossibleLooseOfPrecision10() { |
| shouldFailWithMessages ''' |
| int b = 32768.1d |
| ''', 'Possible loss of precision from double to int' |
| } |
| |
| void testCastIntToShort() { |
| assertScript ''' |
| short s = (short) 0 |
| ''' |
| } |
| |
| void testCastIntToFloat() { |
| assertScript ''' |
| float f = (float) 1 |
| ''' |
| } |
| |
| void testCompatibleTypeCast() { |
| assertScript ''' |
| String s = 'Hello' |
| ((CharSequence) s) |
| ''' |
| } |
| |
| void testIncompatibleTypeCast() { |
| shouldFailWithMessages ''' |
| String s = 'Hello' |
| ((Set) s) |
| ''', 'Inconvertible types: cannot cast java.lang.String to java.util.Set' |
| } |
| |
| void testIncompatibleTypeCastWithAsType() { |
| // If the user uses explicit type coercion, there's nothing we can do |
| assertScript ''' |
| String s = 'Hello' |
| s as Set |
| ''' |
| } |
| |
| void testIncompatibleTypeCastWithTypeInference() { |
| shouldFailWithMessages ''' |
| def s = 'Hello' |
| s = 1 |
| ((Set) s) |
| ''', 'Inconvertible types: cannot cast int to java.util.Set' |
| } |
| |
| void testArrayLength() { |
| assertScript ''' |
| String[] arr = [1,2,3] |
| int len = arr.length |
| ''' |
| } |
| |
| void testMultipleAssignment1() { |
| assertScript ''' |
| def (x,y) = [1,2] |
| assert x == 1 |
| assert y == 2 |
| ''' |
| } |
| |
| void testMultipleAssignmentWithExplicitTypes() { |
| assertScript ''' |
| int x |
| int y |
| (x,y) = [1,2] |
| assert x == 1 |
| assert y == 2 |
| ''' |
| } |
| |
| void testMultipleAssignmentWithIncompatibleTypes() { |
| shouldFailWithMessages ''' |
| List x |
| List y |
| (x,y) = [1,2] |
| ''', 'Cannot assign value of type int to variable of type java.util.List' |
| } |
| |
| void testMultipleAssignmentWithoutEnoughArgs() { |
| shouldFailWithMessages ''' |
| int x |
| int y |
| (x,y) = [1] |
| ''', 'Incorrect number of values. Expected:2 Was:1' |
| } |
| |
| void testMultipleAssignmentTooManyArgs() { |
| assertScript ''' |
| int x |
| int y |
| (x,y) = [1,2,3] |
| assert x == 1 |
| assert y == 2 |
| ''' |
| } |
| |
| void testMultipleAssignmentFromVariable() { |
| shouldFailWithMessages ''' |
| def list = [1,2,3] |
| def (x,y) = list |
| ''', 'Multiple assignments without list expressions on the right hand side are unsupported in static type checking mode' |
| } |
| |
| void testAssignmentToInterface() { |
| assertScript ''' |
| Serializable ser = 'Hello' |
| ''' |
| } |
| |
| void testAssignmentToIncompatibleInterface() { |
| shouldFailWithMessages ''' |
| Collection ser = 'Hello' |
| ''', 'Cannot assign value of type java.lang.String to variable of type java.util.Collection' |
| } |
| |
| void testTernaryOperatorAssignmentShouldFailBecauseOfIncompatibleGenericTypes() { |
| shouldFailWithMessages ''' |
| List<Integer> foo = true?new LinkedList<String>():new LinkedList<Integer>(); |
| ''', 'Incompatible generic argument types. Cannot assign java.util.LinkedList <? extends java.io.Serializable <? extends java.io.Serializable>> to: java.util.List <Integer>' |
| } |
| |
| void testCastStringToChar() { |
| assertScript ''' |
| char c = 'a' |
| ''' |
| } |
| |
| void testCastStringLongerThan1CharToChar() { |
| shouldFailWithMessages ''' |
| char c = 'aa' |
| ''','Cannot assign value of type java.lang.String to variable of type char' |
| } |
| |
| void testCastNullToChar() { |
| shouldFailWithMessages ''' |
| char c = null |
| ''', 'Cannot assign value of type java.lang.Object to variable of type char' |
| } |
| |
| void testCastNullToBoolean() { |
| // GROOVY-6577 |
| assertScript ''' |
| boolean c = null |
| assert c == false |
| ''' |
| } |
| |
| void testCastNullToBooleanWithExplicitCast() { |
| // GROOVY-6577 |
| assertScript ''' |
| boolean c = (boolean) null |
| assert c == false |
| ''' |
| } |
| |
| void testCastStringToCharacter() { |
| assertScript ''' |
| Character c = 'a' |
| ''' |
| } |
| |
| void testCastStringLongerThan1CharToCharacter() { |
| shouldFailWithMessages ''' |
| Character c = 'aa' |
| ''','Cannot assign value of type java.lang.String to variable of type java.lang.Character' |
| } |
| |
| void testAssignNullToCharacter() { |
| assertScript ''' |
| Character c = null |
| ''' |
| } |
| |
| void testCastStringToCharWithCast() { |
| assertScript ''' |
| def c = (char) 'a' |
| ''' |
| } |
| |
| void testCastCharToByte() { |
| assertScript ''' |
| void foo(char c) { |
| byte b = (byte) c |
| } |
| ''' |
| } |
| |
| void testCastCharToInt() { |
| assertScript ''' |
| void foo(char c) { |
| int b = (int) c |
| } |
| ''' |
| } |
| |
| void testCastStringLongerThan1ToCharWithCast() { |
| shouldFailWithMessages ''' |
| def c = (char) 'aa' |
| ''', 'Inconvertible types: cannot cast java.lang.String to char' |
| } |
| |
| void testCastNullToCharWithCast() { |
| shouldFailWithMessages ''' |
| def c = (char) null |
| ''', 'Inconvertible types: cannot cast java.lang.Object to char' |
| } |
| |
| void testCastStringToCharacterWithCast() { |
| assertScript ''' |
| def c = (Character) 'a' |
| ''' |
| } |
| |
| void testCastStringLongerThan1ToCharacterWithCast() { |
| shouldFailWithMessages ''' |
| def c = (Character) 'aa' |
| ''', 'Inconvertible types: cannot cast java.lang.String to java.lang.Character' |
| } |
| |
| void testCastNullToCharacterWithCast() { |
| assertScript ''' |
| def c = (Character) null |
| ''' |
| } |
| |
| void testCastObjectToSubclass() { |
| assertScript ''' |
| Object o = null |
| try { |
| ((Integer)o).intValue() |
| } catch (NullPointerException e) { |
| } |
| ''' |
| } |
| |
| void testIfElseBranch() { |
| shouldFailWithMessages ''' |
| def x |
| def y = 'foo' |
| if (y) { |
| x = new HashSet() |
| } else { |
| x = '123' |
| } |
| x.toInteger() |
| ''', 'Cannot find matching method java.io.Serializable#toInteger()' |
| } |
| |
| void testIfElseBranchParameter() { |
| shouldFailWithMessages ''' |
| def foo(x) { |
| def y = 'foo' |
| if (y) { |
| x = new HashSet() |
| } else { |
| x = '123' |
| } |
| x.toInteger() |
| } |
| foo('bar') |
| ''', 'Cannot find matching method java.lang.Object#toInteger()' |
| } |
| |
| void testIfOnly() { |
| shouldFailWithMessages ''' |
| def x = '123' |
| def y = 'foo' |
| if (y) { |
| x = new HashSet() |
| } |
| x.toInteger() |
| ''', 'Cannot find matching method java.io.Serializable#toInteger()' |
| } |
| |
| void testIfOnlyParameter() { |
| shouldFailWithMessages ''' |
| def foo(x) { |
| def y = 'foo' |
| if (y) { |
| x = new HashSet() |
| assert x.isEmpty() |
| } |
| x.toInteger() |
| } |
| foo('123') |
| ''', 'Cannot find matching method java.lang.Object#toInteger()' |
| } |
| |
| void testIfWithCommonInterface() { |
| assertScript ''' |
| interface Foo { void foo() } |
| class A implements Foo { void foo() { println 'A' } } |
| class B implements Foo { void foo() { println 'B' } } |
| def x = new A() |
| def y = 'foo' |
| if (y) { |
| x = new B() |
| } |
| x.foo() |
| ''' |
| } |
| |
| void testForLoopWithNewAssignment() { |
| shouldFailWithMessages ''' |
| def x = '123' |
| for (int i=0; i<5;i++) { x = new HashSet() } |
| x.toInteger() |
| ''', 'Cannot find matching method java.io.Serializable#toInteger()' |
| } |
| |
| void testWhileLoopWithNewAssignment() { |
| shouldFailWithMessages ''' |
| def x = '123' |
| while (false) { x = new HashSet() } |
| x.toInteger() |
| ''', 'Cannot find matching method java.io.Serializable#toInteger()' |
| } |
| |
| void testTernaryWithNewAssignment() { |
| shouldFailWithMessages ''' |
| def x = '123' |
| def cond = false |
| cond?(x = new HashSet()):3 |
| x.toInteger() |
| ''', 'Cannot find matching method java.io.Serializable#toInteger()' |
| } |
| |
| void testFloatSub() { |
| assertScript ''' |
| float x = 1.0f |
| float y = 1.0f |
| float z = x-y |
| ''' |
| } |
| |
| void testDoubleMinusInt() { |
| assertScript ''' |
| double m() { |
| double a = 10d |
| int b = 1 |
| double c = a-b |
| } |
| assert m()==9d |
| ''' |
| } |
| |
| void testDoubleMinusFloat() { |
| assertScript ''' |
| double m() { |
| double a = 10d |
| float b = 1f |
| double c = a-b |
| } |
| assert m()==9d |
| ''' |
| } |
| |
| void testBigDecimalSub() { |
| assertScript ''' |
| BigDecimal m() { |
| BigDecimal a = 10 |
| BigDecimal b = 10 |
| BigDecimal c = a-b |
| } |
| assert m()==0 |
| assert m().getClass() == BigDecimal |
| ''' |
| } |
| |
| void testBigDecimalMinusDouble() { |
| assertScript ''' |
| BigDecimal m() { |
| BigDecimal a = 10 |
| double b = 10d |
| BigDecimal c = a-b |
| } |
| assert m()==0 |
| assert m().getClass() == BigDecimal |
| ''' |
| } |
| |
| void testFloatSum() { |
| assertScript ''' |
| float x = 1.0f |
| float y = 1.0f |
| float z = x+y |
| ''' |
| } |
| |
| void testDoublePlusInt() { |
| assertScript ''' |
| double m() { |
| double a = 10d |
| int b = 1 |
| double c = a+b |
| } |
| assert m()==11d |
| ''' |
| } |
| |
| void testDoublePlusFloat() { |
| assertScript ''' |
| double m() { |
| double a = 10d |
| float b = 1f |
| double c = a+b |
| } |
| assert m()==11d |
| ''' |
| } |
| |
| void testBigDecimalSum() { |
| assertScript ''' |
| BigDecimal m() { |
| BigDecimal a = 10 |
| BigDecimal b = 10 |
| BigDecimal c = a+b |
| } |
| assert m()==20 |
| assert m().getClass() == BigDecimal |
| ''' |
| } |
| |
| void testBigDecimalPlusDouble() { |
| assertScript ''' |
| BigDecimal m() { |
| BigDecimal a = 10 |
| double b = 10d |
| BigDecimal c = a+b |
| } |
| assert m()==20 |
| assert m().getClass() == BigDecimal |
| ''' |
| } |
| |
| void testBigIntegerAssignment() { |
| assertScript ''' |
| BigInteger bigInt = 6666666666666666666666666666666666666 |
| assert bigInt.toString()=='6666666666666666666666666666666666666' |
| assert bigInt.class == BigInteger |
| ''' |
| } |
| |
| void testBigIntegerSum() { |
| assertScript ''' |
| BigInteger a = 6666666666666666666666666666666666666 |
| BigInteger b = 6666666666666666666666666666666666666 |
| BigInteger c = a + b |
| assert c.toString()=='13333333333333333333333333333333333332' |
| assert c.class == BigInteger |
| ''' |
| } |
| |
| void testBigIntegerSub() { |
| assertScript ''' |
| BigInteger a = 6666666666666666666666666666666666666 |
| BigInteger b = 6666666666666666666666666666666666666 |
| BigInteger c = a - b |
| assert c.toString()=='0' |
| assert c.class == BigInteger |
| ''' |
| } |
| |
| void testBigIntegerMult() { |
| assertScript ''' |
| BigInteger a = 6666666666666666666666666666666666666 |
| BigInteger b = 2 |
| BigInteger c = a * b |
| assert c.toString()=='13333333333333333333333333333333333332' |
| assert c.class == BigInteger |
| ''' |
| } |
| |
| void testBigIntegerMultDouble() { |
| assertScript ''' |
| BigInteger a = 333 |
| double b = 2d |
| BigDecimal c = a * b |
| assert c == 666 |
| assert c.getClass() == BigDecimal |
| ''' |
| |
| shouldFailWithMessages ''' |
| BigInteger a = 333 |
| double b = 2d |
| BigInteger c = a * b |
| ''', 'Cannot assign value of type java.math.BigDecimal to variable of type java.math.BigInteger' |
| } |
| |
| void testBigIntegerMultInteger() { |
| assertScript ''' |
| BigInteger a = 333 |
| int b = 2 |
| BigDecimal c = a * b |
| assert c == 666 |
| assert c.getClass() == BigDecimal |
| ''' |
| } |
| |
| //GROOVY-6435 |
| void testBigDecAndBigIntSubclass() { |
| assertScript ''' |
| class MyDecimal extends BigDecimal { |
| public MyDecimal(String s) {super(s)} |
| } |
| class MyInteger extends BigInteger { |
| public MyInteger(String s) {super(s)} |
| } |
| |
| BigDecimal d = new MyDecimal("3.0") |
| BigInteger i = new MyInteger("3") |
| ''' |
| } |
| |
| void testPostfixOnInt() { |
| assertScript ''' |
| int i = 0 |
| i++ |
| ''' |
| assertScript ''' |
| int i = 0 |
| i-- |
| ''' |
| } |
| |
| void testPostfixOnDate() { |
| assertScript ''' |
| Date d = new Date() |
| d++ |
| ''' |
| assertScript ''' |
| Date d = new Date() |
| d-- |
| ''' |
| } |
| |
| void testPostfixOnObject() { |
| shouldFailWithMessages ''' |
| Object o = new Object() |
| o++ |
| ''', 'Cannot find matching method java.lang.Object#next()' |
| shouldFailWithMessages ''' |
| Object o = new Object() |
| o-- |
| ''', 'Cannot find matching method java.lang.Object#previous()' |
| } |
| |
| void testPrefixOnInt() { |
| assertScript ''' |
| int i = 0 |
| ++i |
| ''' |
| assertScript ''' |
| int i = 0 |
| --i |
| ''' |
| } |
| |
| void testPrefixOnDate() { |
| assertScript ''' |
| Date d = new Date() |
| ++d |
| ''' |
| assertScript ''' |
| Date d = new Date() |
| --d |
| ''' |
| } |
| |
| void testPrefixOnObject() { |
| shouldFailWithMessages ''' |
| Object o = new Object() |
| ++o |
| ''', 'Cannot find matching method java.lang.Object#next()' |
| shouldFailWithMessages ''' |
| Object o = new Object() |
| --o |
| ''', 'Cannot find matching method java.lang.Object#previous()' |
| } |
| |
| void testAssignArray() { |
| assertScript ''' |
| String[] src = ['a','b','c'] |
| Object[] arr = src |
| ''' |
| } |
| |
| void testCastArray() { |
| assertScript ''' |
| List<String> src = ['a','b','c'] |
| (String[]) src.toArray(src as String[]) |
| ''' |
| } |
| |
| void testIncompatibleCastArray() { |
| shouldFailWithMessages ''' |
| String[] src = ['a','b','c'] |
| (Set[]) src |
| ''', 'Inconvertible types: cannot cast java.lang.String[] to java.util.Set[]' |
| } |
| |
| void testIncompatibleToArray() { |
| shouldFailWithMessages ''' |
| (Set[]) ['a','b','c'].toArray(new String[3]) |
| ''', 'Inconvertible types: cannot cast java.lang.String[] to java.util.Set[]' |
| } |
| |
| // GROOVY-5535 |
| void testAssignToNullInsideIf() { |
| assertScript ''' |
| Date foo() { |
| Date result = new Date() |
| if (true) { |
| result = null |
| } |
| return result |
| } |
| assert foo() == null |
| ''' |
| } |
| |
| // GROOVY-5798 |
| void testShouldNotThrowConversionError() { |
| assertScript ''' |
| char m( int v ) { |
| char c = (char)v |
| c |
| } |
| |
| println m( 65 ) |
| ''' |
| } |
| |
| // GROOVY-6575 |
| void testAssignmentOfObjectToArrayShouldFail() { |
| shouldFailWithMessages ''' |
| Object o |
| int[] array = o |
| ''', 'Cannot assign value of type java.lang.Object to variable of type int[]' |
| } |
| |
| // GROOVY-7015 |
| void testAssingmentToSuperclassFieldWithDifferingGenerics() { |
| assertScript ''' |
| class Base {} |
| class Derived extends Base { |
| public String sayHello() { "hello"} |
| } |
| |
| class GBase<T extends Base> { |
| T myVar; |
| } |
| class GDerived extends GBase<Derived> { |
| GDerived() { myVar = new Derived(); } |
| public String method() {myVar.sayHello()} |
| } |
| |
| GDerived d = new GDerived(); |
| assert d.method() == "hello" |
| ''' |
| } |
| |
| //GROOVY-8157 |
| void testFlowTypingAfterParameterAssignment() { |
| assertScript ''' |
| class A {} |
| class B extends A { def bbb() { 42 } } |
| |
| def fooParameterAssignment(A a) { |
| a = new B() |
| a.bbb() |
| } |
| assert fooParameterAssignment(null) == 42 |
| ''' |
| } |
| |
| void testIntegerArraySmartType() { |
| assertScript ''' |
| def m() { |
| def a = 1 |
| Integer[] b = [a] |
| } |
| ''' |
| } |
| |
| void testIntegerSecondDimArraySmartType() { |
| assertScript ''' |
| def m() { |
| def a = new int[5] |
| int[][] b = [a] |
| } |
| ''' |
| } |
| |
| void testMultiAssign() { |
| assertScript ''' |
| def m() { |
| def row = ["", "", ""] |
| def (left, right) = [row[0], row[1]] |
| left.toUpperCase() |
| } |
| ''' |
| } |
| |
| // GROOVY-8220 |
| void testFlowTypingParameterTempTypeAssignmentTracking() { |
| assertScript ''' |
| class Foo { |
| CharSequence makeEnv( env, StringBuilder result = new StringBuilder() ) { |
| if (env instanceof File) { |
| env = env.toPath() |
| } |
| if (env instanceof String && env.contains('=')) { |
| result << 'export ' << env << ';' |
| } |
| return result.toString() |
| } |
| } |
| assert new Foo().makeEnv('X=1') == 'export X=1;' |
| ''' |
| // GROOVY-8237 |
| assertScript ''' |
| class Foo { |
| String parse(Reader reader) { |
| if (reader == null) |
| reader = new BufferedReader(reader) |
| int i = reader.read() |
| return (i != -1) ? 'bar' : 'baz' |
| } |
| } |
| assert new Foo().parse(new StringReader('foo')) == 'bar' |
| ''' |
| } |
| |
| void testFlowTypingParameterTempTypeAssignmentTrackingWithGenerics() { |
| assertScript ''' |
| class M { |
| Map<String, List<Object>> mvm = new HashMap<String, List<Object>>() |
| void setProperty(String name, value) { |
| if (value instanceof File) { |
| value = new File(value, 'bar.txt') |
| } |
| else if (value instanceof URL) { |
| value = value.toURI() |
| } |
| else if (value instanceof InputStream) { |
| value = new BufferedInputStream(value) |
| } |
| else if (value instanceof GString) { |
| value = value.toString() |
| } |
| if (mvm[name]) { |
| mvm[name].add value |
| } else { |
| mvm.put(name, [value]) |
| } |
| } |
| } |
| new M().setProperty('foo', 'bar') |
| ''' |
| } |
| |
| void testNarrowingConversion() { |
| assertScript ''' |
| interface A1{} |
| interface A2 extends A1{} |
| |
| class C1 implements A1{} |
| |
| def m(A2 a2) { |
| C1 c1 = (C1) a2 |
| } |
| ''' |
| } |
| |
| void testFinalNarrowingConversion() { |
| shouldFailWithMessages ''' |
| interface A1{} |
| interface A2 extends A1{} |
| |
| final class C1 implements A1{} |
| |
| def m(A2 a2) { |
| C1 c1 = (C1) a2 |
| } |
| ''', "Inconvertible types: cannot cast A2 to C1" |
| } |
| } |
| |