Index: test/checker/checker_test.dart |
diff --git a/test/checker/checker_test.dart b/test/checker/checker_test.dart |
deleted file mode 100644 |
index ba9885292fd16fbc4eb60cefe25c59c150b49a9c..0000000000000000000000000000000000000000 |
--- a/test/checker/checker_test.dart |
+++ /dev/null |
@@ -1,2319 +0,0 @@ |
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-/// General type checking tests |
-library dev_compiler.test.checker_test; |
- |
-import 'package:test/test.dart'; |
- |
-import '../testing.dart'; |
- |
-void main() { |
- testChecker('ternary operator', { |
- '/main.dart': ''' |
- abstract class Comparable<T> { |
- int compareTo(T other); |
- static int compare(Comparable a, Comparable b) => a.compareTo(b); |
- } |
- typedef int Comparator<T>(T a, T b); |
- |
- typedef bool _Predicate<T>(T value); |
- |
- class SplayTreeMap<K, V> { |
- Comparator<K> _comparator; |
- _Predicate _validKey; |
- |
- // Initializing _comparator needs a cast, since K may not always be |
- // Comparable. |
- // Initializing _validKey shouldn't need a cast. Currently |
- // it requires inference to work because of dartbug.com/23381 |
- SplayTreeMap([int compare(K key1, K key2), |
- bool isValidKey(potentialKey)]) { |
- : _comparator = /*warning:DownCastComposite*/(compare == null) ? Comparable.compare : compare, |
- _validKey = /*info:InferredType should be pass*/(isValidKey != null) ? isValidKey : ((v) => true); |
- _Predicate<Object> _v = /*warning:DownCastComposite*/(isValidKey != null) ? isValidKey : ((v) => true); |
- _v = /*info:InferredType should be pass*/(isValidKey != null) ? _v : ((v) => true); |
- } |
- } |
- void main() { |
- Object obj = 42; |
- dynamic dyn = 42; |
- int i = 42; |
- |
- // Check the boolean conversion of the condition. |
- print((/*severe:StaticTypeError*/i) ? false : true); |
- print((/*info:DownCastImplicit*/obj) ? false : true); |
- print((/*info:DynamicCast*/dyn) ? false : true); |
- } |
- ''' |
- }); |
- |
- testChecker('if/for/do/while statements use boolean conversion', { |
- '/main.dart': ''' |
- main() { |
- dynamic d = 42; |
- Object obj = 42; |
- int i = 42; |
- bool b = false; |
- |
- if (b) {} |
- if (/*info:DynamicCast*/dyn) {} |
- if (/*info:DownCastImplicit*/obj) {} |
- if (/*severe:StaticTypeError*/i) {} |
- |
- while (b) {} |
- while (/*info:DynamicCast*/dyn) {} |
- while (/*info:DownCastImplicit*/obj) {} |
- while (/*severe:StaticTypeError*/i) {} |
- |
- do {} while (b); |
- do {} while (/*info:DynamicCast*/dyn); |
- do {} while (/*info:DownCastImplicit*/obj); |
- do {} while (/*severe:StaticTypeError*/i); |
- |
- for (;b;) {} |
- for (;/*info:DynamicCast*/dyn;) {} |
- for (;/*info:DownCastImplicit*/obj;) {} |
- for (;/*severe:StaticTypeError*/i;) {} |
- } |
- ''' |
- }); |
- |
- testChecker('dynamic invocation', { |
- '/main.dart': ''' |
- |
- class A { |
- dynamic call(dynamic x) => x; |
- } |
- class B extends A { |
- int call(int x) => x; |
- double col(double x) => x; |
- } |
- void main() { |
- { |
- B f = new B(); |
- int x; |
- double y; |
- // The analyzer has what I believe is a bug (dartbug.com/23252) which |
- // causes the return type of calls to f to be treated as dynamic. |
- x = /*info:DynamicCast should be pass*/f(3); |
- x = /*severe:StaticTypeError*/f.col(3.0); |
- y = /*info:DynamicCast should be severe:StaticTypeError*/f(3); |
- y = f.col(3.0); |
- f(/*severe:StaticTypeError*/3.0); |
- f.col(/*severe:StaticTypeError*/3); |
- } |
- { |
- Function f = new B(); |
- int x; |
- double y; |
- x = /*info:DynamicCast, info:DynamicInvoke*/f(3); |
- x = /*info:DynamicCast, info:DynamicInvoke*/f.col(3.0); |
- y = /*info:DynamicCast, info:DynamicInvoke*/f(3); |
- y = /*info:DynamicCast, info:DynamicInvoke*/f.col(3.0); |
- (/*info:DynamicInvoke*/f(3.0)); |
- (/*info:DynamicInvoke*/f.col(3)); |
- } |
- { |
- A f = new B(); |
- int x; |
- double y; |
- x = /*info:DynamicCast, info:DynamicInvoke*/f(3); |
- y = /*info:DynamicCast, info:DynamicInvoke*/f(3); |
- (/*info:DynamicInvoke*/f(3.0)); |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('conversion and dynamic invoke', { |
- '/helper.dart': ''' |
- dynamic toString = (int x) => x + 42; |
- dynamic hashCode = "hello"; |
- ''', |
- '/main.dart': ''' |
- import 'helper.dart' as helper; |
- |
- class A { |
- String x = "hello world"; |
- |
- void baz1(y) => x + /*info:DynamicCast*/y; |
- static baz2(y) => /*info:DynamicInvoke*/y + y; |
- } |
- |
- void foo(String str) { |
- print(str); |
- } |
- |
- class B { |
- String toString([int arg]) => arg.toString(); |
- } |
- |
- void bar(a) { |
- foo(/*info:DynamicCast,info:DynamicInvoke*/a.x); |
- } |
- |
- baz() => new B(); |
- |
- typedef DynFun(x); |
- typedef StrFun(String x); |
- |
- var bar1 = bar; |
- |
- void main() { |
- var a = new A(); |
- bar(a); |
- (/*info:DynamicInvoke*/bar1(a)); |
- var b = bar; |
- (/*info:DynamicInvoke*/b(a)); |
- var f1 = foo; |
- f1("hello"); |
- dynamic f2 = foo; |
- (/*info:DynamicInvoke*/f2("hello")); |
- DynFun f3 = foo; |
- (/*info:DynamicInvoke*/f3("hello")); |
- (/*info:DynamicInvoke*/f3(42)); |
- StrFun f4 = foo; |
- f4("hello"); |
- a.baz1("hello"); |
- var b1 = a.baz1; |
- (/*info:DynamicInvoke*/b1("hello")); |
- A.baz2("hello"); |
- var b2 = A.baz2; |
- (/*info:DynamicInvoke*/b2("hello")); |
- |
- dynamic a1 = new B(); |
- (/*info:DynamicInvoke*/a1.x); |
- a1.toString(); |
- (/*info:DynamicInvoke*/a1.toString(42)); |
- var toStringClosure = a1.toString; |
- (/*info:DynamicInvoke*/a1.toStringClosure()); |
- (/*info:DynamicInvoke*/a1.toStringClosure(42)); |
- (/*info:DynamicInvoke*/a1.toStringClosure("hello")); |
- a1.hashCode; |
- |
- dynamic toString = () => null; |
- (/*info:DynamicInvoke*/toString()); |
- |
- (/*info:DynamicInvoke*/helper.toString()); |
- var toStringClosure2 = helper.toString; |
- (/*info:DynamicInvoke*/toStringClosure2()); |
- int hashCode = /*info:DynamicCast*/helper.hashCode; |
- |
- baz().toString(); |
- baz().hashCode; |
- } |
- ''' |
- }); |
- |
- testChecker('Constructors', { |
- '/main.dart': ''' |
- const num z = 25; |
- Object obj = "world"; |
- |
- class A { |
- int x; |
- String y; |
- |
- A(this.x) : this.y = /*severe:StaticTypeError*/42; |
- |
- A.c1(p): this.x = /*info:DownCastImplicit*/z, this.y = /*info:DynamicCast*/p; |
- |
- A.c2(this.x, this.y); |
- |
- A.c3(/*severe:InvalidParameterDeclaration*/num this.x, String this.y); |
- } |
- |
- class B extends A { |
- B() : super(/*severe:StaticTypeError*/"hello"); |
- |
- B.c2(int x, String y) : super.c2(/*severe:StaticTypeError*/y, |
- /*severe:StaticTypeError*/x); |
- |
- B.c3(num x, Object y) : super.c3(x, /*info:DownCastImplicit*/y); |
- } |
- |
- void main() { |
- A a = new A.c2(/*info:DownCastImplicit*/z, /*severe:StaticTypeError*/z); |
- var b = new B.c2(/*severe:StaticTypeError*/"hello", /*info:DownCastImplicit*/obj); |
- } |
- ''' |
- }); |
- |
- testChecker('Unbound variable', { |
- '/main.dart': ''' |
- void main() { |
- dynamic y = /*pass should be severe:StaticTypeError*/unboundVariable; |
- } |
- ''' |
- }); |
- |
- testChecker('Unbound type name', { |
- '/main.dart': ''' |
- void main() { |
- /*pass should be severe:StaticTypeError*/AToB y; |
- } |
- ''' |
- }); |
- |
- testChecker('Ground type subtyping: dynamic is top', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- |
- void main() { |
- dynamic y; |
- Object o; |
- int i = 0; |
- double d = 0.0; |
- num n; |
- A a; |
- B b; |
- y = o; |
- y = i; |
- y = d; |
- y = n; |
- y = a; |
- y = b; |
- } |
- ''' |
- }); |
- |
- testChecker('Ground type subtyping: dynamic downcasts', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- |
- void main() { |
- dynamic y; |
- Object o; |
- int i = 0; |
- double d = 0.0; |
- num n; |
- A a; |
- B b; |
- o = y; |
- i = /*info:DynamicCast*/y; |
- d = /*info:DynamicCast*/y; |
- n = /*info:DynamicCast*/y; |
- a = /*info:DynamicCast*/y; |
- b = /*info:DynamicCast*/y; |
- } |
- ''' |
- }); |
- |
- testChecker('Ground type subtyping: assigning a class', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- |
- void main() { |
- dynamic y; |
- Object o; |
- int i = 0; |
- double d = 0.0; |
- num n; |
- A a; |
- B b; |
- y = a; |
- o = a; |
- i = /*severe:StaticTypeError*/a; |
- d = /*severe:StaticTypeError*/a; |
- n = /*severe:StaticTypeError*/a; |
- a = a; |
- b = /*info:DownCastImplicit*/a; |
- } |
- ''' |
- }); |
- |
- testChecker('Ground type subtyping: assigning a subclass', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- class C extends A {} |
- |
- void main() { |
- dynamic y; |
- Object o; |
- int i = 0; |
- double d = 0.0; |
- num n; |
- A a; |
- B b; |
- C c; |
- y = b; |
- o = b; |
- i = /*severe:StaticTypeError*/b; |
- d = /*severe:StaticTypeError*/b; |
- n = /*severe:StaticTypeError*/b; |
- a = b; |
- b = b; |
- c = /*severe:StaticTypeError*/b; |
- } |
- ''' |
- }); |
- |
- testChecker('Ground type subtyping: interfaces', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- class C extends A {} |
- class D extends B implements C {} |
- |
- void main() { |
- A top; |
- B left; |
- C right; |
- D bot; |
- { |
- top = top; |
- top = left; |
- top = right; |
- top = bot; |
- } |
- { |
- left = /*info:DownCastImplicit*/top; |
- left = left; |
- left = /*severe:StaticTypeError*/right; |
- left = bot; |
- } |
- { |
- right = /*info:DownCastImplicit*/top; |
- right = /*severe:StaticTypeError*/left; |
- right = right; |
- right = bot; |
- } |
- { |
- bot = /*info:DownCastImplicit*/top; |
- bot = /*info:DownCastImplicit*/left; |
- bot = /*info:DownCastImplicit*/right; |
- bot = bot; |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('Function typing and subtyping: int and object', { |
- '/main.dart': ''' |
- |
- typedef Object Top(int x); // Top of the lattice |
- typedef int Left(int x); // Left branch |
- typedef int Left2(int x); // Left branch |
- typedef Object Right(Object x); // Right branch |
- typedef int Bot(Object x); // Bottom of the lattice |
- |
- Object top(int x) => x; |
- int left(int x) => x; |
- Object right(Object x) => x; |
- int _bot(Object x) => /*info:DownCastImplicit*/x; |
- int bot(Object x) => x as int; |
- |
- void main() { |
- { // Check typedef equality |
- Left f = left; |
- Left2 g = f; |
- } |
- { |
- Top f; |
- f = top; |
- f = left; |
- f = right; |
- f = bot; |
- } |
- { |
- Left f; |
- f = /*warning:DownCastComposite*/top; |
- f = left; |
- f = /*warning:DownCastComposite*/right; // Should we reject this? |
- f = bot; |
- } |
- { |
- Right f; |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; // Should we reject this? |
- f = right; |
- f = bot; |
- } |
- { |
- Bot f; |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; |
- f = /*warning:DownCastComposite*/right; |
- f = bot; |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('Function typing and subtyping: classes', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- |
- typedef A Top(B x); // Top of the lattice |
- typedef B Left(B x); // Left branch |
- typedef B Left2(B x); // Left branch |
- typedef A Right(A x); // Right branch |
- typedef B Bot(A x); // Bottom of the lattice |
- |
- B left(B x) => x; |
- B _bot(A x) => /*info:DownCastImplicit*/x; |
- B bot(A x) => x as B; |
- A top(B x) => x; |
- A right(A x) => x; |
- |
- void main() { |
- { // Check typedef equality |
- Left f = left; |
- Left2 g = f; |
- } |
- { |
- Top f; |
- f = top; |
- f = left; |
- f = right; |
- f = bot; |
- } |
- { |
- Left f; |
- f = /*warning:DownCastComposite*/top; |
- f = left; |
- f = /*warning:DownCastComposite*/right; // Should we reject this? |
- f = bot; |
- } |
- { |
- Right f; |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; // Should we reject this? |
- f = right; |
- f = bot; |
- } |
- { |
- Bot f; |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; |
- f = /*warning:DownCastComposite*/right; |
- f = bot; |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('Function typing and subtyping: dynamic', { |
- '/main.dart': ''' |
- |
- class A {} |
- |
- typedef dynamic Top(dynamic x); // Top of the lattice |
- typedef dynamic Left(A x); // Left branch |
- typedef A Right(dynamic x); // Right branch |
- typedef A Bottom(A x); // Bottom of the lattice |
- |
- dynamic left(A x) => x; |
- A bot(A x) => x; |
- dynamic top(dynamic x) => x; |
- A right(dynamic x) => /*info:DynamicCast*/x; |
- |
- void main() { |
- { |
- Top f; |
- f = top; |
- f = left; |
- f = right; |
- f = bot; |
- } |
- { |
- Left f; |
- f = /*warning:DownCastComposite*/top; |
- f = left; |
- f = /*warning:DownCastComposite*/right; |
- f = bot; |
- } |
- { |
- Right f; |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; |
- f = right; |
- f = bot; |
- } |
- { |
- Bottom f; |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; |
- f = /*warning:DownCastComposite*/right; |
- f = bot; |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('Function typing and subtyping: function literal variance', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- |
- typedef T Function2<S, T>(S z); |
- |
- A top(B x) => x; |
- B left(B x) => x; |
- A right(A x) => x; |
- B bot(A x) => x as B; |
- |
- void main() { |
- { |
- Function2<B, A> f; |
- f = top; |
- f = left; |
- f = right; |
- f = bot; |
- } |
- { |
- Function2<B, B> f; |
- f = /*warning:DownCastComposite*/top; |
- f = left; |
- f = /*warning:DownCastComposite*/right; // Should we reject this? |
- f = bot; |
- } |
- { |
- Function2<A, A> f; |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; // Should we reject this? |
- f = right; |
- f = bot; |
- } |
- { |
- Function2<A, B> f; |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; |
- f = /*warning:DownCastComposite*/right; |
- f = bot; |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('Function typing and subtyping: function variable variance', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- |
- typedef T Function2<S, T>(S z); |
- |
- void main() { |
- { |
- Function2<B, A> top; |
- Function2<B, B> left; |
- Function2<A, A> right; |
- Function2<A, B> bot; |
- |
- top = right; |
- top = bot; |
- top = top; |
- top = left; |
- |
- left = /*warning:DownCastComposite*/top; |
- left = left; |
- left = /*warning:DownCastComposite*/right; // Should we reject this? |
- left = bot; |
- |
- right = /*warning:DownCastComposite*/top; |
- right = /*warning:DownCastComposite*/left; // Should we reject this? |
- right = right; |
- right = bot; |
- |
- bot = /*warning:DownCastComposite*/top; |
- bot = /*warning:DownCastComposite*/left; |
- bot = /*warning:DownCastComposite*/right; |
- bot = bot; |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('Function typing and subtyping: higher order function literals', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- |
- typedef T Function2<S, T>(S z); |
- |
- typedef A BToA(B x); // Top of the base lattice |
- typedef B AToB(A x); // Bot of the base lattice |
- |
- BToA top(AToB f) => f; |
- AToB left(AToB f) => f; |
- BToA right(BToA f) => f; |
- AToB _bot(BToA f) => /*warning:DownCastComposite*/f; |
- AToB bot(BToA f) => f as AToB; |
- |
- Function2<B, A> top(AToB f) => f; |
- Function2<A, B> left(AToB f) => f; |
- Function2<B, A> right(BToA f) => f; |
- Function2<A, B> _bot(BToA f) => /*warning:DownCastComposite*/f; |
- Function2<A, B> bot(BToA f) => f as Function2<A, B>; |
- |
- |
- BToA top(Function2<A, B> f) => f; |
- AToB left(Function2<A, B> f) => f; |
- BToA right(Function2<B, A> f) => f; |
- AToB _bot(Function2<B, A> f) => /*warning:DownCastComposite*/f; |
- AToB bot(Function2<B, A> f) => f as AToB; |
- |
- void main() { |
- { |
- Function2<AToB, BToA> f; // Top |
- f = top; |
- f = left; |
- f = right; |
- f = bot; |
- } |
- { |
- Function2<AToB, AToB> f; // Left |
- f = /*warning:DownCastComposite*/top; |
- f = left; |
- f = /*warning:DownCastComposite*/right; // Should we reject this? |
- f = bot; |
- } |
- { |
- Function2<BToA, BToA> f; // Right |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; // Should we reject this? |
- f = right; |
- f = bot; |
- } |
- { |
- Function2<BToA, AToB> f; // Bot |
- f = bot; |
- f = /*warning:DownCastComposite*/left; |
- f = /*warning:DownCastComposite*/top; |
- f = /*warning:DownCastComposite*/left; |
- } |
- } |
- ''' |
- }); |
- |
- testChecker( |
- 'Function typing and subtyping: higher order function variables', { |
- '/main.dart': ''' |
- |
- class A {} |
- class B extends A {} |
- |
- typedef T Function2<S, T>(S z); |
- |
- void main() { |
- { |
- Function2<Function2<A, B>, Function2<B, A>> top; |
- Function2<Function2<B, A>, Function2<B, A>> right; |
- Function2<Function2<A, B>, Function2<A, B>> left; |
- Function2<Function2<B, A>, Function2<A, B>> bot; |
- |
- top = right; |
- top = bot; |
- top = top; |
- top = left; |
- |
- left = /*warning:DownCastComposite*/top; |
- left = left; |
- left = |
- /*warning:DownCastComposite should be severe:StaticTypeError*/right; |
- left = bot; |
- |
- right = /*warning:DownCastComposite*/top; |
- right = |
- /*warning:DownCastComposite should be severe:StaticTypeError*/left; |
- right = right; |
- right = bot; |
- |
- bot = /*warning:DownCastComposite*/top; |
- bot = /*warning:DownCastComposite*/left; |
- bot = /*warning:DownCastComposite*/right; |
- bot = bot; |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('Function typing and subtyping: named and optional parameters', { |
- '/main.dart': ''' |
- |
- class A {} |
- |
- typedef A FR(A x); |
- typedef A FO([A x]); |
- typedef A FN({A x}); |
- typedef A FRR(A x, A y); |
- typedef A FRO(A x, [A y]); |
- typedef A FRN(A x, {A n}); |
- typedef A FOO([A x, A y]); |
- typedef A FNN({A x, A y}); |
- typedef A FNNN({A z, A y, A x}); |
- |
- void main() { |
- FR r; |
- FO o; |
- FN n; |
- FRR rr; |
- FRO ro; |
- FRN rn; |
- FOO oo; |
- FNN nn; |
- FNNN nnn; |
- |
- r = r; |
- r = o; |
- r = /*severe:StaticTypeError*/n; |
- r = /*severe:StaticTypeError*/rr; |
- r = ro; |
- r = rn; |
- r = oo; |
- r = /*severe:StaticTypeError*/nn; |
- r = /*severe:StaticTypeError*/nnn; |
- |
- o = /*warning:DownCastComposite*/r; |
- o = o; |
- o = /*severe:StaticTypeError*/n; |
- o = /*severe:StaticTypeError*/rr; |
- o = /*severe:StaticTypeError*/ro; |
- o = /*severe:StaticTypeError*/rn; |
- o = oo; |
- o = /*severe:StaticTypeError*/nn |
- o = /*severe:StaticTypeError*/nnn; |
- |
- n = /*severe:StaticTypeError*/r; |
- n = /*severe:StaticTypeError*/o; |
- n = n; |
- n = /*severe:StaticTypeError*/rr; |
- n = /*severe:StaticTypeError*/ro; |
- n = /*severe:StaticTypeError*/rn; |
- n = /*severe:StaticTypeError*/oo; |
- n = nn; |
- n = nnn; |
- |
- rr = /*severe:StaticTypeError*/r; |
- rr = /*severe:StaticTypeError*/o; |
- rr = /*severe:StaticTypeError*/n; |
- rr = rr; |
- rr = ro; |
- rr = /*severe:StaticTypeError*/rn; |
- rr = oo; |
- rr = /*severe:StaticTypeError*/nn; |
- rr = /*severe:StaticTypeError*/nnn; |
- |
- ro = /*warning:DownCastComposite*/r; |
- ro = /*severe:StaticTypeError*/o; |
- ro = /*severe:StaticTypeError*/n; |
- ro = /*warning:DownCastComposite*/rr; |
- ro = ro; |
- ro = /*severe:StaticTypeError*/rn; |
- ro = oo; |
- ro = /*severe:StaticTypeError*/nn; |
- ro = /*severe:StaticTypeError*/nnn; |
- |
- rn = /*warning:DownCastComposite*/r; |
- rn = /*severe:StaticTypeError*/o; |
- rn = /*severe:StaticTypeError*/n; |
- rn = /*severe:StaticTypeError*/rr; |
- rn = /*severe:StaticTypeError*/ro; |
- rn = rn; |
- rn = /*severe:StaticTypeError*/oo; |
- rn = /*severe:StaticTypeError*/nn; |
- rn = /*severe:StaticTypeError*/nnn; |
- |
- oo = /*warning:DownCastComposite*/r; |
- oo = /*warning:DownCastComposite*/o; |
- oo = /*severe:StaticTypeError*/n; |
- oo = /*warning:DownCastComposite*/rr; |
- oo = /*warning:DownCastComposite*/ro; |
- oo = /*severe:StaticTypeError*/rn; |
- oo = oo; |
- oo = /*severe:StaticTypeError*/nn; |
- oo = /*severe:StaticTypeError*/nnn; |
- |
- nn = /*severe:StaticTypeError*/r; |
- nn = /*severe:StaticTypeError*/o; |
- nn = /*warning:DownCastComposite*/n; |
- nn = /*severe:StaticTypeError*/rr; |
- nn = /*severe:StaticTypeError*/ro; |
- nn = /*severe:StaticTypeError*/rn; |
- nn = /*severe:StaticTypeError*/oo; |
- nn = nn; |
- nn = nnn; |
- |
- nnn = /*severe:StaticTypeError*/r; |
- nnn = /*severe:StaticTypeError*/o; |
- nnn = /*warning:DownCastComposite*/n; |
- nnn = /*severe:StaticTypeError*/rr; |
- nnn = /*severe:StaticTypeError*/ro; |
- nnn = /*severe:StaticTypeError*/rn; |
- nnn = /*severe:StaticTypeError*/oo; |
- nnn = /*warning:DownCastComposite*/nn; |
- nnn = nnn; |
- } |
- ''' |
- }); |
- |
- testChecker('Function subtyping: objects with call methods', { |
- '/main.dart': ''' |
- |
- typedef int I2I(int x); |
- typedef num N2N(num x); |
- class A { |
- int call(int x) => x; |
- } |
- class B { |
- num call(num x) => x; |
- } |
- int i2i(int x) => x; |
- num n2n(num x) => x; |
- void main() { |
- { |
- I2I f; |
- f = new A(); |
- f = /*severe:StaticTypeError*/new B(); |
- f = i2i; |
- f = /*warning:DownCastComposite*/n2n; |
- f = /*warning:DownCastComposite*/i2i as Object; |
- f = /*warning:DownCastComposite*/n2n as Function; |
- } |
- { |
- N2N f; |
- f = /*severe:StaticTypeError*/new A(); |
- f = new B(); |
- f = /*warning:DownCastComposite*/i2i; |
- f = n2n; |
- f = /*warning:DownCastComposite*/i2i as Object; |
- f = /*warning:DownCastComposite*/n2n as Function; |
- } |
- { |
- A f; |
- f = new A(); |
- f = /*severe:StaticTypeError*/new B(); |
- f = /*severe:StaticTypeError*/i2i; |
- f = /*severe:StaticTypeError*/n2n; |
- f = /*info:DownCastImplicit*/i2i as Object; |
- f = /*info:DownCastImplicit*/n2n as Function; |
- } |
- { |
- B f; |
- f = /*severe:StaticTypeError*/new A(); |
- f = new B(); |
- f = /*severe:StaticTypeError*/i2i; |
- f = /*severe:StaticTypeError*/n2n; |
- f = /*info:DownCastImplicit*/i2i as Object; |
- f = /*info:DownCastImplicit*/n2n as Function; |
- } |
- { |
- Function f; |
- f = new A(); |
- f = new B(); |
- f = i2i; |
- f = n2n; |
- f = /*info:DownCastImplicit*/i2i as Object; |
- f = (n2n as Function); |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('Function typing and subtyping: void', { |
- '/main.dart': ''' |
- |
- class A { |
- void bar() => null; |
- void foo() => bar; // allowed |
- } |
- ''' |
- }); |
- |
- testChecker('Relaxed casts', { |
- '/main.dart': ''' |
- |
- class A {} |
- |
- class L<T> {} |
- class M<T> extends L<T> {} |
- // L<dynamic|Object> |
- // / \ |
- // M<dynamic|Object> L<A> |
- // \ / |
- // M<A> |
- // In normal Dart, there are additional edges |
- // from M<A> to M<dynamic> |
- // from L<A> to M<dynamic> |
- // from L<A> to L<dynamic> |
- void main() { |
- L lOfDs; |
- L<Object> lOfOs; |
- L<A> lOfAs; |
- |
- M mOfDs; |
- M<Object> mOfOs; |
- M<A> mOfAs; |
- |
- { |
- lOfDs = mOfDs; |
- lOfDs = mOfOs; |
- lOfDs = mOfAs; |
- lOfDs = lOfDs; |
- lOfDs = lOfOs; |
- lOfDs = lOfAs; |
- } |
- { |
- lOfOs = mOfDs; |
- lOfOs = mOfOs; |
- lOfOs = mOfAs; |
- lOfOs = lOfDs; |
- lOfOs = lOfOs; |
- lOfOs = lOfAs; |
- } |
- { |
- lOfAs = /*warning:DownCastComposite*/mOfDs; |
- lOfAs = /*severe:StaticTypeError*/mOfOs; |
- lOfAs = mOfAs; |
- lOfAs = /*warning:DownCastComposite*/lOfDs; |
- lOfAs = /*warning:DownCastComposite*/lOfOs; |
- lOfAs = lOfAs; |
- } |
- { |
- mOfDs = mOfDs; |
- mOfDs = mOfOs; |
- mOfDs = mOfAs; |
- mOfDs = /*info:DownCastImplicit*/lOfDs; |
- mOfDs = /*info:DownCastImplicit*/lOfOs; |
- mOfDs = /*info:DownCastImplicit*/lOfAs; |
- } |
- { |
- mOfOs = mOfDs; |
- mOfOs = mOfOs; |
- mOfOs = mOfAs; |
- mOfOs = /*info:DownCastImplicit*/lOfDs; |
- mOfOs = /*info:DownCastImplicit*/lOfOs; |
- mOfOs = /*severe:StaticTypeError*/lOfAs; |
- } |
- { |
- mOfAs = /*warning:DownCastComposite*/mOfDs; |
- mOfAs = /*warning:DownCastComposite*/mOfOs; |
- mOfAs = mOfAs; |
- mOfAs = /*warning:DownCastComposite*/lOfDs; |
- mOfAs = /*warning:DownCastComposite*/lOfOs; |
- mOfAs = /*warning:DownCastComposite*/lOfAs; |
- } |
- |
- } |
- ''' |
- }); |
- |
- testChecker('Type checking literals', { |
- '/main.dart': ''' |
- test() { |
- num n = 3; |
- int i = 3; |
- String s = "hello"; |
- { |
- List<int> l = <int>[i]; |
- l = <int>[/*severe:StaticTypeError*/s]; |
- l = <int>[/*info:DownCastImplicit*/n]; |
- l = <int>[i, /*info:DownCastImplicit*/n, /*severe:StaticTypeError*/s]; |
- } |
- { |
- List l = [i]; |
- l = [s]; |
- l = [n]; |
- l = [i, n, s]; |
- } |
- { |
- Map<String, int> m = <String, int>{s: i}; |
- m = <String, int>{s: /*severe:StaticTypeError*/s}; |
- m = <String, int>{s: /*info:DownCastImplicit*/n}; |
- m = <String, int>{s: i, |
- s: /*info:DownCastImplicit*/n, |
- s: /*severe:StaticTypeError*/s}; |
- } |
- // TODO(leafp): We can't currently test for key errors since the |
- // error marker binds to the entire entry. |
- { |
- Map m = {s: i}; |
- m = {s: s}; |
- m = {s: n}; |
- m = {s: i, |
- s: n, |
- s: s}; |
- m = {i: s, |
- n: s, |
- s: s}; |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('casts in constant contexts', { |
- '/main.dart': ''' |
- class A { |
- static const num n = 3.0; |
- static const int i = /*info:AssignmentCast*/n; |
- final int fi; |
- const A(num a) : this.fi = /*info:DownCastImplicit*/a; |
- } |
- class B extends A { |
- const B(Object a) : super(/*info:DownCastImplicit*/a); |
- } |
- void foo(Object o) { |
- var a = const A(/*info:DownCastImplicit*/o); |
- } |
- ''' |
- }); |
- |
- testChecker('casts in conditionals', { |
- '/main.dart': ''' |
- main() { |
- bool b = true; |
- num x = b ? 1 : 2.3; |
- int y = /*info:AssignmentCast*/b ? 1 : 2.3; |
- String z = !b ? "hello" : null; |
- z = b ? null : "hello"; |
- } |
- ''' |
- }); |
- |
- testChecker('redirecting constructor', { |
- '/main.dart': ''' |
- class A { |
- A(A x) {} |
- A.two() : this(/*severe:StaticTypeError*/3); |
- } |
- ''' |
- }); |
- |
- testChecker('super constructor', { |
- '/main.dart': ''' |
- class A { A(A x) {} } |
- class B extends A { |
- B() : super(/*severe:StaticTypeError*/3); |
- } |
- ''' |
- }); |
- |
- testChecker('field/field override', { |
- '/main.dart': ''' |
- class A {} |
- class B extends A {} |
- class C extends B {} |
- |
- class Base { |
- B f1; |
- B f2; |
- B f3; |
- B f4; |
- } |
- |
- class Child extends Base { |
- /*severe:InvalidMethodOverride*/A f1; // invalid for getter |
- /*severe:InvalidMethodOverride*/C f2; // invalid for setter |
- var f3; |
- /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/dynamic f4; |
- } |
- ''' |
- }); |
- |
- testChecker('getter/getter override', { |
- '/main.dart': ''' |
- class A {} |
- class B extends A {} |
- class C extends B {} |
- |
- abstract class Base { |
- B get f1; |
- B get f2; |
- B get f3; |
- B get f4; |
- } |
- |
- class Child extends Base { |
- /*severe:InvalidMethodOverride*/A get f1 => null; |
- C get f2 => null; |
- get f3 => null; |
- /*severe:InvalidMethodOverride*/dynamic get f4 => null; |
- } |
- ''' |
- }); |
- |
- testChecker('field/getter override', { |
- '/main.dart': ''' |
- class A {} |
- class B extends A {} |
- class C extends B {} |
- |
- abstract class Base { |
- B f1; |
- B f2; |
- B f3; |
- B f4; |
- } |
- |
- class Child extends Base { |
- /*severe:InvalidMethodOverride*/A get f1 => null; |
- C get f2 => null; |
- get f3 => null; |
- /*severe:InvalidMethodOverride*/dynamic get f4 => null; |
- } |
- ''' |
- }); |
- |
- testChecker('setter/setter override', { |
- '/main.dart': ''' |
- class A {} |
- class B extends A {} |
- class C extends B {} |
- |
- abstract class Base { |
- void set f1(B value); |
- void set f2(B value); |
- void set f3(B value); |
- void set f4(B value); |
- void set f5(B value); |
- } |
- |
- class Child extends Base { |
- void set f1(A value) {} |
- /*severe:InvalidMethodOverride*/void set f2(C value) {} |
- void set f3(value) {} |
- /*severe:InvalidMethodOverride*/void set f4(dynamic value) {} |
- set f5(B value) {} |
- } |
- ''' |
- }); |
- |
- testChecker('field/setter override', { |
- '/main.dart': ''' |
- class A {} |
- class B extends A {} |
- class C extends B {} |
- |
- class Base { |
- B f1; |
- B f2; |
- B f3; |
- B f4; |
- B f5; |
- } |
- |
- class Child extends Base { |
- B get f1 => null; |
- B get f2 => null; |
- B get f3 => null; |
- B get f4 => null; |
- B get f5 => null; |
- |
- void set f1(A value) {} |
- /*severe:InvalidMethodOverride*/void set f2(C value) {} |
- void set f3(value) {} |
- /*severe:InvalidMethodOverride*/void set f4(dynamic value) {} |
- set f5(B value) {} |
- } |
- ''' |
- }); |
- |
- testChecker('method override', { |
- '/main.dart': ''' |
- class A {} |
- class B extends A {} |
- class C extends B {} |
- |
- class Base { |
- B m1(B a); |
- B m2(B a); |
- B m3(B a); |
- B m4(B a); |
- B m5(B a); |
- B m6(B a); |
- } |
- |
- class Child extends Base { |
- /*severe:InvalidMethodOverride*/A m1(A value) {} |
- /*severe:InvalidMethodOverride*/C m2(C value) {} |
- /*severe:InvalidMethodOverride*/A m3(C value) {} |
- C m4(A value) {} |
- m5(value) {} |
- /*severe:InvalidMethodOverride*/dynamic m6(dynamic value) {} |
- } |
- ''' |
- }); |
- |
- testChecker('unary operators', { |
- '/main.dart': ''' |
- class A { |
- A operator ~() {} |
- A operator +(int x) {} |
- A operator -(int x) {} |
- A operator -() {} |
- } |
- |
- foo() => new A(); |
- |
- test() { |
- A a = new A(); |
- var c = foo(); |
- |
- ~a; |
- (/*info:DynamicInvoke*/~d); |
- |
- !/*severe:StaticTypeError*/a; |
- !/*info:DynamicCast*/d; |
- |
- -a; |
- (/*info:DynamicInvoke*/-d); |
- |
- ++a; |
- --a; |
- (/*info:DynamicInvoke*/++d); |
- (/*info:DynamicInvoke*/--d); |
- |
- a++; |
- a--; |
- (/*info:DynamicInvoke*/d++); |
- (/*info:DynamicInvoke*/d--); |
- }''' |
- }); |
- |
- testChecker('binary and index operators', { |
- '/main.dart': ''' |
- class A { |
- A operator *(B b) {} |
- A operator /(B b) {} |
- A operator ~/(B b) {} |
- A operator %(B b) {} |
- A operator +(B b) {} |
- A operator -(B b) {} |
- A operator <<(B b) {} |
- A operator >>(B b) {} |
- A operator &(B b) {} |
- A operator ^(B b) {} |
- A operator |(B b) {} |
- A operator[](B b) {} |
- } |
- |
- class B { |
- A operator -(B b) {} |
- } |
- |
- foo() => new A(); |
- |
- test() { |
- A a = new A(); |
- B b = new B(); |
- var c = foo(); |
- a = a * b; |
- a = a * /*info:DynamicCast*/c; |
- a = a / b; |
- a = a ~/ b; |
- a = a % b; |
- a = a + b; |
- a = a + /*severe:StaticTypeError*/a; |
- a = a - b; |
- b = /*severe:StaticTypeError*/b - b; |
- a = a << b; |
- a = a >> b; |
- a = a & b; |
- a = a ^ b; |
- a = a | b; |
- c = (/*info:DynamicInvoke*/c + b); |
- |
- String x = 'hello'; |
- int y = 42; |
- x = x + x; |
- x = x + /*info:DynamicCast*/c; |
- x = x + /*severe:StaticTypeError*/y; |
- |
- bool p = true; |
- p = p && p; |
- p = p && /*info:DynamicCast*/c; |
- p = (/*info:DynamicCast*/c) && p; |
- p = (/*info:DynamicCast*/c) && /*info:DynamicCast*/c; |
- p = (/*severe:StaticTypeError*/y) && p; |
- p = c == y; |
- |
- a = a[b]; |
- a = a[/*info:DynamicCast*/c]; |
- c = (/*info:DynamicInvoke*/c[b]); |
- a[/*severe:StaticTypeError*/y]; |
- } |
- ''' |
- }); |
- |
- testChecker('compound assignments', { |
- '/main.dart': ''' |
- class A { |
- A operator *(B b) {} |
- A operator /(B b) {} |
- A operator ~/(B b) {} |
- A operator %(B b) {} |
- A operator +(B b) {} |
- A operator -(B b) {} |
- A operator <<(B b) {} |
- A operator >>(B b) {} |
- A operator &(B b) {} |
- A operator ^(B b) {} |
- A operator |(B b) {} |
- D operator [](B index) {} |
- void operator []=(B index, D value) {} |
- } |
- |
- class B { |
- A operator -(B b) {} |
- } |
- |
- class D { |
- D operator +(D d) {} |
- } |
- |
- foo() => new A(); |
- |
- test() { |
- int x = 0; |
- x += 5; |
- (/*severe:StaticTypeError*/x += 3.14); |
- |
- double y = 0.0; |
- y += 5; |
- y += 3.14; |
- |
- num z = 0; |
- z += 5; |
- z += 3.14; |
- |
- x = /*info:DownCastImplicit*/x + z; |
- x += /*info:DownCastImplicit*/z; |
- y = /*info:DownCastImplicit*/y + z; |
- y += /*info:DownCastImplicit*/z; |
- |
- dynamic w = 42; |
- x += /*info:DynamicCast*/w; |
- y += /*info:DynamicCast*/w; |
- z += /*info:DynamicCast*/w; |
- |
- A a = new A(); |
- B b = new B(); |
- var c = foo(); |
- a = a * b; |
- a *= b; |
- a *= /*info:DynamicCast*/c; |
- a /= b; |
- a ~/= b; |
- a %= b; |
- a += b; |
- a += /*severe:StaticTypeError*/a; |
- a -= b; |
- (/*severe:StaticTypeError*/b -= b); |
- a <<= b; |
- a >>= b; |
- a &= b; |
- a ^= b; |
- a |= b; |
- (/*info:DynamicInvoke*/c += b); |
- |
- var d = new D(); |
- a[b] += d; |
- a[/*info:DynamicCast*/c] += d; |
- a[/*severe:StaticTypeError*/z] += d; |
- a[b] += /*info:DynamicCast*/c; |
- a[b] += /*severe:StaticTypeError*/z; |
- (/*info:DynamicInvoke*/(/*info:DynamicInvoke*/c[b]) += d); |
- } |
- ''' |
- }); |
- |
- testChecker('super call placement', { |
- '/main.dart': ''' |
- class Base { |
- var x; |
- Base() : x = print('Base.1') { print('Base.2'); } |
- } |
- |
- class Derived extends Base { |
- var y, z; |
- Derived() |
- : y = print('Derived.1'), |
- /*severe:InvalidSuperInvocation*/super(), |
- z = print('Derived.2') { |
- print('Derived.3'); |
- } |
- } |
- |
- class Valid extends Base { |
- var y, z; |
- Valid() |
- : y = print('Valid.1'), |
- z = print('Valid.2'), |
- super() { |
- print('Valid.3'); |
- } |
- } |
- |
- class AlsoValid extends Base { |
- AlsoValid() : super(); |
- } |
- |
- main() => new Derived(); |
- ''' |
- }); |
- |
- testChecker('for loop variable', { |
- '/main.dart': ''' |
- foo() { |
- for (int i = 0; i < 10; i++) { |
- i = /*severe:StaticTypeError*/"hi"; |
- } |
- } |
- bar() { |
- for (var i = 0; i < 10; i++) { |
- int j = i + 1; |
- } |
- } |
- ''' |
- }); |
- |
- group('invalid overrides', () { |
- testChecker('child override', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- class Base { |
- A f; |
- } |
- |
- class T1 extends Base { |
- /*severe:InvalidMethodOverride*/B get f => null; |
- } |
- |
- class T2 extends Base { |
- /*severe:InvalidMethodOverride*/set f(B b) => null; |
- } |
- |
- class T3 extends Base { |
- /*severe:InvalidMethodOverride*/final B f; |
- } |
- class T4 extends Base { |
- // two: one for the getter one for the setter. |
- /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/B f; |
- } |
- ''' |
- }); |
- |
- testChecker('child override 2', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- class Base { |
- m(A a) {} |
- } |
- |
- class Test extends Base { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- testChecker('grandchild override', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- class Grandparent { |
- m(A a) {} |
- } |
- class Parent extends Grandparent { |
- } |
- |
- class Test extends Parent { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- |
- testChecker('double override', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- class Grandparent { |
- m(A a) {} |
- } |
- class Parent extends Grandparent { |
- m(A a) {} |
- } |
- |
- class Test extends Parent { |
- // Reported only once |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- |
- testChecker('double override 2', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- class Grandparent { |
- m(A a) {} |
- } |
- class Parent extends Grandparent { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- |
- class Test extends Parent { |
- m(B a) {} |
- } |
- ''' |
- }); |
- |
- testChecker('mixin override to base', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- class Base { |
- m(A a) {} |
- } |
- |
- class M1 { |
- m(B a) {} |
- } |
- |
- class M2 {} |
- |
- class T1 extends Base with /*severe:InvalidMethodOverride*/M1 {} |
- class T2 extends Base with /*severe:InvalidMethodOverride*/M1, M2 {} |
- class T3 extends Base with M2, /*severe:InvalidMethodOverride*/M1 {} |
- ''' |
- }); |
- |
- testChecker('mixin override to mixin', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- class Base { |
- } |
- |
- class M1 { |
- m(B a) {} |
- } |
- |
- class M2 { |
- m(A a) {} |
- } |
- |
- class T1 extends Base with M1, /*severe:InvalidMethodOverride*/M2 {} |
- ''' |
- }); |
- |
- // This is a regression test for a bug in an earlier implementation were |
- // names were hiding errors if the first mixin override looked correct, |
- // but subsequent ones did not. |
- testChecker('no duplicate mixin override', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- class Base { |
- m(A a) {} |
- } |
- |
- class M1 { |
- m(A a) {} |
- } |
- |
- class M2 { |
- m(B a) {} |
- } |
- |
- class M3 { |
- m(B a) {} |
- } |
- |
- class T1 extends Base |
- with M1, /*severe:InvalidMethodOverride*/M2, M3 {} |
- ''' |
- }); |
- |
- testChecker('class override of interface', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I { |
- m(A a); |
- } |
- |
- class T1 implements I { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- |
- testChecker('base class override to child interface', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I { |
- m(A a); |
- } |
- |
- class Base { |
- m(B a) {} |
- } |
- |
- |
- class T1 /*severe:InvalidMethodOverride*/extends Base implements I { |
- } |
- ''' |
- }); |
- |
- testChecker('mixin override of interface', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I { |
- m(A a); |
- } |
- |
- class M { |
- m(B a) {} |
- } |
- |
- class T1 extends Object with /*severe:InvalidMethodOverride*/M |
- implements I {} |
- ''' |
- }); |
- |
- // This is a case were it is incorrect to say that the base class |
- // incorrectly overrides the interface. |
- testChecker( |
- 'no errors if subclass correctly overrides base and interface', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- class Base { |
- m(A a) {} |
- } |
- |
- class I1 { |
- m(B a) {} |
- } |
- |
- class T1 /*severe:InvalidMethodOverride*/extends Base |
- implements I1 {} |
- |
- class T2 extends Base implements I1 { |
- /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/m(a) {} |
- } |
- |
- class T3 extends Object with /*severe:InvalidMethodOverride*/Base |
- implements I1 {} |
- |
- class T4 extends Object with Base implements I1 { |
- /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/m(a) {} |
- } |
- ''' |
- }); |
- }); |
- |
- group('class override of grand interface', () { |
- testChecker('interface of interface of child', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- abstract class I2 implements I1 {} |
- |
- class T1 implements I2 { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- testChecker('superclass of interface of child', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- abstract class I2 extends I1 {} |
- |
- class T1 implements I2 { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- testChecker('mixin of interface of child', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class M1 { |
- m(A a); |
- } |
- abstract class I2 extends Object with M1 {} |
- |
- class T1 implements I2 { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- testChecker('interface of abstract superclass', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- abstract class Base implements I1 {} |
- |
- class T1 extends Base { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- testChecker('interface of concrete superclass', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- |
- // See issue #25 |
- /*pass should be warning:AnalyzerError*/class Base implements I1 { |
- } |
- |
- class T1 extends Base { |
- // not reported technically because if the class is concrete, |
- // it should implement all its interfaces and hence it is |
- // sufficient to check overrides against it. |
- m(B a) {} |
- } |
- ''' |
- }); |
- }); |
- |
- group('mixin override of grand interface', () { |
- testChecker('interface of interface of child', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- abstract class I2 implements I1 {} |
- |
- class M { |
- m(B a) {} |
- } |
- |
- class T1 extends Object with /*severe:InvalidMethodOverride*/M |
- implements I2 { |
- } |
- ''' |
- }); |
- testChecker('superclass of interface of child', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- abstract class I2 extends I1 {} |
- |
- class M { |
- m(B a) {} |
- } |
- |
- class T1 extends Object with /*severe:InvalidMethodOverride*/M |
- implements I2 { |
- } |
- ''' |
- }); |
- testChecker('mixin of interface of child', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class M1 { |
- m(A a); |
- } |
- abstract class I2 extends Object with M1 {} |
- |
- class M { |
- m(B a) {} |
- } |
- |
- class T1 extends Object with /*severe:InvalidMethodOverride*/M |
- implements I2 { |
- } |
- ''' |
- }); |
- testChecker('interface of abstract superclass', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- abstract class Base implements I1 {} |
- |
- class M { |
- m(B a) {} |
- } |
- |
- class T1 extends Base with /*severe:InvalidMethodOverride*/M { |
- } |
- ''' |
- }); |
- testChecker('interface of concrete superclass', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- |
- // See issue #25 |
- /*pass should be warning:AnalyzerError*/class Base implements I1 { |
- } |
- |
- class M { |
- m(B a) {} |
- } |
- |
- class T1 extends Base with M { |
- } |
- ''' |
- }); |
- }); |
- |
- group('superclass override of grand interface', () { |
- testChecker('interface of interface of child', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- abstract class I2 implements I1 {} |
- |
- class Base { |
- m(B a) {} |
- } |
- |
- class T1 /*severe:InvalidMethodOverride*/extends Base |
- implements I2 { |
- } |
- ''' |
- }); |
- testChecker('superclass of interface of child', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- abstract class I2 extends I1 {} |
- |
- class Base { |
- m(B a) {} |
- } |
- |
- class T1 /*severe:InvalidMethodOverride*/extends Base |
- implements I2 { |
- } |
- ''' |
- }); |
- testChecker('mixin of interface of child', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class M1 { |
- m(A a); |
- } |
- abstract class I2 extends Object with M1 {} |
- |
- class Base { |
- m(B a) {} |
- } |
- |
- class T1 /*severe:InvalidMethodOverride*/extends Base |
- implements I2 { |
- } |
- ''' |
- }); |
- testChecker('interface of abstract superclass', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- |
- abstract class Base implements I1 { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- |
- class T1 extends Base { |
- // we consider the base class incomplete because it is |
- // abstract, so we report the error here too. |
- // TODO(sigmund): consider tracking overrides in a fine-grain |
- // manner, then this and the double-overrides would not be |
- // reported. |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- testChecker('interface of concrete superclass', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- |
- class Base implements I1 { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- |
- class T1 extends Base { |
- m(B a) {} |
- } |
- ''' |
- }); |
- }); |
- |
- group('no duplicate reports from overriding interfaces', () { |
- testChecker('type overrides same method in multiple interfaces', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- abstract class I2 implements I1 { |
- m(A a); |
- } |
- |
- class Base { |
- } |
- |
- class T1 implements I2 { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- ''' |
- }); |
- |
- testChecker('type and base type override same method in interface', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- |
- class Base { |
- m(B a); |
- } |
- |
- // Note: no error reported in `extends Base` to avoid duplicating |
- // the error in T1. |
- class T1 extends Base implements I1 { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- |
- // If there is no error in the class, we do report the error at |
- // the base class: |
- class T2 /*severe:InvalidMethodOverride*/extends Base |
- implements I1 { |
- } |
- ''' |
- }); |
- |
- testChecker('type and mixin override same method in interface', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- |
- class M { |
- m(B a); |
- } |
- |
- class T1 extends Object with M implements I1 { |
- /*severe:InvalidMethodOverride*/m(B a) {} |
- } |
- |
- class T2 extends Object with /*severe:InvalidMethodOverride*/M |
- implements I1 { |
- } |
- ''' |
- }); |
- |
- testChecker('two grand types override same method in interface', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- |
- class Grandparent { |
- m(B a) {} |
- } |
- |
- class Parent1 extends Grandparent { |
- m(B a) {} |
- } |
- class Parent2 extends Grandparent { |
- } |
- |
- // Note: otherwise both errors would be reported on this line |
- class T1 /*severe:InvalidMethodOverride*/extends Parent1 |
- implements I1 { |
- } |
- class T2 /*severe:InvalidMethodOverride*/extends Parent2 |
- implements I1 { |
- } |
- ''' |
- }); |
- |
- testChecker('two mixins override same method in interface', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- |
- class M1 { |
- m(B a) {} |
- } |
- |
- class M2 { |
- m(B a) {} |
- } |
- |
- // Here we want to report both, because the error location is |
- // different. |
- // TODO(sigmund): should we merge these as well? |
- class T1 extends Object |
- with /*severe:InvalidMethodOverride*/M1 |
- with /*severe:InvalidMethodOverride*/M2 |
- implements I1 { |
- } |
- ''' |
- }); |
- |
- testChecker('base type and mixin override same method in interface', { |
- '/main.dart': ''' |
- class A {} |
- class B {} |
- |
- abstract class I1 { |
- m(A a); |
- } |
- |
- class Base { |
- m(B a) {} |
- } |
- |
- class M { |
- m(B a) {} |
- } |
- |
- // Here we want to report both, because the error location is |
- // different. |
- // TODO(sigmund): should we merge these as well? |
- class T1 /*severe:InvalidMethodOverride*/extends Base |
- with /*severe:InvalidMethodOverride*/M |
- implements I1 { |
- } |
- ''' |
- }); |
- }); |
- |
- testChecker('invalid runtime checks', { |
- '/main.dart': ''' |
- typedef int I2I(int x); |
- typedef int D2I(x); |
- typedef int II2I(int x, int y); |
- typedef int DI2I(x, int y); |
- typedef int ID2I(int x, y); |
- typedef int DD2I(x, y); |
- |
- typedef I2D(int x); |
- typedef D2D(x); |
- typedef II2D(int x, int y); |
- typedef DI2D(x, int y); |
- typedef ID2D(int x, y); |
- typedef DD2D(x, y); |
- |
- int foo(int x) => x; |
- int bar(int x, int y) => x + y; |
- |
- void main() { |
- bool b; |
- b = /*info:NonGroundTypeCheckInfo*/foo is I2I; |
- b = /*info:NonGroundTypeCheckInfo*/foo is D2I; |
- b = /*info:NonGroundTypeCheckInfo*/foo is I2D; |
- b = foo is D2D; |
- |
- b = /*info:NonGroundTypeCheckInfo*/bar is II2I; |
- b = /*info:NonGroundTypeCheckInfo*/bar is DI2I; |
- b = /*info:NonGroundTypeCheckInfo*/bar is ID2I; |
- b = /*info:NonGroundTypeCheckInfo*/bar is II2D; |
- b = /*info:NonGroundTypeCheckInfo*/bar is DD2I; |
- b = /*info:NonGroundTypeCheckInfo*/bar is DI2D; |
- b = /*info:NonGroundTypeCheckInfo*/bar is ID2D; |
- b = bar is DD2D; |
- |
- // For as, the validity of checks is deferred to runtime. |
- Function f; |
- f = foo as I2I; |
- f = foo as D2I; |
- f = foo as I2D; |
- f = foo as D2D; |
- |
- f = bar as II2I; |
- f = bar as DI2I; |
- f = bar as ID2I; |
- f = bar as II2D; |
- f = bar as DD2I; |
- f = bar as DI2D; |
- f = bar as ID2D; |
- f = bar as DD2D; |
- } |
- ''' |
- }); |
- |
- testChecker('custom URL mappings', { |
- '/main.dart': ''' |
- import 'dart:foobar' show Baz; |
- main() { |
- print(Baz.quux); |
- }''' |
- }, customUrlMappings: { |
- 'dart:foobar': '$testDirectory/checker/dart_foobar.dart' |
- }); |
- |
- group('function modifiers', () { |
- testChecker('async', { |
- '/main.dart': ''' |
- import 'dart:async'; |
- import 'dart:math' show Random; |
- |
- dynamic x; |
- |
- foo1() async => x; |
- Future foo2() async => x; |
- Future<int> foo3() async => (/*info:DynamicCast*/x); |
- Future<int> foo4() async => (/*severe:StaticTypeError*/new Future<int>.value(/*info:DynamicCast*/x)); |
- |
- bar1() async { return x; } |
- Future bar2() async { return x; } |
- Future<int> bar3() async { return (/*info:DynamicCast*/x); } |
- Future<int> bar4() async { return (/*severe:StaticTypeError*/new Future<int>.value(/*info:DynamicCast*/x)); } |
- |
- int y; |
- Future<int> z; |
- |
- void baz() async { |
- int a = /*info:DynamicCast*/await x; |
- int b = await y; |
- int c = await z; |
- String d = /*severe:StaticTypeError*/await z; |
- } |
- |
- Future<bool> get issue_264 async { |
- await 42; |
- if (new Random().nextBool()) { |
- return true; |
- } else { |
- return /*severe:StaticTypeError*/new Future<bool>.value(false); |
- } |
- } |
- ''' |
- }); |
- |
- testChecker('async*', { |
- '/main.dart': ''' |
- import 'dart:async'; |
- |
- dynamic x; |
- |
- bar1() async* { yield x; } |
- Stream bar2() async* { yield x; } |
- Stream<int> bar3() async* { yield (/*info:DynamicCast*/x); } |
- Stream<int> bar4() async* { yield (/*severe:StaticTypeError*/new Stream<int>()); } |
- |
- baz1() async* { yield* (/*info:DynamicCast*/x); } |
- Stream baz2() async* { yield* (/*info:DynamicCast*/x); } |
- Stream<int> baz3() async* { yield* (/*warning:DownCastComposite*/x); } |
- Stream<int> baz4() async* { yield* new Stream<int>(); } |
- Stream<int> baz5() async* { yield* (/*info:InferredTypeAllocation*/new Stream()); } |
- ''' |
- }); |
- |
- testChecker('sync*', { |
- '/main.dart': ''' |
- import 'dart:async'; |
- |
- dynamic x; |
- |
- bar1() sync* { yield x; } |
- Iterable bar2() sync* { yield x; } |
- Iterable<int> bar3() sync* { yield (/*info:DynamicCast*/x); } |
- Iterable<int> bar4() sync* { yield (/*severe:StaticTypeError*/new Iterable<int>()); } |
- |
- baz1() sync* { yield* (/*info:DynamicCast*/x); } |
- Iterable baz2() sync* { yield* (/*info:DynamicCast*/x); } |
- Iterable<int> baz3() sync* { yield* (/*warning:DownCastComposite*/x); } |
- Iterable<int> baz4() sync* { yield* new Iterable<int>(); } |
- Iterable<int> baz5() sync* { yield* (/*info:InferredTypeAllocation*/new Iterable()); } |
- ''' |
- }); |
- }); |
-} |