Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analyzer.test.src.task.strong.checker_test; | 5 library analyzer.test.src.task.strong.checker_test; |
| 6 | 6 |
| 7 import '../../../reflective_tests.dart'; | 7 import '../../../reflective_tests.dart'; |
| 8 import 'strong_test_helper.dart'; | 8 import 'strong_test_helper.dart'; |
| 9 | 9 |
| 10 void main() { | 10 void main() { |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 308 a[b] += d; | 308 a[b] += d; |
| 309 a[/*info:DYNAMIC_CAST*/c] += d; | 309 a[/*info:DYNAMIC_CAST*/c] += d; |
| 310 a[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/z] += d; | 310 a[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/z] += d; |
| 311 a[b] += /*info:DYNAMIC_CAST*/c; | 311 a[b] += /*info:DYNAMIC_CAST*/c; |
| 312 a[b] += /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/z; | 312 a[b] += /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/z; |
| 313 /*info:DYNAMIC_INVOKE,info:DYNAMIC_INVOKE*/c[b] += d; | 313 /*info:DYNAMIC_INVOKE,info:DYNAMIC_INVOKE*/c[b] += d; |
| 314 } | 314 } |
| 315 '''); | 315 '''); |
| 316 } | 316 } |
| 317 | 317 |
| 318 void test_constructorInvalid() { | |
| 319 // Regression test for https://github.com/dart-lang/sdk/issues/26695 | |
| 320 checkFile(''' | |
| 321 class A { | |
| 322 B({ /*error:FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR*/this.test: 1.0 }) {} | |
| 323 final double test = 0.0; | |
| 324 } | |
| 325 '''); | |
| 326 } | |
| 327 | |
| 318 void test_constructors() { | 328 void test_constructors() { |
| 319 checkFile(''' | 329 checkFile(''' |
| 320 const num z = 25; | 330 const num z = 25; |
| 321 Object obj = "world"; | 331 Object obj = "world"; |
| 322 | 332 |
| 323 class A { | 333 class A { |
| 324 int x; | 334 int x; |
| 325 String y; | 335 String y; |
| 326 | 336 |
| 327 A(this.x) : this.y = /*warning:FIELD_INITIALIZER_NOT_ASSIGNABLE*/42; | 337 A(this.x) : this.y = /*warning:FIELD_INITIALIZER_NOT_ASSIGNABLE*/42; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 342 B.c3(num x, Object y) : super.c3(x, /*info:DOWN_CAST_IMPLICIT*/y); | 352 B.c3(num x, Object y) : super.c3(x, /*info:DOWN_CAST_IMPLICIT*/y); |
| 343 } | 353 } |
| 344 | 354 |
| 345 void main() { | 355 void main() { |
| 346 A a = new A.c2(/*info:DOWN_CAST_IMPLICIT*/z, /*warning:ARGUMENT_TYPE_NOT_ASSI GNABLE*/z); | 356 A a = new A.c2(/*info:DOWN_CAST_IMPLICIT*/z, /*warning:ARGUMENT_TYPE_NOT_ASSI GNABLE*/z); |
| 347 var b = new B.c2(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/"hello", /*info:DOWN _CAST_IMPLICIT*/obj); | 357 var b = new B.c2(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/"hello", /*info:DOWN _CAST_IMPLICIT*/obj); |
| 348 } | 358 } |
| 349 '''); | 359 '''); |
| 350 } | 360 } |
| 351 | 361 |
| 352 void test_constructorInvalid() { | |
| 353 // Regression test for https://github.com/dart-lang/sdk/issues/26695 | |
| 354 checkFile(''' | |
| 355 class A { | |
| 356 B({ /*error:FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR*/this.test: 1.0 }) {} | |
| 357 final double test = 0.0; | |
| 358 } | |
| 359 '''); | |
| 360 } | |
| 361 | |
| 362 void test_conversionAndDynamicInvoke() { | 362 void test_conversionAndDynamicInvoke() { |
| 363 addFile( | 363 addFile( |
| 364 ''' | 364 ''' |
| 365 dynamic toString = (int x) => x + 42; | 365 dynamic toString = (int x) => x + 42; |
| 366 dynamic hashCode = "hello"; | 366 dynamic hashCode = "hello"; |
| 367 ''', | 367 ''', |
| 368 name: '/helper.dart'); | 368 name: '/helper.dart'); |
| 369 checkFile(''' | 369 checkFile(''' |
| 370 import 'helper.dart' as helper; | 370 import 'helper.dart' as helper; |
| 371 | 371 |
| (...skipping 1532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1904 for (;/*info:DOWN_CAST_IMPLICIT*/obj;) {} | 1904 for (;/*info:DOWN_CAST_IMPLICIT*/obj;) {} |
| 1905 for (;/*error:NON_BOOL_CONDITION*/i;) {} | 1905 for (;/*error:NON_BOOL_CONDITION*/i;) {} |
| 1906 } | 1906 } |
| 1907 '''); | 1907 '''); |
| 1908 } | 1908 } |
| 1909 | 1909 |
| 1910 void test_implicitCasts() { | 1910 void test_implicitCasts() { |
| 1911 addFile('num n; int i = /*info:ASSIGNMENT_CAST*/n;'); | 1911 addFile('num n; int i = /*info:ASSIGNMENT_CAST*/n;'); |
| 1912 check(); | 1912 check(); |
| 1913 // TODO(jmesserly): should not be emitting the hint as well as the error. | 1913 // TODO(jmesserly): should not be emitting the hint as well as the error. |
| 1914 // It is a "strong mode hint" however, so it will not be user visible. | |
| 1914 addFile( | 1915 addFile( |
| 1915 'num n; int i = /*info:ASSIGNMENT_CAST,error:INVALID_ASSIGNMENT*/n;'); | 1916 'num n; int i = /*info:ASSIGNMENT_CAST,error:INVALID_ASSIGNMENT*/n;'); |
| 1916 check(implicitCasts: false); | 1917 check(implicitCasts: false); |
| 1917 } | 1918 } |
| 1918 | 1919 |
| 1920 void test_implicitDynamic_field() { | |
| 1921 addFile(r''' | |
| 1922 class C { | |
| 1923 var /*error:IMPLICIT_DYNAMIC_FIELD*/x0; | |
| 1924 var /*error:IMPLICIT_DYNAMIC_FIELD*/x1 = (<dynamic>[])[0]; | |
|
Bob Nystrom
2016/06/23 23:25:52
This one is a little surprising to me. My intuitio
Jennifer Messerly
2016/06/24 01:15:56
Yeah, I added it for illustration. The current tec
| |
| 1925 var /*error:IMPLICIT_DYNAMIC_FIELD*/x2, | |
| 1926 x3 = 42, | |
| 1927 /*error:IMPLICIT_DYNAMIC_FIELD*/x4; | |
| 1928 dynamic y0; | |
| 1929 dynamic y1 = (<dynamic>[])[0]; | |
| 1930 } | |
| 1931 '''); | |
| 1932 check(implicitDynamic: false); | |
| 1933 } | |
| 1934 | |
| 1935 void test_implicitDynamic_function() { | |
| 1936 addFile(r''' | |
| 1937 /*=T*/ a/*<T>*/(/*=T*/ t) => t; | |
| 1938 /*=T*/ b/*<T>*/() => null; | |
| 1939 | |
| 1940 void main/*<S>*/() { | |
| 1941 dynamic d; | |
| 1942 int i; | |
| 1943 /*error:IMPLICIT_DYNAMIC_FUNCTION*/a(d); | |
| 1944 a(42); | |
| 1945 /*error:IMPLICIT_DYNAMIC_FUNCTION*/b(); | |
| 1946 d = /*error:IMPLICIT_DYNAMIC_FUNCTION*/b(); | |
| 1947 i = b(); | |
| 1948 | |
| 1949 void f/*<T>*/(/*=T*/ t) {}; | |
| 1950 /*=T*/ g/*<T>*/() => null; | |
| 1951 | |
| 1952 /*error:IMPLICIT_DYNAMIC_FUNCTION*/f(d); | |
| 1953 f(42); | |
| 1954 /*error:IMPLICIT_DYNAMIC_FUNCTION*/g(); | |
| 1955 d = /*error:IMPLICIT_DYNAMIC_FUNCTION*/g(); | |
| 1956 i = g(); | |
| 1957 | |
| 1958 /*error:IMPLICIT_DYNAMIC_INVOKE*/(/*<T>*/(/*=T*/ t) => t)(d); | |
| 1959 (/*<T>*/(/*=T*/ t) => t)(42); | |
| 1960 (/*<T>*/() => null as dynamic/*=T*/)/*<int>*/(); | |
| 1961 } | |
|
Bob Nystrom
2016/06/23 23:25:52
These test cases are fantastic. So thorough!
Jennifer Messerly
2016/06/24 01:15:56
Thanks. Wanted to illustrate what it does, especia
Leaf
2016/06/24 21:40:26
+1!
| |
| 1962 '''); | |
| 1963 check(implicitDynamic: false); | |
| 1964 } | |
| 1965 void test_implicitDynamic_listLiteral() { | |
| 1966 addFile(r''' | |
| 1967 | |
| 1968 var l0 = /*error:IMPLICIT_DYNAMIC_LIST_LITERAL*/[]; | |
| 1969 List l1 = /*error:IMPLICIT_DYNAMIC_LIST_LITERAL*/[]; | |
| 1970 List<dynamic> l2 = /*error:IMPLICIT_DYNAMIC_LIST_LITERAL*/[]; | |
|
Bob Nystrom
2016/06/23 23:25:52
This case is interesting too. This might be one to
Jennifer Messerly
2016/06/24 01:15:55
Yeah this dovetails into my other comment. We woul
| |
| 1971 dynamic d = 42; | |
| 1972 var l3 = /*error:IMPLICIT_DYNAMIC_LIST_LITERAL*/[d, d]; | |
|
Bob Nystrom
2016/06/23 23:25:52
I *think* I would consider this to be explicit. On
Jennifer Messerly
2016/06/24 01:15:55
That is an error in the current impl. makePair is
| |
| 1973 | |
| 1974 var l4 = <dynamic>[]; | |
| 1975 var l5 = <int>[]; | |
| 1976 List<int> l6 = /*info:INFERRED_TYPE_LITERAL*/[]; | |
| 1977 var l7 = /*info:INFERRED_TYPE_LITERAL*/[42]; | |
| 1978 '''); | |
| 1979 check(implicitDynamic: false); | |
| 1980 } | |
| 1981 | |
| 1982 void test_implicitDynamic_mapLiteral() { | |
| 1983 addFile(r''' | |
| 1984 var m0 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{}; | |
| 1985 Map m1 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{}; | |
| 1986 Map<dynamic, dynamic> m2 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{}; | |
| 1987 dynamic d = 42; | |
| 1988 var m3 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: d}; | |
| 1989 var m4 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{'x': d, 'y': d}; | |
| 1990 var m5 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: 'x '}; | |
| 1991 | |
| 1992 var m6 = <dynamic, dynamic>{}; | |
| 1993 var m7 = <String, String>{}; | |
| 1994 Map<String, String> m8 = /*info:INFERRED_TYPE_LITERAL*/{}; | |
| 1995 var m9 = /*info:INFERRED_TYPE_LITERAL*/{'hi': 'there'}; | |
| 1996 '''); | |
| 1997 check(implicitDynamic: false); | |
| 1998 } | |
| 1999 | |
| 2000 void test_implicitDynamic_method() { | |
| 2001 addFile(r''' | |
| 2002 class C { | |
| 2003 /*=T*/ m/*<T>*/(/*=T*/ s) => s; | |
| 2004 /*=T*/ n/*<T>*/() => null; | |
| 2005 } | |
| 2006 class D<E> { | |
| 2007 /*=T*/ m/*<T>*/(/*=T*/ s) => s; | |
| 2008 /*=T*/ n/*<T>*/() => null; | |
| 2009 } | |
| 2010 void f() { | |
| 2011 dynamic d; | |
| 2012 int i; | |
| 2013 new C()./*error:IMPLICIT_DYNAMIC_METHOD*/m(d); | |
| 2014 new C().m(42); | |
| 2015 new C()./*error:IMPLICIT_DYNAMIC_METHOD*/n(); | |
| 2016 d = new C()./*error:IMPLICIT_DYNAMIC_METHOD*/n(); | |
| 2017 i = new C().n(); | |
| 2018 | |
| 2019 new D<int>()./*error:IMPLICIT_DYNAMIC_METHOD*/m(d); | |
|
Bob Nystrom
2016/06/23 23:25:52
This feels like an explicit use of dynamic to me s
Jennifer Messerly
2016/06/24 01:15:56
yes, same as your other examples. They will either
| |
| 2020 new D<int>().m(42); | |
| 2021 new D<int>()./*error:IMPLICIT_DYNAMIC_METHOD*/n(); | |
| 2022 d = new D<int>()./*error:IMPLICIT_DYNAMIC_METHOD*/n(); | |
| 2023 i = new D<int>().n(); | |
| 2024 } | |
| 2025 '''); | |
| 2026 check(implicitDynamic: false); | |
| 2027 } | |
| 2028 | |
| 2029 void test_implicitDynamic_parameter() { | |
| 2030 addFile(r''' | |
| 2031 const dynamic DYNAMIC_VALUE = 42; | |
| 2032 | |
| 2033 // simple formal | |
| 2034 void f0(/*error:IMPLICIT_DYNAMIC_PARAMETER*/x) {} | |
| 2035 void f1(dynamic x) {} | |
| 2036 | |
| 2037 // default formal | |
| 2038 void df0([/*error:IMPLICIT_DYNAMIC_PARAMETER*/x = DYNAMIC_VALUE]) {} | |
| 2039 void df1([dynamic x = DYNAMIC_VALUE]) {} | |
| 2040 | |
| 2041 // BUG: this should work, see https://github.com/dart-lang/sdk/issues/25794 | |
| 2042 void df2([/*error:IMPLICIT_DYNAMIC_PARAMETER*/x = 42]) {} | |
| 2043 | |
| 2044 // default formal (named) | |
| 2045 void nf0({/*error:IMPLICIT_DYNAMIC_PARAMETER*/x: DYNAMIC_VALUE}) {} | |
| 2046 void nf1({dynamic x: DYNAMIC_VALUE}) {} | |
| 2047 | |
| 2048 // BUG: this should work, see https://github.com/dart-lang/sdk/issues/25794 | |
| 2049 void nf2({/*error:IMPLICIT_DYNAMIC_PARAMETER*/x: 42}) {} | |
| 2050 | |
| 2051 // field formal | |
| 2052 class C { | |
| 2053 var /*error:IMPLICIT_DYNAMIC_FIELD*/x; | |
| 2054 C(this.x); | |
| 2055 } | |
| 2056 | |
| 2057 // function typed formal | |
| 2058 void ftf0(void x(/*error:IMPLICIT_DYNAMIC_PARAMETER*/y)) {} | |
| 2059 void ftf1(void x(int y)) {} | |
| 2060 '''); | |
| 2061 check(implicitDynamic: false); | |
| 2062 } | |
| 2063 | |
| 2064 void test_implicitDynamic_return() { | |
| 2065 addFile(r''' | |
| 2066 // function | |
| 2067 /*error:IMPLICIT_DYNAMIC_RETURN*/f0() {} | |
| 2068 dynamic f1() { return 42; } | |
| 2069 | |
| 2070 // nested function | |
| 2071 void main() { | |
| 2072 /*error:IMPLICIT_DYNAMIC_RETURN*/g0() {} | |
| 2073 dynamic g1() { return 42; } | |
| 2074 } | |
| 2075 | |
| 2076 // methods | |
| 2077 class B { | |
| 2078 int m1() => 42; | |
| 2079 } | |
| 2080 class C extends B { | |
| 2081 /*error:IMPLICIT_DYNAMIC_RETURN*/m0() => 123; | |
| 2082 m1() => 123; | |
| 2083 dynamic m2() => 'hi'; | |
| 2084 } | |
| 2085 | |
| 2086 // accessors | |
| 2087 set x(int value) {} | |
| 2088 /*error:IMPLICIT_DYNAMIC_RETURN*/get y0 => 42; | |
| 2089 dynamic get y1 => 42; | |
| 2090 | |
| 2091 // function typed formals | |
| 2092 void ftf0(/*error:IMPLICIT_DYNAMIC_RETURN*/f(int x)) {} | |
| 2093 void ftf1(dynamic f(int x)) {} | |
| 2094 | |
| 2095 // function expressions | |
| 2096 var fe0 = /*error:IMPLICIT_DYNAMIC_RETURN*/(int x) => x as dynamic; | |
| 2097 var fe1 = (int x) => x; | |
| 2098 '''); | |
| 2099 check(implicitDynamic: false); | |
| 2100 } | |
| 2101 | |
| 2102 void test_implicitDynamic_type() { | |
| 2103 addFile(r''' | |
| 2104 class C<T> {} | |
| 2105 class M1<T extends /*error:IMPLICIT_DYNAMIC_TYPE*/List> {} | |
| 2106 class M2<T> {} | |
| 2107 class I<T> {} | |
| 2108 class D<T, S> extends /*error:IMPLICIT_DYNAMIC_TYPE*/C | |
| 2109 with M1, /*error:IMPLICIT_DYNAMIC_TYPE*/M2 | |
| 2110 implements /*error:IMPLICIT_DYNAMIC_TYPE*/I {} | |
| 2111 | |
| 2112 C f(D d) { | |
| 2113 D x = new /*error:IMPLICIT_DYNAMIC_TYPE*/D(); | |
| 2114 D<int, dynamic> y = /*info:INFERRED_TYPE_ALLOCATION*/new /*error:IMPLICIT_DYNA MIC_TYPE*/D(); | |
| 2115 D<dynamic, int> z = /*info:INFERRED_TYPE_ALLOCATION*/new /*error:IMPLICIT_DYNA MIC_TYPE*/D(); | |
| 2116 return new /*error:IMPLICIT_DYNAMIC_TYPE*/C(); | |
| 2117 } | |
| 2118 | |
| 2119 class A<T extends num> {} | |
| 2120 class N1<T extends List<int>> {} | |
| 2121 class N2<T extends Object> {} | |
| 2122 class J<T extends Object> {} | |
| 2123 class B<T extends Object> extends A with N1, N2 implements J {} | |
| 2124 A g(B b) { | |
| 2125 B y = /*info:INFERRED_TYPE_ALLOCATION*/new B(); | |
| 2126 return /*info:INFERRED_TYPE_ALLOCATION*/new A(); | |
| 2127 } | |
| 2128 '''); | |
| 2129 check(implicitDynamic: false); | |
| 2130 } | |
| 2131 | |
| 2132 void test_implicitDynamic_variable() { | |
| 2133 addFile(r''' | |
| 2134 var /*error:IMPLICIT_DYNAMIC_VARIABLE*/x0; | |
| 2135 var /*error:IMPLICIT_DYNAMIC_VARIABLE*/x1 = (<dynamic>[])[0]; | |
| 2136 var /*error:IMPLICIT_DYNAMIC_VARIABLE*/x2, | |
| 2137 x3 = 42, | |
| 2138 /*error:IMPLICIT_DYNAMIC_VARIABLE*/x4; | |
| 2139 dynamic y0; | |
| 2140 dynamic y1 = (<dynamic>[])[0]; | |
| 2141 '''); | |
| 2142 check(implicitDynamic: false); | |
| 2143 } | |
| 2144 | |
| 1919 void test_invalidOverrides_baseClassOverrideToChildInterface() { | 2145 void test_invalidOverrides_baseClassOverrideToChildInterface() { |
| 1920 checkFile(''' | 2146 checkFile(''' |
| 1921 class A {} | 2147 class A {} |
| 1922 class B {} | 2148 class B {} |
| 1923 | 2149 |
| 1924 abstract class I { | 2150 abstract class I { |
| 1925 m(A a); | 2151 m(A a); |
| 1926 } | 2152 } |
| 1927 | 2153 |
| 1928 class Base { | 2154 class Base { |
| (...skipping 1380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3309 // Regression test for https://github.com/dart-lang/sdk/issues/25069 | 3535 // Regression test for https://github.com/dart-lang/sdk/issues/25069 |
| 3310 checkFile(''' | 3536 checkFile(''' |
| 3311 typedef int Foo(); | 3537 typedef int Foo(); |
| 3312 void foo() {} | 3538 void foo() {} |
| 3313 void main () { | 3539 void main () { |
| 3314 Foo x = /*error:INVALID_ASSIGNMENT,info:USE_OF_VOID_RESULT*/foo(); | 3540 Foo x = /*error:INVALID_ASSIGNMENT,info:USE_OF_VOID_RESULT*/foo(); |
| 3315 } | 3541 } |
| 3316 '''); | 3542 '''); |
| 3317 } | 3543 } |
| 3318 } | 3544 } |
| OLD | NEW |