Chromium Code Reviews| Index: pkg/analyzer/test/src/task/strong/checker_test.dart |
| diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart |
| index 3286d2131411599d24520ff3373b5a8790753544..4a32cae58b667d2ea88aef360f814f3dea2db97a 100644 |
| --- a/pkg/analyzer/test/src/task/strong/checker_test.dart |
| +++ b/pkg/analyzer/test/src/task/strong/checker_test.dart |
| @@ -315,6 +315,16 @@ test() { |
| '''); |
| } |
| + void test_constructorInvalid() { |
| + // Regression test for https://github.com/dart-lang/sdk/issues/26695 |
| + checkFile(''' |
| +class A { |
| + B({ /*error:FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR*/this.test: 1.0 }) {} |
| + final double test = 0.0; |
| +} |
| +'''); |
| + } |
| + |
| void test_constructors() { |
| checkFile(''' |
| const num z = 25; |
| @@ -349,16 +359,6 @@ void main() { |
| '''); |
| } |
| - void test_constructorInvalid() { |
| - // Regression test for https://github.com/dart-lang/sdk/issues/26695 |
| - checkFile(''' |
| -class A { |
| - B({ /*error:FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR*/this.test: 1.0 }) {} |
| - final double test = 0.0; |
| -} |
| -'''); |
| - } |
| - |
| void test_conversionAndDynamicInvoke() { |
| addFile( |
| ''' |
| @@ -1911,11 +1911,237 @@ main() { |
| addFile('num n; int i = /*info:ASSIGNMENT_CAST*/n;'); |
| check(); |
| // TODO(jmesserly): should not be emitting the hint as well as the error. |
| + // It is a "strong mode hint" however, so it will not be user visible. |
| addFile( |
| 'num n; int i = /*info:ASSIGNMENT_CAST,error:INVALID_ASSIGNMENT*/n;'); |
| check(implicitCasts: false); |
| } |
| + void test_implicitDynamic_field() { |
| + addFile(r''' |
| +class C { |
| + var /*error:IMPLICIT_DYNAMIC_FIELD*/x0; |
| + 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
|
| + var /*error:IMPLICIT_DYNAMIC_FIELD*/x2, |
| + x3 = 42, |
| + /*error:IMPLICIT_DYNAMIC_FIELD*/x4; |
| + dynamic y0; |
| + dynamic y1 = (<dynamic>[])[0]; |
| +} |
| + '''); |
| + check(implicitDynamic: false); |
| + } |
| + |
| + void test_implicitDynamic_function() { |
| + addFile(r''' |
| +/*=T*/ a/*<T>*/(/*=T*/ t) => t; |
| +/*=T*/ b/*<T>*/() => null; |
| + |
| +void main/*<S>*/() { |
| + dynamic d; |
| + int i; |
| + /*error:IMPLICIT_DYNAMIC_FUNCTION*/a(d); |
| + a(42); |
| + /*error:IMPLICIT_DYNAMIC_FUNCTION*/b(); |
| + d = /*error:IMPLICIT_DYNAMIC_FUNCTION*/b(); |
| + i = b(); |
| + |
| + void f/*<T>*/(/*=T*/ t) {}; |
| + /*=T*/ g/*<T>*/() => null; |
| + |
| + /*error:IMPLICIT_DYNAMIC_FUNCTION*/f(d); |
| + f(42); |
| + /*error:IMPLICIT_DYNAMIC_FUNCTION*/g(); |
| + d = /*error:IMPLICIT_DYNAMIC_FUNCTION*/g(); |
| + i = g(); |
| + |
| + /*error:IMPLICIT_DYNAMIC_INVOKE*/(/*<T>*/(/*=T*/ t) => t)(d); |
| + (/*<T>*/(/*=T*/ t) => t)(42); |
| + (/*<T>*/() => null as dynamic/*=T*/)/*<int>*/(); |
| +} |
|
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!
|
| + '''); |
| + check(implicitDynamic: false); |
| + } |
| + void test_implicitDynamic_listLiteral() { |
| + addFile(r''' |
| + |
| +var l0 = /*error:IMPLICIT_DYNAMIC_LIST_LITERAL*/[]; |
| +List l1 = /*error:IMPLICIT_DYNAMIC_LIST_LITERAL*/[]; |
| +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
|
| +dynamic d = 42; |
| +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
|
| + |
| +var l4 = <dynamic>[]; |
| +var l5 = <int>[]; |
| +List<int> l6 = /*info:INFERRED_TYPE_LITERAL*/[]; |
| +var l7 = /*info:INFERRED_TYPE_LITERAL*/[42]; |
| + '''); |
| + check(implicitDynamic: false); |
| + } |
| + |
| + void test_implicitDynamic_mapLiteral() { |
| + addFile(r''' |
| +var m0 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{}; |
| +Map m1 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{}; |
| +Map<dynamic, dynamic> m2 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{}; |
| +dynamic d = 42; |
| +var m3 = /*error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: d}; |
| +var m4 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{'x': d, 'y': d}; |
| +var m5 = /*info:INFERRED_TYPE_LITERAL,error:IMPLICIT_DYNAMIC_MAP_LITERAL*/{d: 'x'}; |
| + |
| +var m6 = <dynamic, dynamic>{}; |
| +var m7 = <String, String>{}; |
| +Map<String, String> m8 = /*info:INFERRED_TYPE_LITERAL*/{}; |
| +var m9 = /*info:INFERRED_TYPE_LITERAL*/{'hi': 'there'}; |
| + '''); |
| + check(implicitDynamic: false); |
| + } |
| + |
| + void test_implicitDynamic_method() { |
| + addFile(r''' |
| +class C { |
| + /*=T*/ m/*<T>*/(/*=T*/ s) => s; |
| + /*=T*/ n/*<T>*/() => null; |
| +} |
| +class D<E> { |
| + /*=T*/ m/*<T>*/(/*=T*/ s) => s; |
| + /*=T*/ n/*<T>*/() => null; |
| +} |
| +void f() { |
| + dynamic d; |
| + int i; |
| + new C()./*error:IMPLICIT_DYNAMIC_METHOD*/m(d); |
| + new C().m(42); |
| + new C()./*error:IMPLICIT_DYNAMIC_METHOD*/n(); |
| + d = new C()./*error:IMPLICIT_DYNAMIC_METHOD*/n(); |
| + i = new C().n(); |
| + |
| + 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
|
| + new D<int>().m(42); |
| + new D<int>()./*error:IMPLICIT_DYNAMIC_METHOD*/n(); |
| + d = new D<int>()./*error:IMPLICIT_DYNAMIC_METHOD*/n(); |
| + i = new D<int>().n(); |
| +} |
| + '''); |
| + check(implicitDynamic: false); |
| + } |
| + |
| + void test_implicitDynamic_parameter() { |
| + addFile(r''' |
| +const dynamic DYNAMIC_VALUE = 42; |
| + |
| +// simple formal |
| +void f0(/*error:IMPLICIT_DYNAMIC_PARAMETER*/x) {} |
| +void f1(dynamic x) {} |
| + |
| +// default formal |
| +void df0([/*error:IMPLICIT_DYNAMIC_PARAMETER*/x = DYNAMIC_VALUE]) {} |
| +void df1([dynamic x = DYNAMIC_VALUE]) {} |
| + |
| +// BUG: this should work, see https://github.com/dart-lang/sdk/issues/25794 |
| +void df2([/*error:IMPLICIT_DYNAMIC_PARAMETER*/x = 42]) {} |
| + |
| +// default formal (named) |
| +void nf0({/*error:IMPLICIT_DYNAMIC_PARAMETER*/x: DYNAMIC_VALUE}) {} |
| +void nf1({dynamic x: DYNAMIC_VALUE}) {} |
| + |
| +// BUG: this should work, see https://github.com/dart-lang/sdk/issues/25794 |
| +void nf2({/*error:IMPLICIT_DYNAMIC_PARAMETER*/x: 42}) {} |
| + |
| +// field formal |
| +class C { |
| + var /*error:IMPLICIT_DYNAMIC_FIELD*/x; |
| + C(this.x); |
| +} |
| + |
| +// function typed formal |
| +void ftf0(void x(/*error:IMPLICIT_DYNAMIC_PARAMETER*/y)) {} |
| +void ftf1(void x(int y)) {} |
| + '''); |
| + check(implicitDynamic: false); |
| + } |
| + |
| + void test_implicitDynamic_return() { |
| + addFile(r''' |
| +// function |
| +/*error:IMPLICIT_DYNAMIC_RETURN*/f0() {} |
| +dynamic f1() { return 42; } |
| + |
| +// nested function |
| +void main() { |
| + /*error:IMPLICIT_DYNAMIC_RETURN*/g0() {} |
| + dynamic g1() { return 42; } |
| +} |
| + |
| +// methods |
| +class B { |
| + int m1() => 42; |
| +} |
| +class C extends B { |
| + /*error:IMPLICIT_DYNAMIC_RETURN*/m0() => 123; |
| + m1() => 123; |
| + dynamic m2() => 'hi'; |
| +} |
| + |
| +// accessors |
| +set x(int value) {} |
| +/*error:IMPLICIT_DYNAMIC_RETURN*/get y0 => 42; |
| +dynamic get y1 => 42; |
| + |
| +// function typed formals |
| +void ftf0(/*error:IMPLICIT_DYNAMIC_RETURN*/f(int x)) {} |
| +void ftf1(dynamic f(int x)) {} |
| + |
| +// function expressions |
| +var fe0 = /*error:IMPLICIT_DYNAMIC_RETURN*/(int x) => x as dynamic; |
| +var fe1 = (int x) => x; |
| + '''); |
| + check(implicitDynamic: false); |
| + } |
| + |
| + void test_implicitDynamic_type() { |
| + addFile(r''' |
| +class C<T> {} |
| +class M1<T extends /*error:IMPLICIT_DYNAMIC_TYPE*/List> {} |
| +class M2<T> {} |
| +class I<T> {} |
| +class D<T, S> extends /*error:IMPLICIT_DYNAMIC_TYPE*/C |
| + with M1, /*error:IMPLICIT_DYNAMIC_TYPE*/M2 |
| + implements /*error:IMPLICIT_DYNAMIC_TYPE*/I {} |
| + |
| +C f(D d) { |
| + D x = new /*error:IMPLICIT_DYNAMIC_TYPE*/D(); |
| + D<int, dynamic> y = /*info:INFERRED_TYPE_ALLOCATION*/new /*error:IMPLICIT_DYNAMIC_TYPE*/D(); |
| + D<dynamic, int> z = /*info:INFERRED_TYPE_ALLOCATION*/new /*error:IMPLICIT_DYNAMIC_TYPE*/D(); |
| + return new /*error:IMPLICIT_DYNAMIC_TYPE*/C(); |
| +} |
| + |
| +class A<T extends num> {} |
| +class N1<T extends List<int>> {} |
| +class N2<T extends Object> {} |
| +class J<T extends Object> {} |
| +class B<T extends Object> extends A with N1, N2 implements J {} |
| +A g(B b) { |
| + B y = /*info:INFERRED_TYPE_ALLOCATION*/new B(); |
| + return /*info:INFERRED_TYPE_ALLOCATION*/new A(); |
| +} |
| + '''); |
| + check(implicitDynamic: false); |
| + } |
| + |
| + void test_implicitDynamic_variable() { |
| + addFile(r''' |
| +var /*error:IMPLICIT_DYNAMIC_VARIABLE*/x0; |
| +var /*error:IMPLICIT_DYNAMIC_VARIABLE*/x1 = (<dynamic>[])[0]; |
| +var /*error:IMPLICIT_DYNAMIC_VARIABLE*/x2, |
| + x3 = 42, |
| + /*error:IMPLICIT_DYNAMIC_VARIABLE*/x4; |
| +dynamic y0; |
| +dynamic y1 = (<dynamic>[])[0]; |
| + '''); |
| + check(implicitDynamic: false); |
| + } |
| + |
| void test_invalidOverrides_baseClassOverrideToChildInterface() { |
| checkFile(''' |
| class A {} |