Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 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 | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:collection'; | 6 import 'dart:collection'; |
| 7 import 'dart:convert'; | 7 import 'dart:convert'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 // URIs with the 'dart:' scheme are served from the SDK bundle. | 435 // URIs with the 'dart:' scheme are served from the SDK bundle. |
| 436 if (libraryUri.scheme == 'dart') { | 436 if (libraryUri.scheme == 'dart') { |
| 437 return null; | 437 return null; |
| 438 } | 438 } |
| 439 | 439 |
| 440 String libraryUriStr = libraryUri.toString(); | 440 String libraryUriStr = libraryUri.toString(); |
| 441 _LibraryNode node = nodes[libraryUriStr]; | 441 _LibraryNode node = nodes[libraryUriStr]; |
| 442 if (node == null) { | 442 if (node == null) { |
| 443 node = new _LibraryNode(this, nodes, libraryUri); | 443 node = new _LibraryNode(this, nodes, libraryUri); |
| 444 nodes[libraryUriStr] = node; | 444 nodes[libraryUriStr] = node; |
| 445 _ReferencedUris referenced = _getReferencedUris(libraryFile); | |
| 446 | 445 |
| 447 // Append the defining unit. | 446 // Append the defining unit. |
| 447 _ReferencedUris referenced; | |
| 448 { | 448 { |
| 449 PackageBundle unlinked = _getUnlinked(libraryFile); | 449 PackageBundle bundle = _getUnlinked(libraryFile); |
| 450 node.unlinkedBundles.add(unlinked); | 450 UnlinkedUnit unlinked = bundle.unlinkedUnits.single; |
| 451 _addToStoreUnlinked( | 451 referenced = new _ReferencedUris(unlinked); |
| 452 store, libraryUriStr, unlinked.unlinkedUnits.single); | 452 node.unlinkedBundles.add(bundle); |
| 453 _addToStoreUnlinked(store, libraryUriStr, unlinked); | |
| 453 } | 454 } |
| 454 | 455 |
| 455 // Append unlinked bundles. | 456 // Append parts. |
| 456 for (String uri in referenced.parted) { | 457 for (String uri in referenced.parted) { |
| 457 _File file = libraryFile.resolveUri(uri); | 458 _File file = libraryFile.resolveUri(uri); |
| 458 PackageBundle unlinked = _getUnlinked(file); | 459 PackageBundle bundle = _getUnlinked(file); |
| 459 node.unlinkedBundles.add(unlinked); | 460 UnlinkedUnit unlinked = bundle.unlinkedUnits.single; |
| 460 _addToStoreUnlinked( | 461 node.unlinkedBundles.add(bundle); |
| 461 store, file.uri.toString(), unlinked.unlinkedUnits.single); | 462 _addToStoreUnlinked(store, file.uri.toString(), unlinked); |
| 462 } | 463 } |
| 463 | 464 |
| 464 // Create nodes for referenced libraries. | 465 // Create nodes for referenced libraries. |
| 465 for (String uri in referenced.imported) { | 466 for (String uri in referenced.imported) { |
| 466 _File file = libraryFile.resolveUri(uri); | 467 _File file = libraryFile.resolveUri(uri); |
| 467 createLibraryNodes(file); | 468 createLibraryNodes(file); |
| 468 } | 469 } |
| 469 for (String uri in referenced.exported) { | 470 for (String uri in referenced.exported) { |
| 470 _File file = libraryFile.resolveUri(uri); | 471 _File file = libraryFile.resolveUri(uri); |
| 471 createLibraryNodes(file); | 472 createLibraryNodes(file); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 /** | 547 /** |
| 547 * Return the unlinked bundle of [file] for the current file state, or `null`. | 548 * Return the unlinked bundle of [file] for the current file state, or `null`. |
| 548 */ | 549 */ |
| 549 PackageBundle _getCurrentUnlinked(_File file) { | 550 PackageBundle _getCurrentUnlinked(_File file) { |
| 550 String key = '${file.currentContentHash}.unlinked'; | 551 String key = '${file.currentContentHash}.unlinked'; |
| 551 List<int> bytes = _byteStore.get(key); | 552 List<int> bytes = _byteStore.get(key); |
| 552 return bytes != null ? new PackageBundle.fromBuffer(bytes) : null; | 553 return bytes != null ? new PackageBundle.fromBuffer(bytes) : null; |
| 553 } | 554 } |
| 554 | 555 |
| 555 /** | 556 /** |
| 556 * TODO(scheglov) It would be nice to get URIs of "parts" from unlinked. | |
| 557 */ | |
| 558 _ReferencedUris _getReferencedUris(_File file) { | |
| 559 // Try to get from the store. | |
| 560 { | |
| 561 String key = '${file.contentHash}.uris'; | |
| 562 List<int> bytes = _byteStore.get(key); | |
| 563 if (bytes != null) { | |
| 564 fb.BufferContext bp = new fb.BufferContext.fromBytes(bytes); | |
| 565 int table = bp.derefObject(0); | |
| 566 const fb.ListReader<String> stringListReader = | |
| 567 const fb.ListReader<String>(const fb.StringReader()); | |
| 568 bool isLibrary = const fb.BoolReader().vTableGet(bp, table, 0); | |
| 569 List<String> imported = stringListReader.vTableGet(bp, table, 1); | |
| 570 List<String> exported = stringListReader.vTableGet(bp, table, 2); | |
| 571 List<String> parted = stringListReader.vTableGet(bp, table, 3); | |
| 572 _ReferencedUris referencedUris = new _ReferencedUris(); | |
| 573 referencedUris.isLibrary = isLibrary; | |
| 574 referencedUris.imported.addAll(imported); | |
| 575 referencedUris.exported.addAll(exported); | |
| 576 referencedUris.parted.addAll(parted); | |
| 577 return referencedUris; | |
| 578 } | |
| 579 } | |
| 580 | |
| 581 // Compute URIs. | |
| 582 _ReferencedUris referencedUris = new _ReferencedUris(); | |
| 583 for (Directive directive in file.unit.directives) { | |
| 584 if (directive is PartOfDirective) { | |
| 585 referencedUris.isLibrary = false; | |
| 586 } else if (directive is UriBasedDirective) { | |
| 587 String uri = directive.uri.stringValue; | |
| 588 if (directive is ImportDirective) { | |
| 589 referencedUris.imported.add(uri); | |
| 590 } else if (directive is ExportDirective) { | |
| 591 referencedUris.exported.add(uri); | |
| 592 } else if (directive is PartDirective) { | |
| 593 referencedUris.parted.add(uri); | |
| 594 } | |
| 595 } | |
| 596 } | |
| 597 | |
| 598 // Serialize into bytes. | |
| 599 List<int> bytes; | |
| 600 { | |
| 601 fb.Builder fbBuilder = new fb.Builder(); | |
| 602 var importedOffset = fbBuilder.writeList(referencedUris.imported | |
| 603 .map((uri) => fbBuilder.writeString(uri)) | |
| 604 .toList()); | |
| 605 var exportedOffset = fbBuilder.writeList(referencedUris.exported | |
| 606 .map((uri) => fbBuilder.writeString(uri)) | |
| 607 .toList()); | |
| 608 var partedOffset = fbBuilder.writeList(referencedUris.parted | |
| 609 .map((uri) => fbBuilder.writeString(uri)) | |
| 610 .toList()); | |
| 611 fbBuilder.startTable(); | |
| 612 fbBuilder.addBool(0, referencedUris.isLibrary); | |
| 613 fbBuilder.addOffset(1, importedOffset); | |
| 614 fbBuilder.addOffset(2, exportedOffset); | |
| 615 fbBuilder.addOffset(3, partedOffset); | |
| 616 var offset = fbBuilder.endTable(); | |
| 617 bytes = fbBuilder.finish(offset, 'SoRU'); | |
| 618 } | |
| 619 | |
| 620 // We read the content and recomputed the hash. | |
| 621 // So, we need to update the key. | |
| 622 String key = '${file.contentHash}.uris'; | |
| 623 _byteStore.put(key, bytes); | |
| 624 | |
| 625 return referencedUris; | |
| 626 } | |
| 627 | |
| 628 /** | |
| 629 * Return the unlinked bundle of [file] for the current file state. | 557 * Return the unlinked bundle of [file] for the current file state. |
| 630 * | 558 * |
| 631 * Return [_getCurrentUnlinked] or read the [file] content is read, compute | 559 * Return [_getCurrentUnlinked] or read the [file] content is read, compute |
| 632 * the content hash and update the current file state accordingly. Parse the | 560 * the content hash and update the current file state accordingly. Parse the |
| 633 * content into the [CompilationUnit] and serialize into a new unlinked | 561 * content into the [CompilationUnit] and serialize into a new unlinked |
| 634 * bundle. The bundle is then put into the [_byteStore] and returned. | 562 * bundle. The bundle is then put into the [_byteStore] and returned. |
| 635 */ | 563 */ |
| 636 PackageBundle _getUnlinked(_File file) { | 564 PackageBundle _getUnlinked(_File file) { |
| 565 // By accessing 'contentHash' we ensure that the current file state | |
| 566 // has some version of the file content hash, so we will be able to | |
| 567 // use it to attempt to get the current unlinked bundle. | |
| 568 String key = '${file.contentHash}.unlinked'; | |
| 637 return _getCurrentUnlinked(file) ?? | 569 return _getCurrentUnlinked(file) ?? |
| 638 _logger.run('Create unlinked for $file', () { | 570 _logger.run('Create unlinked for $file', () { |
| 639 String key = '${file.contentHash}.unlinked'; | |
| 640 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(file.unit); | 571 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(file.unit); |
| 641 PackageBundleAssembler assembler = new PackageBundleAssembler(); | 572 PackageBundleAssembler assembler = new PackageBundleAssembler(); |
| 642 assembler.addUnlinkedUnitWithHash( | 573 assembler.addUnlinkedUnitWithHash( |
| 643 file.uri.toString(), unlinkedUnit, key); | 574 file.uri.toString(), unlinkedUnit, key); |
| 644 List<int> bytes = assembler.assemble().toBuffer(); | 575 List<int> bytes = assembler.assemble().toBuffer(); |
| 645 _byteStore.put(key, bytes); | 576 _byteStore.put(key, bytes); |
| 646 return new PackageBundle.fromBuffer(bytes); | 577 return new PackageBundle.fromBuffer(bytes); |
| 647 }); | 578 }); |
| 648 } | 579 } |
| 649 | 580 |
| 650 /** | 581 /** |
| 651 * Verify the API signatures for the changed files, and decide which linked | 582 * Verify the API signatures for the changed files, and decide which linked |
| 652 * libraries should be invalidated, and files reanalyzed. | 583 * libraries should be invalidated, and files reanalyzed. |
| 584 * | |
| 585 * TODO(scheglov) I see that adding a local var changes (full) API signature. | |
|
Paul Berry
2016/10/31 15:56:56
Do you have a repro for this? If you'd rather spe
scheglov
2016/10/31 16:03:16
Adding a local variable per se is not a problem.
B
| |
| 653 */ | 586 */ |
| 654 void _verifyUnlinkedSignatureOfChangedFiles() { | 587 void _verifyUnlinkedSignatureOfChangedFiles() { |
| 655 if (_filesToVerifyUnlinkedSignature.isEmpty) { | 588 if (_filesToVerifyUnlinkedSignature.isEmpty) { |
| 656 return; | 589 return; |
| 657 } | 590 } |
| 658 int numOfFiles = _filesToVerifyUnlinkedSignature.length; | 591 int numOfFiles = _filesToVerifyUnlinkedSignature.length; |
| 659 _logger.run('Verify API signatures of $numOfFiles files', () { | 592 _logger.run('Verify API signatures of $numOfFiles files', () { |
| 660 for (String path in _filesToVerifyUnlinkedSignature) { | 593 for (String path in _filesToVerifyUnlinkedSignature) { |
| 661 _File file = _fileForPath(path); | 594 _File file = _fileForPath(path); |
| 662 // Get the existing old API signature, maybe null. | 595 // Get the existing old API signature, maybe null. |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1032 } | 965 } |
| 1033 | 966 |
| 1034 /** | 967 /** |
| 1035 * TODO(scheglov) document | 968 * TODO(scheglov) document |
| 1036 */ | 969 */ |
| 1037 class _ReferencedUris { | 970 class _ReferencedUris { |
| 1038 bool isLibrary = true; | 971 bool isLibrary = true; |
| 1039 final List<String> imported = <String>[]; | 972 final List<String> imported = <String>[]; |
| 1040 final List<String> exported = <String>[]; | 973 final List<String> exported = <String>[]; |
| 1041 final List<String> parted = <String>[]; | 974 final List<String> parted = <String>[]; |
| 975 | |
| 976 factory _ReferencedUris(UnlinkedUnit unit) { | |
| 977 _ReferencedUris referenced = new _ReferencedUris._(); | |
| 978 referenced.parted.addAll(unit.publicNamespace.parts); | |
| 979 for (UnlinkedImport import in unit.imports) { | |
| 980 if (!import.isImplicit) { | |
| 981 referenced.imported.add(import.uri); | |
| 982 } | |
| 983 } | |
| 984 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { | |
| 985 referenced.exported.add(export.uri); | |
| 986 } | |
| 987 return referenced; | |
| 988 } | |
| 989 | |
| 990 _ReferencedUris._(); | |
| 1042 } | 991 } |
| OLD | NEW |