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 |