| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2016, 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 import 'package:analyzer/dart/element/type.dart'; |
| 6 import 'package:analyzer/src/dart/element/element.dart'; |
| 7 import 'package:analyzer/src/summary/format.dart'; |
| 8 import 'package:analyzer/src/summary/idl.dart'; |
| 9 import 'package:analyzer/src/summary/link.dart'; |
| 10 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| 11 import 'package:unittest/unittest.dart'; |
| 12 |
| 13 import 'summarize_ast_test.dart'; |
| 14 |
| 15 main() { |
| 16 groupSep = ' | '; |
| 17 defineReflectiveTests(LinkerUnitTest); |
| 18 } |
| 19 |
| 20 @reflectiveTest |
| 21 class LinkerUnitTest extends SummaryLinkerTest { |
| 22 Linker linker; |
| 23 |
| 24 LinkerInputs linkerInputs; |
| 25 LibraryElementInBuildUnit _testLibrary; |
| 26 @override |
| 27 bool get allowMissingFiles => false; |
| 28 |
| 29 Matcher get isUndefined => new isInstanceOf<UndefinedElementForLink>(); |
| 30 |
| 31 LibraryElementInBuildUnit get testLibrary => _testLibrary ??= |
| 32 linker.getLibrary(linkerInputs.testDartUri) as LibraryElementInBuildUnit; |
| 33 |
| 34 void createLinker(String text, {String path: '/test.dart'}) { |
| 35 linkerInputs = createLinkerInputs(text, path: path); |
| 36 Map<String, LinkedLibraryBuilder> linkedLibraries = setupForLink( |
| 37 linkerInputs.linkedLibraries, |
| 38 linkerInputs.getUnit, |
| 39 linkerInputs.getDeclaredVariable); |
| 40 linker = new Linker(linkedLibraries, linkerInputs.getDependency, |
| 41 linkerInputs.getUnit, true); |
| 42 } |
| 43 |
| 44 LibraryElementForLink getLibrary(String uri) { |
| 45 return linker.getLibrary(Uri.parse(uri)); |
| 46 } |
| 47 |
| 48 void test_apiSignature_apiChanges() { |
| 49 var bundle0 = |
| 50 createPackageBundle('f(int i) { print(i); }', path: '/test.dart'); |
| 51 var bundle1 = |
| 52 createPackageBundle('f(String s) { print(s); }', path: '/test.dart'); |
| 53 expect(bundle0.apiSignature, isNotEmpty); |
| 54 expect(bundle1.apiSignature, isNotEmpty); |
| 55 expect(bundle0.apiSignature, isNot(bundle1.apiSignature)); |
| 56 } |
| 57 |
| 58 void test_apiSignature_localChanges() { |
| 59 var bundle0 = createPackageBundle('f() { print(0); }', path: '/test.dart'); |
| 60 var bundle1 = createPackageBundle('f() { print(1); }', path: '/test.dart'); |
| 61 expect(bundle0.apiSignature, isNotEmpty); |
| 62 expect(bundle1.apiSignature, isNotEmpty); |
| 63 expect(bundle0.apiSignature, bundle1.apiSignature); |
| 64 } |
| 65 |
| 66 void test_apiSignature_orderChange() { |
| 67 // A change to the order in which files are processed should not affect the |
| 68 // API signature. |
| 69 addNamedSource('/a.dart', 'class A {}'); |
| 70 var bundle0 = createPackageBundle('class B {}', path: '/b.dart'); |
| 71 addNamedSource('/b.dart', 'class B {}'); |
| 72 var bundle1 = createPackageBundle('class A {}', path: '/a.dart'); |
| 73 expect(bundle0.apiSignature, isNotEmpty); |
| 74 expect(bundle1.apiSignature, isNotEmpty); |
| 75 expect(bundle0.apiSignature, bundle1.apiSignature); |
| 76 } |
| 77 |
| 78 void test_apiSignature_unlinkedOnly() { |
| 79 // The API signature of a package bundle should only contain unlinked |
| 80 // information. In this test, the linked information for bundle2 and |
| 81 // bundle3 refer to class C as existing in different files. But the |
| 82 // unlinked information for bundle2 and bundle3 should be the same, so their |
| 83 // API signatures should be the same. |
| 84 addNamedSource('/a.dart', 'class C {}'); |
| 85 var bundle0 = createPackageBundle('', path: '/b.dart'); |
| 86 addNamedSource('/a.dart', ''); |
| 87 var bundle1 = createPackageBundle('class C {}', path: '/b.dart'); |
| 88 var text = ''' |
| 89 import 'a.dart'; |
| 90 import 'b.dart'; |
| 91 class D extends C {} |
| 92 '''; |
| 93 addBundle('/bundle0.ds', bundle0); |
| 94 var bundle2 = createPackageBundle(text, path: '/c.dart'); |
| 95 addBundle('/bundle1.ds', bundle1); |
| 96 var bundle3 = createPackageBundle(text, path: '/c.dart'); |
| 97 expect(bundle2.apiSignature, isNotEmpty); |
| 98 expect(bundle3.apiSignature, isNotEmpty); |
| 99 expect(bundle2.apiSignature, bundle3.apiSignature); |
| 100 } |
| 101 |
| 102 void test_baseClass_genericWithAccessor() { |
| 103 createLinker(''' |
| 104 class B<T> { |
| 105 int get i => null; |
| 106 } |
| 107 class C<U> extends B<U> { |
| 108 var j; |
| 109 } |
| 110 '''); |
| 111 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 112 library.libraryCycleForLink.ensureLinked(); |
| 113 // No assertions--just make sure it doesn't crash. |
| 114 } |
| 115 |
| 116 void test_baseClass_genericWithField() { |
| 117 createLinker(''' |
| 118 class B<T> { |
| 119 int i = 0; |
| 120 } |
| 121 class C<T> extends B<T> { |
| 122 void f() {} |
| 123 } |
| 124 '''); |
| 125 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 126 library.libraryCycleForLink.ensureLinked(); |
| 127 // No assertions--just make sure it doesn't crash. |
| 128 } |
| 129 |
| 130 void test_baseClass_genericWithFunctionTypedParameter() { |
| 131 createLinker(''' |
| 132 class B<T> { |
| 133 void f(void g(T t)); |
| 134 } |
| 135 class C<U> extends B<U> { |
| 136 void f(g) {} |
| 137 } |
| 138 '''); |
| 139 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 140 library.libraryCycleForLink.ensureLinked(); |
| 141 // No assertions--just make sure it doesn't crash. |
| 142 } |
| 143 |
| 144 void test_baseClass_genericWithGenericMethod() { |
| 145 createLinker(''' |
| 146 class B<T> { |
| 147 List<U> f<U>(U u) => null; |
| 148 } |
| 149 class C<V> extends B<V> { |
| 150 var j; |
| 151 } |
| 152 '''); |
| 153 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 154 library.libraryCycleForLink.ensureLinked(); |
| 155 // No assertions--just make sure it doesn't crash. |
| 156 } |
| 157 |
| 158 void test_baseClass_genericWithGenericMethod_returnsGenericFuture() { |
| 159 createLinker(''' |
| 160 import 'dart:async'; |
| 161 class B<T> { |
| 162 Future<T> f() => null; |
| 163 } |
| 164 class C<T> extends B<T> { |
| 165 Future<T> f() => null; |
| 166 } |
| 167 '''); |
| 168 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 169 library.libraryCycleForLink.ensureLinked(); |
| 170 // No assertions--just make sure it doesn't crash. |
| 171 } |
| 172 |
| 173 void test_baseClass_genericWithStaticFinal() { |
| 174 createLinker(''' |
| 175 class B<T> { |
| 176 static final int i = 0; |
| 177 } |
| 178 class C<T> extends B<T> { |
| 179 void f() {} |
| 180 } |
| 181 '''); |
| 182 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 183 library.libraryCycleForLink.ensureLinked(); |
| 184 } |
| 185 |
| 186 void test_baseClass_withPrivateField() { |
| 187 createLinker(''' |
| 188 class B { |
| 189 var _b; |
| 190 } |
| 191 class C extends B { |
| 192 var c; |
| 193 } |
| 194 '''); |
| 195 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 196 library.libraryCycleForLink.ensureLinked(); |
| 197 // No assertions--just make sure it doesn't crash. |
| 198 } |
| 199 |
| 200 void test_bundle_refers_to_bundle() { |
| 201 var bundle1 = createPackageBundle( |
| 202 ''' |
| 203 var x = 0; |
| 204 ''', |
| 205 path: '/a.dart'); |
| 206 addBundle('/a.ds', bundle1); |
| 207 var bundle2 = createPackageBundle( |
| 208 ''' |
| 209 import "a.dart"; |
| 210 var y = x; |
| 211 ''', |
| 212 path: '/b.dart'); |
| 213 expect(bundle2.dependencies, hasLength(1)); |
| 214 expect(bundle2.dependencies[0].summaryPath, '/a.ds'); |
| 215 expect(bundle2.dependencies[0].apiSignature, bundle1.apiSignature); |
| 216 addBundle('/a.ds', bundle1); |
| 217 addBundle('/b.ds', bundle2); |
| 218 createLinker(''' |
| 219 import "b.dart"; |
| 220 var z = y; |
| 221 '''); |
| 222 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 223 expect(_getVariable(library.getContainedName('z')).inferredType.toString(), |
| 224 'int'); |
| 225 } |
| 226 |
| 227 void test_constCycle_viaLength() { |
| 228 createLinker(''' |
| 229 class C { |
| 230 final y; |
| 231 const C() : y = x.length; |
| 232 } |
| 233 const x = [const C()]; |
| 234 '''); |
| 235 testLibrary.libraryCycleForLink.ensureLinked(); |
| 236 ClassElementForLink classC = testLibrary.getContainedName('C'); |
| 237 expect(classC.unnamedConstructor.isCycleFree, false); |
| 238 } |
| 239 |
| 240 void test_covariance() { |
| 241 // Note: due to dartbug.com/27393, the keyword "checked" is identified by |
| 242 // its presence in a library called "meta". If that bug is fixed, this test |
| 243 // may need to be changed. |
| 244 createLinker(''' |
| 245 library meta; |
| 246 const checked = null; |
| 247 class A<T> { |
| 248 void f(@checked T t) {} |
| 249 } |
| 250 class B<T> extends A<T> { |
| 251 void f(T t) {} |
| 252 } |
| 253 '''); |
| 254 testLibrary.libraryCycleForLink.ensureLinked(); |
| 255 ClassElementForLink classA = testLibrary.getContainedName('A'); |
| 256 MethodElementForLink methodAF = classA.getContainedName('f'); |
| 257 ParameterElementForLink parameterAFT = methodAF.parameters[0]; |
| 258 expect(parameterAFT.isCovariant, isTrue); |
| 259 expect(parameterAFT.inheritsCovariant, isFalse); |
| 260 ClassElementForLink classB = testLibrary.getContainedName('B'); |
| 261 MethodElementForLink methodBF = classB.getContainedName('f'); |
| 262 ParameterElementForLink parameterBFT = methodBF.parameters[0]; |
| 263 expect(parameterAFT.isCovariant, isTrue); |
| 264 expect(parameterBFT.inheritsCovariant, isTrue); |
| 265 } |
| 266 |
| 267 void test_createPackageBundle_withPackageUri() { |
| 268 PackageBundle bundle = createPackageBundle( |
| 269 ''' |
| 270 class B { |
| 271 void f(int i) {} |
| 272 } |
| 273 class C extends B { |
| 274 f(i) {} // Inferred param type: int |
| 275 } |
| 276 ''', |
| 277 uri: 'package:foo/bar.dart'); |
| 278 UnlinkedExecutable cf = bundle.unlinkedUnits[0].classes[1].executables[0]; |
| 279 UnlinkedParam cfi = cf.parameters[0]; |
| 280 expect(cfi.inferredTypeSlot, isNot(0)); |
| 281 EntityRef typeRef = _lookupInferredType( |
| 282 bundle.linkedLibraries[0].units[0], cfi.inferredTypeSlot); |
| 283 expect(typeRef, isNotNull); |
| 284 expect(bundle.unlinkedUnits[0].references[typeRef.reference].name, 'int'); |
| 285 } |
| 286 |
| 287 void test_getContainedName_nonStaticField() { |
| 288 createLinker('class C { var f; }'); |
| 289 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 290 ClassElementForLink_Class c = library.getContainedName('C'); |
| 291 expect(c.getContainedName('f'), isNot(isUndefined)); |
| 292 } |
| 293 |
| 294 void test_getContainedName_nonStaticGetter() { |
| 295 createLinker('class C { get g => null; }'); |
| 296 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 297 ClassElementForLink_Class c = library.getContainedName('C'); |
| 298 expect(c.getContainedName('g'), isNot(isUndefined)); |
| 299 } |
| 300 |
| 301 void test_getContainedName_nonStaticMethod() { |
| 302 createLinker('class C { m() {} }'); |
| 303 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 304 ClassElementForLink_Class c = library.getContainedName('C'); |
| 305 expect(c.getContainedName('m'), isNot(isUndefined)); |
| 306 } |
| 307 |
| 308 void test_getContainedName_nonStaticSetter() { |
| 309 createLinker('class C { void set s(value) {} }'); |
| 310 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 311 ClassElementForLink_Class c = library.getContainedName('C'); |
| 312 expect(c.getContainedName('s='), isNot(isUndefined)); |
| 313 } |
| 314 |
| 315 void test_inferredType_closure_fromBundle() { |
| 316 var bundle = createPackageBundle( |
| 317 ''' |
| 318 var x = () {}; |
| 319 ''', |
| 320 path: '/a.dart'); |
| 321 addBundle('/a.ds', bundle); |
| 322 createLinker(''' |
| 323 import 'a.dart'; |
| 324 var y = x; |
| 325 '''); |
| 326 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 327 expect(_getVariable(library.getContainedName('y')).inferredType.toString(), |
| 328 '() → dynamic'); |
| 329 } |
| 330 |
| 331 void test_inferredType_closure_fromBundle_identifierSequence() { |
| 332 var bundle = createPackageBundle( |
| 333 ''' |
| 334 class C { |
| 335 static final x = (D d) => d.e; |
| 336 } |
| 337 class D { |
| 338 E e; |
| 339 } |
| 340 class E {} |
| 341 ''', |
| 342 path: '/a.dart'); |
| 343 addBundle('/a.ds', bundle); |
| 344 createLinker(''' |
| 345 import 'a.dart'; |
| 346 var y = C.x; |
| 347 '''); |
| 348 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 349 expect(_getVariable(library.getContainedName('y')).inferredType.toString(), |
| 350 '(D) → E'); |
| 351 } |
| 352 |
| 353 void test_inferredType_instanceField_dynamic() { |
| 354 createLinker(''' |
| 355 var x; |
| 356 class C { |
| 357 var f = x; // Inferred type: dynamic |
| 358 } |
| 359 '''); |
| 360 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 361 library.libraryCycleForLink.ensureLinked(); |
| 362 ClassElementForLink_Class cls = library.getContainedName('C'); |
| 363 expect(cls.fields, hasLength(1)); |
| 364 var field = cls.fields[0]; |
| 365 expect(field.type.toString(), 'dynamic'); |
| 366 } |
| 367 |
| 368 void test_inferredType_methodParamType_dynamic() { |
| 369 createLinker(''' |
| 370 clas B { |
| 371 void f(dynamic x) {} |
| 372 } |
| 373 class C extends B { |
| 374 f(x) {} // Inferred param type: dynamic |
| 375 } |
| 376 '''); |
| 377 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 378 library.libraryCycleForLink.ensureLinked(); |
| 379 ClassElementForLink_Class cls = library.getContainedName('C'); |
| 380 expect(cls.methods, hasLength(1)); |
| 381 var method = cls.methods[0]; |
| 382 expect(method.parameters, hasLength(1)); |
| 383 expect(method.parameters[0].type.toString(), 'dynamic'); |
| 384 } |
| 385 |
| 386 void test_inferredType_methodReturnType_dynamic() { |
| 387 createLinker(''' |
| 388 class B { |
| 389 dynamic f() {} |
| 390 } |
| 391 class C extends B { |
| 392 f() {} // Inferred return type: dynamic |
| 393 } |
| 394 '''); |
| 395 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 396 library.libraryCycleForLink.ensureLinked(); |
| 397 ClassElementForLink_Class cls = library.getContainedName('C'); |
| 398 expect(cls.methods, hasLength(1)); |
| 399 expect(cls.methods[0].returnType.toString(), 'dynamic'); |
| 400 } |
| 401 |
| 402 void test_inferredType_methodReturnType_void() { |
| 403 createLinker(''' |
| 404 class B { |
| 405 void f() {} |
| 406 } |
| 407 class C extends B { |
| 408 f() {} |
| 409 } |
| 410 '''); |
| 411 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 412 library.libraryCycleForLink.ensureLinked(); |
| 413 ClassElementForLink_Class cls = library.getContainedName('C'); |
| 414 expect(cls.methods, hasLength(1)); |
| 415 expect(cls.methods[0].returnType.toString(), 'void'); |
| 416 } |
| 417 |
| 418 void test_inferredType_staticField_dynamic() { |
| 419 createLinker(''' |
| 420 dynamic x = null; |
| 421 class C { |
| 422 static var y = x; |
| 423 } |
| 424 '''); |
| 425 expect( |
| 426 _getVariable(linker |
| 427 .getLibrary(linkerInputs.testDartUri) |
| 428 .getContainedName('C') |
| 429 .getContainedName('y')) |
| 430 .inferredType |
| 431 .toString(), |
| 432 'dynamic'); |
| 433 } |
| 434 |
| 435 void test_inferredType_topLevelVariable_dynamic() { |
| 436 createLinker(''' |
| 437 dynamic x = null; |
| 438 var y = x; |
| 439 '''); |
| 440 expect( |
| 441 _getVariable(linker |
| 442 .getLibrary(linkerInputs.testDartUri) |
| 443 .getContainedName('y')) |
| 444 .inferredType |
| 445 .toString(), |
| 446 'dynamic'); |
| 447 } |
| 448 |
| 449 void test_inferredTypeFromOutsideBuildUnit_dynamic() { |
| 450 var bundle = createPackageBundle( |
| 451 ''' |
| 452 var x; |
| 453 var y = x; // Inferred type: dynamic |
| 454 ''', |
| 455 path: '/a.dart'); |
| 456 addBundle('/a.ds', bundle); |
| 457 createLinker(''' |
| 458 import 'a.dart'; |
| 459 var z = y; // Inferred type: dynamic |
| 460 '''); |
| 461 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 462 expect(_getVariable(library.getContainedName('z')).inferredType.toString(), |
| 463 'dynamic'); |
| 464 } |
| 465 |
| 466 void test_inferredTypeFromOutsideBuildUnit_instanceField() { |
| 467 var bundle = createPackageBundle( |
| 468 ''' |
| 469 class C { |
| 470 var f = 0; // Inferred type: int |
| 471 } |
| 472 ''', |
| 473 path: '/a.dart'); |
| 474 addBundle('/a.ds', bundle); |
| 475 createLinker(''' |
| 476 import 'a.dart'; |
| 477 var x = new C().f; // Inferred type: int |
| 478 '''); |
| 479 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 480 expect(_getVariable(library.getContainedName('x')).inferredType.toString(), |
| 481 'int'); |
| 482 } |
| 483 |
| 484 void test_inferredTypeFromOutsideBuildUnit_instanceField_toInstanceField() { |
| 485 var bundle = createPackageBundle( |
| 486 ''' |
| 487 class C { |
| 488 var f = 0; // Inferred type: int |
| 489 } |
| 490 ''', |
| 491 path: '/a.dart'); |
| 492 addBundle('/a.ds', bundle); |
| 493 createLinker(''' |
| 494 import 'a.dart'; |
| 495 class D { |
| 496 var g = new C().f; // Inferred type: int |
| 497 } |
| 498 '''); |
| 499 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 500 ClassElementForLink_Class classD = library.getContainedName('D'); |
| 501 expect(classD.fields[0].inferredType.toString(), 'int'); |
| 502 } |
| 503 |
| 504 void test_inferredTypeFromOutsideBuildUnit_methodParamType_viaGeneric() { |
| 505 var bundle = createPackageBundle( |
| 506 ''' |
| 507 class B { |
| 508 T f<T>(T t) => t; |
| 509 } |
| 510 class C extends B { |
| 511 f<T>(t) => t; // Inferred param type: T |
| 512 } |
| 513 ''', |
| 514 path: '/a.dart'); |
| 515 addBundle('/a.ds', bundle); |
| 516 createLinker(''' |
| 517 import 'a.dart'; |
| 518 var x = new C().f(0); // Inferred type: int |
| 519 '''); |
| 520 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 521 expect(_getVariable(library.getContainedName('x')).inferredType.toString(), |
| 522 'int'); |
| 523 } |
| 524 |
| 525 void test_inferredTypeFromOutsideBuildUnit_methodParamType_viaInheritance() { |
| 526 var bundle = createPackageBundle( |
| 527 ''' |
| 528 class B { |
| 529 void f(int i) {} |
| 530 } |
| 531 class C extends B { |
| 532 f(i) {} // Inferred param type: int |
| 533 } |
| 534 ''', |
| 535 path: '/a.dart'); |
| 536 addBundle('/a.ds', bundle); |
| 537 createLinker(''' |
| 538 import 'a.dart'; |
| 539 class D extends C { |
| 540 f(i) {} // Inferred param type: int |
| 541 } |
| 542 '''); |
| 543 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 544 library.libraryCycleForLink.ensureLinked(); |
| 545 ClassElementForLink_Class cls = library.getContainedName('D'); |
| 546 expect(cls.methods, hasLength(1)); |
| 547 var method = cls.methods[0]; |
| 548 expect(method.parameters, hasLength(1)); |
| 549 expect(method.parameters[0].type.toString(), 'int'); |
| 550 } |
| 551 |
| 552 void test_inferredTypeFromOutsideBuildUnit_methodReturnType_viaCall() { |
| 553 var bundle = createPackageBundle( |
| 554 ''' |
| 555 class B { |
| 556 int f() => 0; |
| 557 } |
| 558 class C extends B { |
| 559 f() => 1; // Inferred return type: int |
| 560 } |
| 561 ''', |
| 562 path: '/a.dart'); |
| 563 addBundle('/a.ds', bundle); |
| 564 createLinker(''' |
| 565 import 'a.dart'; |
| 566 var x = new C().f(); // Inferred type: int |
| 567 '''); |
| 568 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 569 expect(_getVariable(library.getContainedName('x')).inferredType.toString(), |
| 570 'int'); |
| 571 } |
| 572 |
| 573 void test_inferredTypeFromOutsideBuildUnit_methodReturnType_viaInheritance() { |
| 574 var bundle = createPackageBundle( |
| 575 ''' |
| 576 class B { |
| 577 int f() => 0; |
| 578 } |
| 579 class C extends B { |
| 580 f() => 1; // Inferred return type: int |
| 581 } |
| 582 ''', |
| 583 path: '/a.dart'); |
| 584 addBundle('/a.ds', bundle); |
| 585 createLinker(''' |
| 586 import 'a.dart'; |
| 587 class D extends C { |
| 588 f() => 2; //Inferred return type: int |
| 589 } |
| 590 '''); |
| 591 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 592 library.libraryCycleForLink.ensureLinked(); |
| 593 ClassElementForLink_Class cls = library.getContainedName('D'); |
| 594 expect(cls.methods, hasLength(1)); |
| 595 expect(cls.methods[0].returnType.toString(), 'int'); |
| 596 } |
| 597 |
| 598 void test_inferredTypeFromOutsideBuildUnit_staticField() { |
| 599 var bundle = |
| 600 createPackageBundle('class C { static var f = 0; }', path: '/a.dart'); |
| 601 addBundle('/a.ds', bundle); |
| 602 createLinker('import "a.dart"; var x = C.f;', path: '/b.dart'); |
| 603 expect( |
| 604 _getVariable(linker |
| 605 .getLibrary(linkerInputs.testDartUri) |
| 606 .getContainedName('x')) |
| 607 .inferredType |
| 608 .toString(), |
| 609 'int'); |
| 610 } |
| 611 |
| 612 void test_inferredTypeFromOutsideBuildUnit_topLevelVariable() { |
| 613 var bundle = createPackageBundle('var a = 0;', path: '/a.dart'); |
| 614 addBundle('/a.ds', bundle); |
| 615 createLinker('import "a.dart"; var b = a;', path: '/b.dart'); |
| 616 expect( |
| 617 _getVariable(linker |
| 618 .getLibrary(linkerInputs.testDartUri) |
| 619 .getContainedName('b')) |
| 620 .inferredType |
| 621 .toString(), |
| 622 'int'); |
| 623 } |
| 624 |
| 625 void test_instantiate_param_of_param_to_bounds() { |
| 626 createLinker(''' |
| 627 class C<T> {} |
| 628 class D<T extends num> {} |
| 629 final x = new C<D>(); |
| 630 '''); |
| 631 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 632 library.libraryCycleForLink.ensureLinked(); |
| 633 PropertyAccessorElementForLink_Variable x = library.getContainedName('x'); |
| 634 ParameterizedType type1 = x.returnType; |
| 635 expect(type1.element.name, 'C'); |
| 636 expect(type1.typeArguments, hasLength(1)); |
| 637 ParameterizedType type2 = type1.typeArguments[0]; |
| 638 expect(type2.element.name, 'D'); |
| 639 expect(type2.typeArguments, hasLength(1)); |
| 640 DartType type3 = type2.typeArguments[0]; |
| 641 expect(type3.toString(), 'num'); |
| 642 } |
| 643 |
| 644 void test_instantiate_param_to_bounds_class() { |
| 645 createLinker(''' |
| 646 class C<T extends num> {} |
| 647 final x = new C(); |
| 648 '''); |
| 649 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 650 library.libraryCycleForLink.ensureLinked(); |
| 651 PropertyAccessorElementForLink_Variable x = library.getContainedName('x'); |
| 652 ParameterizedType type1 = x.returnType; |
| 653 expect(type1.element.name, 'C'); |
| 654 expect(type1.typeArguments, hasLength(1)); |
| 655 DartType type2 = type1.typeArguments[0]; |
| 656 expect(type2.toString(), 'num'); |
| 657 } |
| 658 |
| 659 void test_instantiate_param_to_bounds_typedef() { |
| 660 createLinker(''' |
| 661 typedef T F<T extends num>(); |
| 662 final x = new List<F>(); |
| 663 '''); |
| 664 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 665 library.libraryCycleForLink.ensureLinked(); |
| 666 PropertyAccessorElementForLink_Variable x = library.getContainedName('x'); |
| 667 ParameterizedType type1 = x.returnType; |
| 668 expect(type1.element.name, 'List'); |
| 669 expect(type1.typeArguments, hasLength(1)); |
| 670 FunctionType type2 = type1.typeArguments[0]; |
| 671 expect(type2.element.name, 'F'); |
| 672 expect(type2.returnType.toString(), 'num'); |
| 673 } |
| 674 |
| 675 void test_leastUpperBound_functionAndClass() { |
| 676 createLinker(''' |
| 677 class C {} |
| 678 void f() {} |
| 679 var x = { |
| 680 'C': C, |
| 681 'f': f |
| 682 }; |
| 683 '''); |
| 684 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 685 library.libraryCycleForLink.ensureLinked(); |
| 686 // No assertions--just make sure it doesn't crash. |
| 687 } |
| 688 |
| 689 void test_libraryCycle_ignoresDependenciesOutsideBuildUnit() { |
| 690 createLinker('import "dart:async";'); |
| 691 LibraryCycleForLink libraryCycle = testLibrary.libraryCycleForLink; |
| 692 expect(libraryCycle.dependencies, isEmpty); |
| 693 expect(libraryCycle.libraries, [testLibrary]); |
| 694 } |
| 695 |
| 696 void test_libraryCycle_linkEnsuresDependenciesLinked() { |
| 697 addNamedSource('/a.dart', 'import "b.dart";'); |
| 698 addNamedSource('/b.dart', ''); |
| 699 addNamedSource('/c.dart', ''); |
| 700 createLinker('import "a.dart"; import "c.dart";'); |
| 701 LibraryElementForLink libA = getLibrary('file:///a.dart'); |
| 702 LibraryElementForLink libB = getLibrary('file:///b.dart'); |
| 703 LibraryElementForLink libC = getLibrary('file:///c.dart'); |
| 704 expect(libA.libraryCycleForLink.node.isEvaluated, isFalse); |
| 705 expect(libB.libraryCycleForLink.node.isEvaluated, isFalse); |
| 706 expect(libC.libraryCycleForLink.node.isEvaluated, isFalse); |
| 707 libA.libraryCycleForLink.ensureLinked(); |
| 708 expect(libA.libraryCycleForLink.node.isEvaluated, isTrue); |
| 709 expect(libB.libraryCycleForLink.node.isEvaluated, isTrue); |
| 710 expect(libC.libraryCycleForLink.node.isEvaluated, isFalse); |
| 711 } |
| 712 |
| 713 void test_libraryCycle_nontrivial() { |
| 714 addNamedSource('/a.dart', 'import "b.dart";'); |
| 715 addNamedSource('/b.dart', 'import "a.dart";'); |
| 716 createLinker(''); |
| 717 LibraryElementForLink libA = getLibrary('file:///a.dart'); |
| 718 LibraryElementForLink libB = getLibrary('file:///b.dart'); |
| 719 LibraryCycleForLink libraryCycle = libA.libraryCycleForLink; |
| 720 expect(libB.libraryCycleForLink, same(libraryCycle)); |
| 721 expect(libraryCycle.dependencies, isEmpty); |
| 722 expect(libraryCycle.libraries, unorderedEquals([libA, libB])); |
| 723 } |
| 724 |
| 725 void test_libraryCycle_nontrivial_dependencies() { |
| 726 addNamedSource('/a.dart', ''); |
| 727 addNamedSource('/b.dart', ''); |
| 728 addNamedSource('/c.dart', 'import "a.dart"; import "d.dart";'); |
| 729 addNamedSource('/d.dart', 'import "b.dart"; import "c.dart";'); |
| 730 createLinker(''); |
| 731 LibraryElementForLink libA = getLibrary('file:///a.dart'); |
| 732 LibraryElementForLink libB = getLibrary('file:///b.dart'); |
| 733 LibraryElementForLink libC = getLibrary('file:///c.dart'); |
| 734 LibraryElementForLink libD = getLibrary('file:///d.dart'); |
| 735 LibraryCycleForLink libraryCycle = libC.libraryCycleForLink; |
| 736 expect(libD.libraryCycleForLink, same(libraryCycle)); |
| 737 expect(libraryCycle.dependencies, |
| 738 unorderedEquals([libA.libraryCycleForLink, libB.libraryCycleForLink])); |
| 739 expect(libraryCycle.libraries, unorderedEquals([libC, libD])); |
| 740 } |
| 741 |
| 742 void test_libraryCycle_nontrivial_via_export() { |
| 743 addNamedSource('/a.dart', 'export "b.dart";'); |
| 744 addNamedSource('/b.dart', 'export "a.dart";'); |
| 745 createLinker(''); |
| 746 LibraryElementForLink libA = getLibrary('file:///a.dart'); |
| 747 LibraryElementForLink libB = getLibrary('file:///b.dart'); |
| 748 LibraryCycleForLink libraryCycle = libA.libraryCycleForLink; |
| 749 expect(libB.libraryCycleForLink, same(libraryCycle)); |
| 750 expect(libraryCycle.dependencies, isEmpty); |
| 751 expect(libraryCycle.libraries, unorderedEquals([libA, libB])); |
| 752 } |
| 753 |
| 754 void test_libraryCycle_trivial() { |
| 755 createLinker(''); |
| 756 LibraryCycleForLink libraryCycle = testLibrary.libraryCycleForLink; |
| 757 expect(libraryCycle.dependencies, isEmpty); |
| 758 expect(libraryCycle.libraries, [testLibrary]); |
| 759 } |
| 760 |
| 761 void test_libraryCycle_trivial_dependencies() { |
| 762 addNamedSource('/a.dart', ''); |
| 763 addNamedSource('/b.dart', ''); |
| 764 createLinker('import "a.dart"; import "b.dart";'); |
| 765 LibraryElementForLink libA = getLibrary('file:///a.dart'); |
| 766 LibraryElementForLink libB = getLibrary('file:///b.dart'); |
| 767 LibraryCycleForLink libraryCycle = testLibrary.libraryCycleForLink; |
| 768 expect(libraryCycle.dependencies, |
| 769 unorderedEquals([libA.libraryCycleForLink, libB.libraryCycleForLink])); |
| 770 expect(libraryCycle.libraries, [testLibrary]); |
| 771 } |
| 772 |
| 773 void test_malformed_function_reference() { |
| 774 // Create a corrupted package bundle in which the inferred type of `x` |
| 775 // refers to a non-existent local function. |
| 776 var bundle = createPackageBundle('var x = () {}', path: '/a.dart'); |
| 777 expect(bundle.linkedLibraries, hasLength(1)); |
| 778 expect(bundle.linkedLibraries[0].units, hasLength(1)); |
| 779 for (LinkedReferenceBuilder ref |
| 780 in bundle.linkedLibraries[0].units[0].references) { |
| 781 if (ref.kind == ReferenceKind.function) { |
| 782 ref.localIndex = 1234; |
| 783 } |
| 784 } |
| 785 addBundle('/a.ds', bundle); |
| 786 createLinker(''' |
| 787 import 'a.dart'; |
| 788 var y = x; |
| 789 '''); |
| 790 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 791 expect(_getVariable(library.getContainedName('y')).inferredType.toString(), |
| 792 'dynamic'); |
| 793 } |
| 794 |
| 795 @failingTest |
| 796 void test_methodCall_withTypeArguments_topLevelVariable() { |
| 797 // The following code is incorrect but it shouldn't crash analyzer. |
| 798 // TODO(paulberry): fix this. |
| 799 createLinker('var f = f/*<int>*/();'); |
| 800 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 801 library.libraryCycleForLink.ensureLinked(); |
| 802 } |
| 803 |
| 804 void test_multiplyInheritedExecutable_differentSignatures() { |
| 805 createLinker(''' |
| 806 class B { |
| 807 void f() {} |
| 808 } |
| 809 abstract class I { |
| 810 f(); |
| 811 } |
| 812 class C extends B with I {} |
| 813 class D extends C { |
| 814 void f() {} |
| 815 } |
| 816 '''); |
| 817 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 818 library.libraryCycleForLink.ensureLinked(); |
| 819 // No assertions--just make sure it doesn't crash. |
| 820 } |
| 821 |
| 822 void test_parameterParentElementForLink_implicitFunctionTypeIndices() { |
| 823 createLinker('void f(a, void g(b, c, d, void h())) {}'); |
| 824 TopLevelFunctionElementForLink f = testLibrary.getContainedName('f'); |
| 825 expect(f.implicitFunctionTypeIndices, []); |
| 826 ParameterElementForLink g = f.parameters[1]; |
| 827 FunctionType gType = g.type; |
| 828 FunctionElementForLink_FunctionTypedParam gTypeElement = gType.element; |
| 829 expect(gTypeElement.implicitFunctionTypeIndices, [1]); |
| 830 ParameterElementForLink h = gTypeElement.parameters[3]; |
| 831 FunctionType hType = h.type; |
| 832 FunctionElementForLink_FunctionTypedParam hTypeElement = hType.element; |
| 833 expect(hTypeElement.implicitFunctionTypeIndices, [1, 3]); |
| 834 } |
| 835 |
| 836 void test_parameterParentElementForLink_innermostExecutable() { |
| 837 createLinker('void f(void g(void h())) {}'); |
| 838 TopLevelFunctionElementForLink f = testLibrary.getContainedName('f'); |
| 839 expect(f.typeParameterContext, same(f)); |
| 840 ParameterElementForLink g = f.parameters[0]; |
| 841 FunctionType gType = g.type; |
| 842 FunctionElementForLink_FunctionTypedParam gTypeElement = gType.element; |
| 843 expect(gTypeElement.typeParameterContext, same(f)); |
| 844 ParameterElementForLink h = gTypeElement.parameters[0]; |
| 845 FunctionType hType = h.type; |
| 846 FunctionElementForLink_FunctionTypedParam hTypeElement = hType.element; |
| 847 expect(hTypeElement.typeParameterContext, same(f)); |
| 848 } |
| 849 |
| 850 void test_topLevelFunction_isStatic() { |
| 851 createLinker('f() {}'); |
| 852 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 853 TopLevelFunctionElementForLink f = library.getContainedName('f'); |
| 854 expect(f.isStatic, true); |
| 855 } |
| 856 |
| 857 void test_topLevelGetter_isStatic() { |
| 858 createLinker('get x => null;'); |
| 859 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 860 PropertyAccessorElementForLink_Executable x = library.getContainedName('x'); |
| 861 expect(x.isStatic, true); |
| 862 } |
| 863 |
| 864 void test_topLevelSetter_isStatic() { |
| 865 createLinker('void set x(value) {}'); |
| 866 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 867 PropertyAccessorElementForLink_Executable x = |
| 868 library.getContainedName('x='); |
| 869 expect(x.isStatic, true); |
| 870 } |
| 871 |
| 872 void test_topLevelVariable_isStatic() { |
| 873 createLinker('var x;'); |
| 874 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 875 PropertyAccessorElementForLink_Variable x = library.getContainedName('x'); |
| 876 expect(x.isStatic, true); |
| 877 expect(x.variable.isStatic, true); |
| 878 } |
| 879 |
| 880 void test_typeParameter_isTypeParameterInScope_direct() { |
| 881 createLinker('class C<T, U> {}'); |
| 882 ClassElementForLink_Class c = testLibrary.getContainedName('C'); |
| 883 TypeParameterElementImpl t = c.typeParameters[0]; |
| 884 TypeParameterElementImpl u = c.typeParameters[1]; |
| 885 expect(c.isTypeParameterInScope(t), true); |
| 886 expect(c.isTypeParameterInScope(u), true); |
| 887 } |
| 888 |
| 889 void test_typeParameter_isTypeParameterInScope_indirect() { |
| 890 createLinker('class C<T, U> { f<V, W>() {} }'); |
| 891 ClassElementForLink_Class c = testLibrary.getContainedName('C'); |
| 892 MethodElementForLink f = c.methods[0]; |
| 893 TypeParameterElementImpl t = c.typeParameters[0]; |
| 894 TypeParameterElementImpl u = c.typeParameters[1]; |
| 895 expect(f.isTypeParameterInScope(t), true); |
| 896 expect(f.isTypeParameterInScope(u), true); |
| 897 } |
| 898 |
| 899 void test_typeParameter_isTypeParameterInScope_reversed() { |
| 900 createLinker('class C<T, U> { f<V, W>() {} }'); |
| 901 ClassElementForLink_Class c = testLibrary.getContainedName('C'); |
| 902 MethodElementForLink f = c.methods[0]; |
| 903 TypeParameterElementImpl v = f.typeParameters[0]; |
| 904 TypeParameterElementImpl w = f.typeParameters[1]; |
| 905 expect(c.isTypeParameterInScope(v), false); |
| 906 expect(c.isTypeParameterInScope(w), false); |
| 907 } |
| 908 |
| 909 void test_typeParameter_isTypeParameterInScope_unrelated() { |
| 910 createLinker('class C<T, U> {} class D<V, W> {}'); |
| 911 ClassElementForLink_Class c = testLibrary.getContainedName('C'); |
| 912 ClassElementForLink_Class d = testLibrary.getContainedName('D'); |
| 913 TypeParameterElementImpl t = c.typeParameters[0]; |
| 914 TypeParameterElementImpl u = c.typeParameters[1]; |
| 915 TypeParameterElementImpl v = d.typeParameters[0]; |
| 916 TypeParameterElementImpl w = d.typeParameters[1]; |
| 917 expect(c.isTypeParameterInScope(v), false); |
| 918 expect(c.isTypeParameterInScope(w), false); |
| 919 expect(d.isTypeParameterInScope(t), false); |
| 920 expect(d.isTypeParameterInScope(u), false); |
| 921 } |
| 922 |
| 923 void test_variable_initializer_presence() { |
| 924 // Any variable declaration with an initializer should have a non-null value |
| 925 // for `initializer`, regardless of whether it is constant and regardless of |
| 926 // whether it has an explicit type. |
| 927 createLinker(''' |
| 928 const int c = 0; |
| 929 int i = 0; |
| 930 int j; |
| 931 var v = 0; |
| 932 '''); |
| 933 LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri); |
| 934 PropertyAccessorElementForLink_Variable c = library.getContainedName('c'); |
| 935 expect(c.variable.initializer, isNotNull); |
| 936 PropertyAccessorElementForLink_Variable i = library.getContainedName('i'); |
| 937 expect(i.variable.initializer, isNotNull); |
| 938 PropertyAccessorElementForLink_Variable j = library.getContainedName('j'); |
| 939 expect(j.variable.initializer, isNull); |
| 940 PropertyAccessorElementForLink_Variable v = library.getContainedName('v'); |
| 941 expect(v.variable.initializer, isNotNull); |
| 942 } |
| 943 |
| 944 VariableElementForLink _getVariable(ReferenceableElementForLink element) { |
| 945 return (element as PropertyAccessorElementForLink_Variable).variable; |
| 946 } |
| 947 |
| 948 /** |
| 949 * Finds the first inferred type stored in [unit] whose slot matches [slot]. |
| 950 */ |
| 951 EntityRef _lookupInferredType(LinkedUnit unit, int slot) { |
| 952 for (EntityRef ref in unit.types) { |
| 953 if (ref.slot == slot) { |
| 954 return ref; |
| 955 } |
| 956 } |
| 957 return null; |
| 958 } |
| 959 } |
| OLD | NEW |