| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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 library serialization.elements; | 5 library serialization.elements; |
| 6 | 6 |
| 7 import 'package:analyzer/dart/element/element.dart'; | 7 import 'package:analyzer/dart/element/element.dart'; |
| 8 import 'package:analyzer/dart/element/type.dart'; | 8 import 'package:analyzer/dart/element/type.dart'; |
| 9 import 'package:analyzer/src/dart/element/element.dart'; |
| 9 import 'package:analyzer/src/dart/element/type.dart'; | 10 import 'package:analyzer/src/dart/element/type.dart'; |
| 11 import 'package:analyzer/src/generated/ast.dart'; |
| 10 import 'package:analyzer/src/generated/resolver.dart'; | 12 import 'package:analyzer/src/generated/resolver.dart'; |
| 11 import 'package:analyzer/src/generated/utilities_dart.dart'; | 13 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 12 import 'package:analyzer/src/summary/format.dart'; | 14 import 'package:analyzer/src/summary/format.dart'; |
| 13 import 'package:analyzer/src/summary/name_filter.dart'; | 15 import 'package:analyzer/src/summary/name_filter.dart'; |
| 16 import 'package:analyzer/src/summary/summarize_const_expr.dart'; |
| 14 | 17 |
| 15 /** | 18 /** |
| 16 * Serialize all the elements in [lib] to a summary using [ctx] as the context | 19 * Serialize all the elements in [lib] to a summary using [ctx] as the context |
| 17 * for building the summary, and using [typeProvider] to find built-in types. | 20 * for building the summary, and using [typeProvider] to find built-in types. |
| 18 */ | 21 */ |
| 19 LibrarySerializationResult serializeLibrary( | 22 LibrarySerializationResult serializeLibrary( |
| 20 LibraryElement lib, TypeProvider typeProvider) { | 23 LibraryElement lib, TypeProvider typeProvider) { |
| 21 var serializer = new _LibrarySerializer(lib, typeProvider); | 24 var serializer = new _LibrarySerializer(lib, typeProvider); |
| 22 LinkedLibraryBuilder linked = serializer.serializeLibrary(); | 25 LinkedLibraryBuilder linked = serializer.serializeLibrary(); |
| 23 return new LibrarySerializationResult( | 26 return new LibrarySerializationResult( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 44 /** | 47 /** |
| 45 * Absolute URI of each compilation unit appearing in the library. | 48 * Absolute URI of each compilation unit appearing in the library. |
| 46 */ | 49 */ |
| 47 final List<String> unitUris; | 50 final List<String> unitUris; |
| 48 | 51 |
| 49 LibrarySerializationResult(this.linked, this.unlinkedUnits, this.unitUris); | 52 LibrarySerializationResult(this.linked, this.unlinkedUnits, this.unitUris); |
| 50 } | 53 } |
| 51 | 54 |
| 52 /** | 55 /** |
| 53 * Instances of this class keep track of intermediate state during | 56 * Instances of this class keep track of intermediate state during |
| 54 * serialization of a single library.` | 57 * serialization of a single constant [Expression]. |
| 58 */ |
| 59 class _ConstExprSerializer extends AbstractConstExprSerializer { |
| 60 final _LibrarySerializer serializer; |
| 61 |
| 62 _ConstExprSerializer(this.serializer); |
| 63 |
| 64 UnlinkedTypeRefBuilder serializeIdentifier(Identifier identifier) { |
| 65 Element element = identifier.staticElement; |
| 66 assert(element != null); |
| 67 // TODO(scheglov) how to serialize element references? |
| 68 operations.add(UnlinkedConstOperation.pushReference); |
| 69 return new UnlinkedTypeRefBuilder( |
| 70 reference: serializer._getElementReferenceId(element)); |
| 71 } |
| 72 |
| 73 @override |
| 74 UnlinkedTypeRefBuilder serializeType(TypeName typeName) { |
| 75 DartType type = typeName != null ? typeName.type : DynamicTypeImpl.instance; |
| 76 return serializer.serializeTypeRef(type, null); |
| 77 } |
| 78 } |
| 79 |
| 80 /** |
| 81 * Instances of this class keep track of intermediate state during |
| 82 * serialization of a single library. |
| 55 */ | 83 */ |
| 56 class _LibrarySerializer { | 84 class _LibrarySerializer { |
| 57 /** | 85 /** |
| 58 * The library to be serialized. | 86 * The library to be serialized. |
| 59 */ | 87 */ |
| 60 final LibraryElement libraryElement; | 88 final LibraryElement libraryElement; |
| 61 | 89 |
| 62 /** | 90 /** |
| 63 * The type provider. This is used to locate the library for `dart:core`. | 91 * The type provider. This is used to locate the library for `dart:core`. |
| 64 */ | 92 */ |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder(); | 406 UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder(); |
| 379 if (combinator is ShowElementCombinator) { | 407 if (combinator is ShowElementCombinator) { |
| 380 b.shows = combinator.shownNames; | 408 b.shows = combinator.shownNames; |
| 381 } else if (combinator is HideElementCombinator) { | 409 } else if (combinator is HideElementCombinator) { |
| 382 b.hides = combinator.hiddenNames; | 410 b.hides = combinator.hiddenNames; |
| 383 } | 411 } |
| 384 return b; | 412 return b; |
| 385 } | 413 } |
| 386 | 414 |
| 387 /** | 415 /** |
| 416 * Serialize the given [expression], creating an [UnlinkedConstBuilder]. |
| 417 */ |
| 418 UnlinkedConstBuilder serializeConstExpr(Expression expression) { |
| 419 _ConstExprSerializer serializer = new _ConstExprSerializer(this); |
| 420 serializer.serialize(expression); |
| 421 return serializer.toBuilder(); |
| 422 } |
| 423 |
| 424 /** |
| 388 * Return the index of the entry in the dependency table | 425 * Return the index of the entry in the dependency table |
| 389 * ([LinkedLibrary.dependencies]) for the given [dependentLibrary]. A new | 426 * ([LinkedLibrary.dependencies]) for the given [dependentLibrary]. A new |
| 390 * entry is added to the table if necessary to satisfy the request. | 427 * entry is added to the table if necessary to satisfy the request. |
| 391 */ | 428 */ |
| 392 int serializeDependency(LibraryElement dependentLibrary) { | 429 int serializeDependency(LibraryElement dependentLibrary) { |
| 393 return dependencyMap.putIfAbsent(dependentLibrary, () { | 430 return dependencyMap.putIfAbsent(dependentLibrary, () { |
| 394 int index = dependencies.length; | 431 int index = dependencies.length; |
| 395 List<String> parts = dependentLibrary.parts | 432 List<String> parts = dependentLibrary.parts |
| 396 .map((CompilationUnitElement e) => e.source.uri.toString()) | 433 .map((CompilationUnitElement e) => e.source.uri.toString()) |
| 397 .toList(); | 434 .toList(); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 for (String name in exportedNames) { | 594 for (String name in exportedNames) { |
| 558 if (libraryElement.publicNamespace.definedNames.containsKey(name)) { | 595 if (libraryElement.publicNamespace.definedNames.containsKey(name)) { |
| 559 continue; | 596 continue; |
| 560 } | 597 } |
| 561 Element element = libraryElement.exportNamespace.get(name); | 598 Element element = libraryElement.exportNamespace.get(name); |
| 562 LibraryElement dependentLibrary = element.library; | 599 LibraryElement dependentLibrary = element.library; |
| 563 CompilationUnitElement unitElement = | 600 CompilationUnitElement unitElement = |
| 564 element.getAncestor((Element e) => e is CompilationUnitElement); | 601 element.getAncestor((Element e) => e is CompilationUnitElement); |
| 565 int unit = dependentLibrary.units.indexOf(unitElement); | 602 int unit = dependentLibrary.units.indexOf(unitElement); |
| 566 assert(unit != -1); | 603 assert(unit != -1); |
| 567 ReferenceKind kind; | 604 ReferenceKind kind = _getReferenceKind(element); |
| 568 if (element is PropertyAccessorElement) { | |
| 569 kind = ReferenceKind.topLevelPropertyAccessor; | |
| 570 } else if (element is FunctionTypeAliasElement) { | |
| 571 kind = ReferenceKind.typedef; | |
| 572 } else if (element is ClassElement) { | |
| 573 kind = ReferenceKind.classOrEnum; | |
| 574 } else if (element is FunctionElement) { | |
| 575 kind = ReferenceKind.topLevelFunction; | |
| 576 } else { | |
| 577 throw new Exception('Unexpected element kind: ${element.runtimeType}'); | |
| 578 } | |
| 579 exportNames.add(new LinkedExportNameBuilder( | 605 exportNames.add(new LinkedExportNameBuilder( |
| 580 name: name, | 606 name: name, |
| 581 dependency: serializeDependency(dependentLibrary), | 607 dependency: serializeDependency(dependentLibrary), |
| 582 unit: unit, | 608 unit: unit, |
| 583 kind: kind)); | 609 kind: kind)); |
| 584 } | 610 } |
| 585 pb.exportNames = exportNames; | 611 pb.exportNames = exportNames; |
| 586 return pb; | 612 return pb; |
| 587 } | 613 } |
| 588 | 614 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 Element element = type.element; | 713 Element element = type.element; |
| 688 LibraryElement dependentLibrary = element.library; | 714 LibraryElement dependentLibrary = element.library; |
| 689 if (dependentLibrary == null) { | 715 if (dependentLibrary == null) { |
| 690 assert(type.isDynamic); | 716 assert(type.isDynamic); |
| 691 if (type is UndefinedTypeImpl) { | 717 if (type is UndefinedTypeImpl) { |
| 692 b.reference = serializeUnresolvedReference(); | 718 b.reference = serializeUnresolvedReference(); |
| 693 } else { | 719 } else { |
| 694 b.reference = serializeDynamicReference(); | 720 b.reference = serializeDynamicReference(); |
| 695 } | 721 } |
| 696 } else { | 722 } else { |
| 697 b.reference = referenceMap.putIfAbsent(element, () { | 723 b.reference = _getElementReferenceId(element); |
| 698 assert(unlinkedReferences.length == linkedReferences.length); | |
| 699 CompilationUnitElement unitElement = | |
| 700 element.getAncestor((Element e) => e is CompilationUnitElement); | |
| 701 int unit = dependentLibrary.units.indexOf(unitElement); | |
| 702 assert(unit != -1); | |
| 703 int numTypeParameters = 0; | |
| 704 if (element is TypeParameterizedElement) { | |
| 705 numTypeParameters = element.typeParameters.length; | |
| 706 } | |
| 707 // Figure out a prefix that may be used to refer to the given type. | |
| 708 // TODO(paulberry): to avoid subtle relinking inconsistencies we | |
| 709 // should use the actual prefix from the AST (a given type may be | |
| 710 // reachable via multiple prefixes), but sadly, this information is | |
| 711 // not recorded in the element model. | |
| 712 int prefixReference = 0; | |
| 713 PrefixElement prefix = prefixMap[element]; | |
| 714 if (prefix != null) { | |
| 715 prefixReference = serializePrefix(prefix); | |
| 716 } | |
| 717 int index = unlinkedReferences.length; | |
| 718 unlinkedReferences.add(new UnlinkedReferenceBuilder( | |
| 719 name: element.name, prefixReference: prefixReference)); | |
| 720 linkedReferences.add(new LinkedReferenceBuilder( | |
| 721 dependency: serializeDependency(dependentLibrary), | |
| 722 kind: element is FunctionTypeAliasElement | |
| 723 ? ReferenceKind.typedef | |
| 724 : ReferenceKind.classOrEnum, | |
| 725 unit: unit, | |
| 726 numTypeParameters: numTypeParameters)); | |
| 727 return index; | |
| 728 }); | |
| 729 } | 724 } |
| 730 List<DartType> typeArguments; | 725 List<DartType> typeArguments; |
| 731 if (type is InterfaceType) { | 726 if (type is InterfaceType) { |
| 732 typeArguments = type.typeArguments; | 727 typeArguments = type.typeArguments; |
| 733 } else if (type is FunctionType) { | 728 } else if (type is FunctionType) { |
| 734 typeArguments = type.typeArguments; | 729 typeArguments = type.typeArguments; |
| 735 } | 730 } |
| 736 if (typeArguments != null && | 731 if (typeArguments != null && |
| 737 typeArguments.any((DartType argument) => !argument.isDynamic)) { | 732 typeArguments.any((DartType argument) => !argument.isDynamic)) { |
| 738 b.typeArguments = typeArguments | 733 b.typeArguments = typeArguments |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 UnlinkedVariableBuilder serializeVariable(PropertyInducingElement variable) { | 766 UnlinkedVariableBuilder serializeVariable(PropertyInducingElement variable) { |
| 772 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(); | 767 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(); |
| 773 b.name = variable.name; | 768 b.name = variable.name; |
| 774 b.nameOffset = variable.nameOffset; | 769 b.nameOffset = variable.nameOffset; |
| 775 b.type = serializeTypeRef(variable.type, variable); | 770 b.type = serializeTypeRef(variable.type, variable); |
| 776 b.isStatic = variable.isStatic && variable.enclosingElement is ClassElement; | 771 b.isStatic = variable.isStatic && variable.enclosingElement is ClassElement; |
| 777 b.isFinal = variable.isFinal; | 772 b.isFinal = variable.isFinal; |
| 778 b.isConst = variable.isConst; | 773 b.isConst = variable.isConst; |
| 779 b.hasImplicitType = variable.hasImplicitType; | 774 b.hasImplicitType = variable.hasImplicitType; |
| 780 b.documentationComment = serializeDocumentation(variable); | 775 b.documentationComment = serializeDocumentation(variable); |
| 776 if (variable.isConst && variable is ConstVariableElement) { |
| 777 ConstVariableElement constVariable = variable as ConstVariableElement; |
| 778 Expression initializer = constVariable.constantInitializer; |
| 779 if (initializer != null) { |
| 780 b.constExpr = serializeConstExpr(initializer); |
| 781 } |
| 782 } |
| 781 return b; | 783 return b; |
| 782 } | 784 } |
| 785 |
| 786 int _getElementReferenceId(Element element) { |
| 787 LibraryElement dependentLibrary = element.library; |
| 788 return referenceMap.putIfAbsent(element, () { |
| 789 assert(unlinkedReferences.length == linkedReferences.length); |
| 790 CompilationUnitElement unitElement = |
| 791 element.getAncestor((Element e) => e is CompilationUnitElement); |
| 792 int unit = dependentLibrary.units.indexOf(unitElement); |
| 793 assert(unit != -1); |
| 794 int numTypeParameters = 0; |
| 795 if (element is TypeParameterizedElement) { |
| 796 numTypeParameters = element.typeParameters.length; |
| 797 } |
| 798 // Figure out a prefix that may be used to refer to the given type. |
| 799 // TODO(paulberry): to avoid subtle relinking inconsistencies we |
| 800 // should use the actual prefix from the AST (a given type may be |
| 801 // reachable via multiple prefixes), but sadly, this information is |
| 802 // not recorded in the element model. |
| 803 int prefixReference = 0; |
| 804 PrefixElement prefix = prefixMap[element]; |
| 805 if (prefix != null) { |
| 806 prefixReference = serializePrefix(prefix); |
| 807 } |
| 808 int index = unlinkedReferences.length; |
| 809 unlinkedReferences.add(new UnlinkedReferenceBuilder( |
| 810 name: element.name, prefixReference: prefixReference)); |
| 811 linkedReferences.add(new LinkedReferenceBuilder( |
| 812 dependency: serializeDependency(dependentLibrary), |
| 813 kind: _getReferenceKind(element), |
| 814 unit: unit, |
| 815 numTypeParameters: numTypeParameters)); |
| 816 return index; |
| 817 }); |
| 818 } |
| 819 |
| 820 ReferenceKind _getReferenceKind(Element element) { |
| 821 ReferenceKind kind; |
| 822 if (element is PropertyAccessorElement) { |
| 823 kind = ReferenceKind.topLevelPropertyAccessor; |
| 824 } else if (element is FunctionTypeAliasElement) { |
| 825 kind = ReferenceKind.typedef; |
| 826 } else if (element is ClassElement) { |
| 827 kind = ReferenceKind.classOrEnum; |
| 828 } else if (element is FunctionElement) { |
| 829 kind = ReferenceKind.topLevelFunction; |
| 830 } else { |
| 831 throw new Exception('Unexpected element kind: ${element.runtimeType}'); |
| 832 } |
| 833 return kind; |
| 834 } |
| 783 } | 835 } |
| OLD | NEW |