| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 // Test code | |
| 6 import 'dart:collection'; | |
| 7 import 'dart:mirrors'; | |
| 8 import 'package:test/test.dart'; | |
| 9 import 'package:dev_compiler/config.dart'; | |
| 10 import 'package:dev_compiler/runtime/dart_runtime.dart'; | |
| 11 | |
| 12 final bool intIsNonNullable = TypeOptions.NONNULLABLE_TYPES.contains('int'); | |
| 13 final bool doubleIsNonNullable = | |
| 14 TypeOptions.NONNULLABLE_TYPES.contains('double'); | |
| 15 | |
| 16 class A { | |
| 17 int x; | |
| 18 } | |
| 19 | |
| 20 class B extends A { | |
| 21 int y; | |
| 22 } | |
| 23 | |
| 24 class C extends B { | |
| 25 int z; | |
| 26 } | |
| 27 | |
| 28 class AA<T, U> { | |
| 29 T x; | |
| 30 U y; | |
| 31 } | |
| 32 | |
| 33 class BB<T, U> extends AA<U, T> { | |
| 34 T z; | |
| 35 } | |
| 36 | |
| 37 class CC extends BB<String, List> {} | |
| 38 | |
| 39 typedef Func2(x, y); | |
| 40 typedef B Foo(B b, String s); | |
| 41 | |
| 42 A bar1(C c, String s) => null; | |
| 43 bar2(B b, String s) => null; | |
| 44 B bar3(B b, Object o) => null; | |
| 45 B bar4(B b, o) => null; | |
| 46 C bar5(A a, Object o) => null; | |
| 47 B bar6(B b, String s, String o) => null; | |
| 48 B bar7(B b, String s, [Object o]) => null; | |
| 49 B bar8(B b, String s, {Object p}) => null; | |
| 50 | |
| 51 class Bar { | |
| 52 B call(B b, String s) => null; | |
| 53 } | |
| 54 | |
| 55 class Baz { | |
| 56 Foo call = (B b, String s) => null; | |
| 57 } | |
| 58 | |
| 59 class Checker<T> { | |
| 60 void isGround(bool expected) => expect(isGroundType(T), equals(expected)); | |
| 61 void isGroundList(bool expected) => | |
| 62 expect(isGroundType(new List<T>().runtimeType), equals(expected)); | |
| 63 void check(x, bool expected) => checkType(x, T, expected); | |
| 64 void checkList(x, bool expected) => | |
| 65 checkType(x, type((List<T> _) {}), expected); | |
| 66 } | |
| 67 | |
| 68 bool dartIs(expr, Type type) { | |
| 69 var exprMirror = reflectType(expr.runtimeType); | |
| 70 var typeMirror = reflectType(type); | |
| 71 return exprMirror.isSubtypeOf(typeMirror); | |
| 72 } | |
| 73 | |
| 74 void checkType(x, Type type, [bool expectedTrue = true]) { | |
| 75 var isGround = isGroundType(type); | |
| 76 var restrictedSubType = instanceOf(x, type); | |
| 77 var dartSubType = dartIs(x, type); | |
| 78 | |
| 79 // Matches expectation | |
| 80 expect(restrictedSubType, equals(expectedTrue)); | |
| 81 | |
| 82 // x is_R T => x is T | |
| 83 expect(!restrictedSubType || dartSubType, isTrue); | |
| 84 | |
| 85 // x is T && isGroundType(T) => x is_R T | |
| 86 expect(!(dartSubType && isGround) || restrictedSubType, isTrue); | |
| 87 } | |
| 88 | |
| 89 void checkArity(Function f, int min, int max) { | |
| 90 Arity arity = getArity(f); | |
| 91 expect(arity.min, equals(min)); | |
| 92 expect(arity.max, equals(max)); | |
| 93 } | |
| 94 | |
| 95 void main() { | |
| 96 test('int', () { | |
| 97 expect(isGroundType(int), isTrue); | |
| 98 expect(isGroundType(5.runtimeType), isTrue); | |
| 99 | |
| 100 checkType(5, int); | |
| 101 checkType(5, dynamic); | |
| 102 checkType(5, Object); | |
| 103 checkType(5, num); | |
| 104 | |
| 105 checkType(5, bool, false); | |
| 106 checkType(5, String, false); | |
| 107 | |
| 108 expect(cast(5, int), equals(5)); | |
| 109 if (intIsNonNullable) { | |
| 110 expect(() => cast(null, int), throws); | |
| 111 } else { | |
| 112 expect(cast(null, int), equals(null)); | |
| 113 } | |
| 114 }); | |
| 115 | |
| 116 test('dynamic', () { | |
| 117 expect(isGroundType(dynamic), isTrue); | |
| 118 checkType(new Object(), dynamic); | |
| 119 checkType(null, dynamic); | |
| 120 | |
| 121 expect(cast(null, dynamic), equals(null)); | |
| 122 }); | |
| 123 | |
| 124 test('Object', () { | |
| 125 expect(isGroundType(Object), isTrue); | |
| 126 checkType(new Object(), dynamic); | |
| 127 checkType(null, Object); | |
| 128 | |
| 129 expect(cast(null, Object), equals(null)); | |
| 130 }); | |
| 131 | |
| 132 test('String', () { | |
| 133 expect(isGroundType(String), isTrue); | |
| 134 expect(isGroundType("foo".runtimeType), isTrue); | |
| 135 checkType("foo", String); | |
| 136 checkType("foo", Object); | |
| 137 checkType("foo", dynamic); | |
| 138 | |
| 139 expect(cast(null, String), equals(null)); | |
| 140 }); | |
| 141 | |
| 142 test('Map', () { | |
| 143 final m1 = new Map<String, String>(); | |
| 144 final m2 = new Map<Object, Object>(); | |
| 145 final m3 = new Map(); | |
| 146 final m4 = new HashMap<dynamic, dynamic>(); | |
| 147 final m5 = new LinkedHashMap(); | |
| 148 | |
| 149 expect(isGroundType(Map), isTrue); | |
| 150 expect(isGroundType(m1.runtimeType), isFalse); | |
| 151 expect(isGroundType(type((Map<String, String> _) {})), isFalse); | |
| 152 expect(isGroundType(m2.runtimeType), isTrue); | |
| 153 expect(isGroundType(type((Map<Object, Object> _) {})), isTrue); | |
| 154 expect(isGroundType(m3.runtimeType), isTrue); | |
| 155 expect(isGroundType(type((Map _) {})), isTrue); | |
| 156 expect(isGroundType(m4.runtimeType), isTrue); | |
| 157 expect(isGroundType(type((HashMap<dynamic, dynamic> _) {})), isTrue); | |
| 158 expect(isGroundType(m5.runtimeType), isTrue); | |
| 159 expect(isGroundType(type((LinkedHashMap _) {})), isTrue); | |
| 160 expect(isGroundType(LinkedHashMap), isTrue); | |
| 161 | |
| 162 // Map<T1,T2> <: Map | |
| 163 checkType(m1, Map); | |
| 164 checkType(m1, Object); | |
| 165 | |
| 166 // Instance of self | |
| 167 checkType(m1, m1.runtimeType); | |
| 168 checkType(m1, type((Map<String, String> _) {})); | |
| 169 | |
| 170 // Object == dynamic == top as a type parameter | |
| 171 checkType(m2, m3.runtimeType); | |
| 172 checkType(m2, Map); | |
| 173 checkType(m3, m2.runtimeType); | |
| 174 checkType(m3, type((Map<Object, Object> _) {})); | |
| 175 | |
| 176 // Covariance on generics | |
| 177 checkType(m1, m2.runtimeType); | |
| 178 checkType(m1, type((Map<Object, Object> _) {})); | |
| 179 | |
| 180 // No contravariance on generics. | |
| 181 checkType(m2, m1.runtimeType, false); | |
| 182 checkType(m2, type((Map<String, String> _) {}), false); | |
| 183 | |
| 184 // null is! Map | |
| 185 checkType(null, Map, false); | |
| 186 | |
| 187 // Raw generic types | |
| 188 checkType(m5, Map); | |
| 189 checkType(m5, type((Map<Object, Object> _) {})); | |
| 190 checkType(m4, Map); | |
| 191 checkType(m4, type((Map<Object, Object> _) {})); | |
| 192 | |
| 193 // Mixin: the actual implementation class should implement MapMixin | |
| 194 checkType(m1, MapMixin); | |
| 195 checkType(m1, type((MapMixin<String, String> _) {})); | |
| 196 checkType(m1, type((MapMixin<Object, Object> _) {})); | |
| 197 checkType(m5, MapMixin); | |
| 198 checkType(m5, type((MapMixin<String, String> _) {}), false); | |
| 199 checkType(m5, type((MapMixin<Object, Object> _) {})); | |
| 200 }); | |
| 201 | |
| 202 test('generic and inheritance', () { | |
| 203 AA aaraw = new AA(); | |
| 204 final aarawtype = aaraw.runtimeType; | |
| 205 AA<dynamic, dynamic> aadynamic = new AA<dynamic, dynamic>(); | |
| 206 final aadynamictype = aadynamic.runtimeType; | |
| 207 AA<String, List> aa = new AA<String, List>(); | |
| 208 final aatype = aa.runtimeType; | |
| 209 BB<String, List> bb = new BB<String, List>(); | |
| 210 final bbtype = bb.runtimeType; | |
| 211 CC cc = new CC(); | |
| 212 final cctype = cc.runtimeType; | |
| 213 AA<String> aabad = new AA<String>(); | |
| 214 final aabadtype = aabad.runtimeType; | |
| 215 | |
| 216 expect(isGroundType(aatype), isFalse); | |
| 217 expect(isGroundType(type((AA<String, List> _) {})), isFalse); | |
| 218 expect(isGroundType(bbtype), isFalse); | |
| 219 expect(isGroundType(type((BB<String, List> _) {})), isFalse); | |
| 220 expect(isGroundType(cctype), isTrue); | |
| 221 expect(isGroundType(CC), isTrue); | |
| 222 checkType(cc, aatype, false); | |
| 223 checkType(cc, type((AA<String, List> _) {}), false); | |
| 224 checkType(cc, bbtype); | |
| 225 checkType(cc, type((BB<String, List> _) {})); | |
| 226 checkType(aa, cctype, false); | |
| 227 checkType(aa, CC, false); | |
| 228 checkType(aa, bbtype, false); | |
| 229 checkType(aa, type((BB<String, List> _) {}), false); | |
| 230 checkType(bb, cctype, false); | |
| 231 checkType(bb, CC, false); | |
| 232 checkType(aa, aabadtype); | |
| 233 checkType(aa, type((AA<String> _) {})); | |
| 234 checkType(aabad, aatype, false); | |
| 235 checkType(aabad, type((AA<String, List> _) {}), false); | |
| 236 checkType(aabad, aarawtype); | |
| 237 checkType(aabad, AA); | |
| 238 checkType(aaraw, aabadtype); | |
| 239 checkType(aaraw, type((AA<String> _) {})); | |
| 240 checkType(aaraw, aadynamictype); | |
| 241 checkType(aaraw, type((AA<dynamic, dynamic> _) {})); | |
| 242 checkType(aadynamic, aarawtype); | |
| 243 checkType(aadynamic, AA); | |
| 244 }); | |
| 245 | |
| 246 test('Functions', () { | |
| 247 // - return type: Dart is bivariant. We're covariant. | |
| 248 // - param types: Dart is bivariant. We're contravariant. | |
| 249 expect(isGroundType(Func2), isTrue); | |
| 250 expect(isGroundType(Foo), isFalse); | |
| 251 expect(isGroundType(type((B _(B _1, String _2)) {})), isFalse); | |
| 252 checkType(bar1, Foo, false); | |
| 253 checkType(bar1, type((B _(B _1, String _2)) {}), false); | |
| 254 checkType(bar2, Foo, false); | |
| 255 checkType(bar2, type((B _(B _1, String _2)) {}), false); | |
| 256 checkType(bar3, Foo); | |
| 257 checkType(bar3, type((B _(B _1, String _2)) {})); | |
| 258 checkType(bar4, Foo, false); | |
| 259 // TODO(vsm): Revisit. bar4 is (B, *) -> B. Perhaps it should be treated a
s top for a reified object. | |
| 260 checkType(bar4, type((B _(B _1, String _2)) {}), false); | |
| 261 checkType(bar5, Foo); | |
| 262 checkType(bar5, type((B _(B _1, String _2)) {})); | |
| 263 checkType(bar6, Foo, false); | |
| 264 checkType(bar6, type((B _(B _1, String _2)) {}), false); | |
| 265 checkType(bar7, Foo); | |
| 266 checkType(bar7, type((B _(B _1, String _2)) {})); | |
| 267 checkType(bar7, bar6.runtimeType); | |
| 268 checkType(bar8, Foo); | |
| 269 checkType(bar8, type((B _(B _1, String _2)) {})); | |
| 270 checkType(bar8, bar6.runtimeType, false); | |
| 271 checkType(bar7, bar8.runtimeType, false); | |
| 272 checkType(bar8, bar7.runtimeType, false); | |
| 273 }); | |
| 274 | |
| 275 test('void', () { | |
| 276 checkType((x) => x, type((void _(x)) {})); | |
| 277 }); | |
| 278 | |
| 279 test('null', () { | |
| 280 checkType(null, Object); | |
| 281 checkType(null, Null); | |
| 282 checkType(null, dynamic); | |
| 283 checkType(null, int, false); | |
| 284 checkType(null, String, false); | |
| 285 checkType(null, Map, false); | |
| 286 | |
| 287 expect(cast(null, Object), equals(null)); | |
| 288 expect(cast(null, String), equals(null)); | |
| 289 expect(cast(null, Map), equals(null)); | |
| 290 }); | |
| 291 | |
| 292 test('Function objects', () { | |
| 293 // Bar has a call method - it emulates the corresponding function. | |
| 294 var bar = new Bar(); | |
| 295 checkType(bar, Bar); | |
| 296 checkType(bar, Function); | |
| 297 checkType(bar, Foo); | |
| 298 checkType(bar, type((B _(B _1, String _2)) {})); | |
| 299 checkType(bar, type((B _(String _1, String _2)) {}), false); | |
| 300 | |
| 301 // Baz has a call getter that is a closure - this does not make it a | |
| 302 // function. | |
| 303 var baz = new Baz(); | |
| 304 checkType(baz, Function, false); | |
| 305 checkType(baz, Foo, false); | |
| 306 }); | |
| 307 | |
| 308 test('arity', () { | |
| 309 checkArity(bar1, 2, 2); | |
| 310 checkArity(bar4, 2, 2); | |
| 311 checkArity(bar6, 3, 3); | |
| 312 checkArity(bar7, 2, 3); | |
| 313 checkArity(bar8, 2, 2); | |
| 314 checkArity(() {}, 0, 0); | |
| 315 checkArity((a, [b]) {}, 1, 2); | |
| 316 }); | |
| 317 | |
| 318 test('type variable', () { | |
| 319 var stringChecker = new Checker<String>(); | |
| 320 stringChecker.isGround(true); | |
| 321 stringChecker.isGroundList(false); | |
| 322 | |
| 323 stringChecker.check(5, false); | |
| 324 stringChecker.check("hello", true); | |
| 325 stringChecker.check(null, false); | |
| 326 | |
| 327 var objectChecker = new Checker<Object>(); | |
| 328 objectChecker.isGround(true); | |
| 329 objectChecker.isGroundList(true); | |
| 330 | |
| 331 objectChecker.check(5, true); | |
| 332 objectChecker.check("hello", true); | |
| 333 objectChecker.check(null, true); | |
| 334 }); | |
| 335 } | |
| OLD | NEW |