Chromium Code Reviews| 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 summary_resynthesizer; | 5 library summary_resynthesizer; |
| 6 | 6 |
| 7 import 'dart:collection'; | |
| 8 | |
| 7 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 8 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
| 9 import 'package:analyzer/src/generated/element_handle.dart'; | 11 import 'package:analyzer/src/generated/element_handle.dart'; |
| 10 import 'package:analyzer/src/generated/engine.dart'; | 12 import 'package:analyzer/src/generated/engine.dart'; |
| 11 import 'package:analyzer/src/generated/resolver.dart'; | 13 import 'package:analyzer/src/generated/resolver.dart'; |
| 12 import 'package:analyzer/src/generated/source_io.dart'; | 14 import 'package:analyzer/src/generated/source_io.dart'; |
| 13 import 'package:analyzer/src/summary/format.dart'; | 15 import 'package:analyzer/src/summary/format.dart'; |
| 14 | 16 |
| 15 /** | 17 /** |
| 16 * Callback used by [SummaryResynthesizer] to obtain the prelinked summary for | 18 * Callback used by [SummaryResynthesizer] to obtain the prelinked summary for |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 516 new ElementLocationImpl.con3(<String>[exportedLibraryUri])); | 518 new ElementLocationImpl.con3(<String>[exportedLibraryUri])); |
| 517 exportElement.uri = serializedExportPublic.uri; | 519 exportElement.uri = serializedExportPublic.uri; |
| 518 exportElement.combinators = | 520 exportElement.combinators = |
| 519 serializedExportPublic.combinators.map(buildCombinator).toList(); | 521 serializedExportPublic.combinators.map(buildCombinator).toList(); |
| 520 exportElement.uriOffset = serializedExportNonPublic.uriOffset; | 522 exportElement.uriOffset = serializedExportNonPublic.uriOffset; |
| 521 exportElement.uriEnd = serializedExportNonPublic.uriEnd; | 523 exportElement.uriEnd = serializedExportNonPublic.uriEnd; |
| 522 return exportElement; | 524 return exportElement; |
| 523 } | 525 } |
| 524 | 526 |
| 525 /** | 527 /** |
| 528 * Build an [ElementHandle] referring to the entity referred to by the given | |
| 529 * [exportName]. | |
| 530 */ | |
| 531 ElementHandle buildExportName(PrelinkedExportName exportName) { | |
| 532 String name = exportName.name; | |
| 533 if (exportName.kind == PrelinkedReferenceKind.topLevelPropertyAccessor && | |
| 534 !name.endsWith('=')) { | |
| 535 name += '?'; | |
| 536 } | |
| 537 ElementLocationImpl location = getReferencedLocation( | |
| 538 prelinkedLibrary.dependencies[exportName.dependency], | |
| 539 exportName.unit, | |
| 540 name); | |
| 541 switch (exportName.kind) { | |
| 542 case PrelinkedReferenceKind.classOrEnum: | |
| 543 return new ClassElementHandle(summaryResynthesizer, location); | |
| 544 case PrelinkedReferenceKind.typedef: | |
| 545 return new FunctionTypeAliasElementHandle( | |
| 546 summaryResynthesizer, location); | |
| 547 case PrelinkedReferenceKind.topLevelFunction: | |
| 548 return new FunctionElementHandle(summaryResynthesizer, location); | |
| 549 case PrelinkedReferenceKind.topLevelPropertyAccessor: | |
| 550 return new PropertyAccessorElementHandle( | |
| 551 summaryResynthesizer, location); | |
| 552 case PrelinkedReferenceKind.prefix: | |
| 553 case PrelinkedReferenceKind.unresolved: | |
| 554 // Should never happen. Exported names never refer to import prefixes, | |
| 555 // and they always refer to defined entities. | |
| 556 throw new StateError('Unexpected export name kind: ${exportName.kind}'); | |
| 557 } | |
| 558 } | |
| 559 | |
| 560 /** | |
| 561 * Build the export namespace for the library by aggregating together its | |
| 562 * [publicNamespace] and [exportNames]. | |
| 563 */ | |
| 564 Namespace buildExportNamespace( | |
| 565 Namespace publicNamespace, List<PrelinkedExportName> exportNames) { | |
| 566 HashMap<String, Element> definedNames = new HashMap<String, Element>(); | |
| 567 // Start by populating all the public names from [publicNamespace]. | |
| 568 publicNamespace.definedNames.forEach((String name, Element element) { | |
| 569 definedNames[name] = element; | |
| 570 }); | |
| 571 // Add all the names from [exportNames]. | |
| 572 for (PrelinkedExportName exportName in exportNames) { | |
| 573 definedNames.putIfAbsent( | |
| 574 exportName.name, () => buildExportName(exportName)); | |
| 575 } | |
| 576 return new Namespace(definedNames); | |
| 577 } | |
| 578 | |
| 579 /** | |
| 526 * Resynthesize a [FieldElement]. | 580 * Resynthesize a [FieldElement]. |
| 527 */ | 581 */ |
| 528 FieldElement buildField(UnlinkedVariable serializedField) { | 582 FieldElement buildField(UnlinkedVariable serializedField) { |
| 529 FieldElementImpl fieldElement = | 583 FieldElementImpl fieldElement = |
| 530 new FieldElementImpl(serializedField.name, -1); | 584 new FieldElementImpl(serializedField.name, -1); |
| 531 fieldElement.type = buildType(serializedField.type); | 585 fieldElement.type = buildType(serializedField.type); |
| 532 fieldElement.const3 = serializedField.isConst; | 586 fieldElement.const3 = serializedField.isConst; |
| 533 return fieldElement; | 587 return fieldElement; |
| 534 } | 588 } |
| 535 | 589 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 702 if (isCoreLibrary) { | 756 if (isCoreLibrary) { |
| 703 ClassElement objectElement = libraryElement.getType('Object'); | 757 ClassElement objectElement = libraryElement.getType('Object'); |
| 704 assert(objectElement != null); | 758 assert(objectElement != null); |
| 705 for (ClassElementImpl classElement in delayedObjectSubclasses) { | 759 for (ClassElementImpl classElement in delayedObjectSubclasses) { |
| 706 classElement.supertype = objectElement.type; | 760 classElement.supertype = objectElement.type; |
| 707 } | 761 } |
| 708 } | 762 } |
| 709 // Compute namespaces. | 763 // Compute namespaces. |
| 710 libraryElement.publicNamespace = | 764 libraryElement.publicNamespace = |
| 711 new NamespaceBuilder().createPublicNamespaceForLibrary(libraryElement); | 765 new NamespaceBuilder().createPublicNamespaceForLibrary(libraryElement); |
| 712 // TODO(paulberry): compute the export namespace from prelinked data, so | 766 libraryElement.exportNamespace = buildExportNamespace( |
| 713 // that exported libraries won't be unnecessarily resynthesized. | 767 libraryElement.publicNamespace, prelinkedLibrary.exportNames); |
| 714 libraryElement.exportNamespace = | 768 // Find the entry point. Note: we can't use element.isEntryPoint because |
| 715 new NamespaceBuilder().createExportNamespaceForLibrary(libraryElement); | 769 // that will trigger resynthesis of exported libraries. |
| 716 // Find the entry point. | 770 Element entryPoint = libraryElement.exportNamespace.get('main'); |
|
scheglov
2016/01/13 20:59:35
FunctionElement.MAIN_FUNCTION_NAME
Paul Berry
2016/01/13 21:15:24
Done.
| |
| 717 libraryElement.entryPoint = | 771 if (entryPoint is FunctionElement) { |
| 718 libraryElement.exportNamespace.definedNames.values.firstWhere( | 772 libraryElement.entryPoint = entryPoint; |
| 719 (element) => element is FunctionElement && element.isEntryPoint, | 773 } |
| 720 orElse: () => null); | |
| 721 // Create the synthetic element for `loadLibrary`. | 774 // Create the synthetic element for `loadLibrary`. |
| 722 libraryElement.createLoadLibraryFunction(summaryResynthesizer.typeProvider); | 775 libraryElement.createLoadLibraryFunction(summaryResynthesizer.typeProvider); |
| 723 // Done. | 776 // Done. |
| 724 return libraryElement; | 777 return libraryElement; |
| 725 } | 778 } |
| 726 | 779 |
| 727 /** | 780 /** |
| 728 * Resynthesize a [ParameterElement]. | 781 * Resynthesize a [ParameterElement]. |
| 729 */ | 782 */ |
| 730 ParameterElement buildParameter(UnlinkedParam serializedParameter) { | 783 ParameterElement buildParameter(UnlinkedParam serializedParameter) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 784 /** | 837 /** |
| 785 * Build a [DartType] object based on an [UnlinkedTypeRef]. This [DartType] | 838 * Build a [DartType] object based on an [UnlinkedTypeRef]. This [DartType] |
| 786 * may refer to elements in other libraries than the library being | 839 * may refer to elements in other libraries than the library being |
| 787 * deserialized, so handles are used to avoid having to deserialize other | 840 * deserialized, so handles are used to avoid having to deserialize other |
| 788 * libraries in the process. | 841 * libraries in the process. |
| 789 */ | 842 */ |
| 790 DartType buildType(UnlinkedTypeRef type) { | 843 DartType buildType(UnlinkedTypeRef type) { |
| 791 if (type.paramReference != 0) { | 844 if (type.paramReference != 0) { |
| 792 // TODO(paulberry): make this work for generic methods. | 845 // TODO(paulberry): make this work for generic methods. |
| 793 return currentTypeParameters[ | 846 return currentTypeParameters[ |
| 794 currentTypeParameters.length - type.paramReference] | 847 currentTypeParameters.length - type.paramReference].type; |
| 795 .type; | |
| 796 } else { | 848 } else { |
| 797 // TODO(paulberry): handle references to things other than classes (note: | 849 // TODO(paulberry): handle references to things other than classes (note: |
| 798 // this should only occur in the case of erroneous code). | 850 // this should only occur in the case of erroneous code). |
| 799 // TODO(paulberry): test reference to something inside a part. | 851 // TODO(paulberry): test reference to something inside a part. |
| 800 // TODO(paulberry): test reference to something inside a part of the | 852 // TODO(paulberry): test reference to something inside a part of the |
| 801 // current lib. | 853 // current lib. |
| 802 UnlinkedReference reference = unlinkedUnit.references[type.reference]; | 854 UnlinkedReference reference = unlinkedUnit.references[type.reference]; |
| 803 PrelinkedReference referenceResolution = | 855 PrelinkedReference referenceResolution = |
| 804 prelinkedUnit.references[type.reference]; | 856 prelinkedUnit.references[type.reference]; |
| 805 String referencedLibraryUri; | 857 ElementLocationImpl location; |
| 806 String partUri; | |
| 807 if (referenceResolution.dependency != 0) { | 858 if (referenceResolution.dependency != 0) { |
| 808 PrelinkedDependency dependency = | 859 location = getReferencedLocation( |
| 809 prelinkedLibrary.dependencies[referenceResolution.dependency]; | 860 prelinkedLibrary.dependencies[referenceResolution.dependency], |
| 810 Source referencedLibrarySource = summaryResynthesizer.sourceFactory | 861 referenceResolution.unit, |
| 811 .resolveUri(librarySource, dependency.uri); | 862 reference.name); |
| 812 referencedLibraryUri = referencedLibrarySource.uri.toString(); | |
| 813 // TODO(paulberry): consider changing Location format so that this is | |
| 814 // not necessary (2nd string in location should just be the unit | |
| 815 // number). | |
| 816 if (referenceResolution.unit != 0) { | |
| 817 UnlinkedUnit referencedLibraryDefiningUnit = | |
| 818 summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri); | |
| 819 String uri = referencedLibraryDefiningUnit.publicNamespace.parts[ | |
| 820 referenceResolution.unit - 1]; | |
| 821 Source partSource = summaryResynthesizer.sourceFactory | |
| 822 .resolveUri(referencedLibrarySource, uri); | |
| 823 partUri = partSource.uri.toString(); | |
| 824 } else { | |
| 825 partUri = referencedLibraryUri; | |
| 826 } | |
| 827 } else if (referenceResolution.kind == | 863 } else if (referenceResolution.kind == |
| 828 PrelinkedReferenceKind.unresolved) { | 864 PrelinkedReferenceKind.unresolved) { |
| 829 return summaryResynthesizer.typeProvider.undefinedType; | 865 return summaryResynthesizer.typeProvider.undefinedType; |
| 830 } else if (reference.name.isEmpty) { | 866 } else if (reference.name.isEmpty) { |
| 831 return summaryResynthesizer.typeProvider.dynamicType; | 867 return summaryResynthesizer.typeProvider.dynamicType; |
| 832 } else { | 868 } else { |
| 833 referencedLibraryUri = librarySource.uri.toString(); | 869 String referencedLibraryUri = librarySource.uri.toString(); |
| 870 String partUri; | |
| 834 if (referenceResolution.unit != 0) { | 871 if (referenceResolution.unit != 0) { |
| 835 String uri = unlinkedUnits[0].publicNamespace.parts[ | 872 String uri = unlinkedUnits[0].publicNamespace.parts[ |
| 836 referenceResolution.unit - 1]; | 873 referenceResolution.unit - 1]; |
| 837 Source partSource = | 874 Source partSource = |
| 838 summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri); | 875 summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri); |
| 839 partUri = partSource.uri.toString(); | 876 partUri = partSource.uri.toString(); |
| 840 } else { | 877 } else { |
| 841 partUri = referencedLibraryUri; | 878 partUri = referencedLibraryUri; |
| 842 } | 879 } |
| 880 location = new ElementLocationImpl.con3( | |
| 881 <String>[referencedLibraryUri, partUri, reference.name]); | |
| 843 } | 882 } |
| 844 ElementLocationImpl location = new ElementLocationImpl.con3( | |
| 845 <String>[referencedLibraryUri, partUri, reference.name]); | |
| 846 List<DartType> typeArguments = const <DartType>[]; | 883 List<DartType> typeArguments = const <DartType>[]; |
| 847 if (referenceResolution.numTypeParameters != 0) { | 884 if (referenceResolution.numTypeParameters != 0) { |
| 848 typeArguments = <DartType>[]; | 885 typeArguments = <DartType>[]; |
| 849 for (int i = 0; i < referenceResolution.numTypeParameters; i++) { | 886 for (int i = 0; i < referenceResolution.numTypeParameters; i++) { |
| 850 if (i < type.typeArguments.length) { | 887 if (i < type.typeArguments.length) { |
| 851 typeArguments.add(buildType(type.typeArguments[i])); | 888 typeArguments.add(buildType(type.typeArguments[i])); |
| 852 } else { | 889 } else { |
| 853 typeArguments.add(summaryResynthesizer.typeProvider.dynamicType); | 890 typeArguments.add(summaryResynthesizer.typeProvider.dynamicType); |
| 854 } | 891 } |
| 855 } | 892 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 963 * Finish creating a [TypeParameterElement] by deserializing its bound. | 1000 * Finish creating a [TypeParameterElement] by deserializing its bound. |
| 964 */ | 1001 */ |
| 965 void finishTypeParameter(UnlinkedTypeParam serializedTypeParameter, | 1002 void finishTypeParameter(UnlinkedTypeParam serializedTypeParameter, |
| 966 TypeParameterElementImpl typeParameterElement) { | 1003 TypeParameterElementImpl typeParameterElement) { |
| 967 if (serializedTypeParameter.bound != null) { | 1004 if (serializedTypeParameter.bound != null) { |
| 968 typeParameterElement.bound = buildType(serializedTypeParameter.bound); | 1005 typeParameterElement.bound = buildType(serializedTypeParameter.bound); |
| 969 } | 1006 } |
| 970 } | 1007 } |
| 971 | 1008 |
| 972 /** | 1009 /** |
| 1010 * Build an [ElementLocationImpl] for the entity in the given [unit] of the | |
| 1011 * given [dependency], having the given [name]. | |
| 1012 */ | |
| 1013 ElementLocationImpl getReferencedLocation( | |
| 1014 PrelinkedDependency dependency, int unit, String name) { | |
| 1015 Source referencedLibrarySource = summaryResynthesizer.sourceFactory | |
| 1016 .resolveUri(librarySource, dependency.uri); | |
| 1017 String referencedLibraryUri = referencedLibrarySource.uri.toString(); | |
| 1018 // TODO(paulberry): consider changing Location format so that this is | |
| 1019 // not necessary (2nd string in location should just be the unit | |
| 1020 // number). | |
| 1021 String partUri; | |
| 1022 if (unit != 0) { | |
| 1023 UnlinkedUnit referencedLibraryDefiningUnit = | |
| 1024 summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri); | |
| 1025 String uri = | |
| 1026 referencedLibraryDefiningUnit.publicNamespace.parts[unit - 1]; | |
| 1027 Source partSource = summaryResynthesizer.sourceFactory | |
| 1028 .resolveUri(referencedLibrarySource, uri); | |
| 1029 partUri = partSource.uri.toString(); | |
| 1030 } else { | |
| 1031 partUri = referencedLibraryUri; | |
| 1032 } | |
| 1033 return new ElementLocationImpl.con3( | |
| 1034 <String>[referencedLibraryUri, partUri, name]); | |
| 1035 } | |
| 1036 | |
| 1037 /** | |
| 973 * Populate a [CompilationUnitElement] by deserializing all the elements | 1038 * Populate a [CompilationUnitElement] by deserializing all the elements |
| 974 * contained in it. | 1039 * contained in it. |
| 975 */ | 1040 */ |
| 976 void populateUnit(CompilationUnitElementImpl unit, int unitNum) { | 1041 void populateUnit(CompilationUnitElementImpl unit, int unitNum) { |
| 977 prelinkedUnit = prelinkedLibrary.units[unitNum]; | 1042 prelinkedUnit = prelinkedLibrary.units[unitNum]; |
| 978 unlinkedUnit = unlinkedUnits[unitNum]; | 1043 unlinkedUnit = unlinkedUnits[unitNum]; |
| 979 unitHolder = new ElementHolder(); | 1044 unitHolder = new ElementHolder(); |
| 980 unlinkedUnit.classes.forEach(buildClass); | 1045 unlinkedUnit.classes.forEach(buildClass); |
| 981 unlinkedUnit.enums.forEach(buildEnum); | 1046 unlinkedUnit.enums.forEach(buildEnum); |
| 982 unlinkedUnit.executables.forEach(buildExecutable); | 1047 unlinkedUnit.executables.forEach(buildExecutable); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 998 Map<String, Element> elementMap = <String, Element>{}; | 1063 Map<String, Element> elementMap = <String, Element>{}; |
| 999 for (ClassElement cls in unit.types) { | 1064 for (ClassElement cls in unit.types) { |
| 1000 elementMap[cls.name] = cls; | 1065 elementMap[cls.name] = cls; |
| 1001 } | 1066 } |
| 1002 for (ClassElement cls in unit.enums) { | 1067 for (ClassElement cls in unit.enums) { |
| 1003 elementMap[cls.name] = cls; | 1068 elementMap[cls.name] = cls; |
| 1004 } | 1069 } |
| 1005 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { | 1070 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { |
| 1006 elementMap[typeAlias.name] = typeAlias; | 1071 elementMap[typeAlias.name] = typeAlias; |
| 1007 } | 1072 } |
| 1073 for (FunctionElement function in unit.functions) { | |
| 1074 elementMap[function.name] = function; | |
| 1075 } | |
| 1076 for (PropertyAccessorElementImpl accessor in unit.accessors) { | |
| 1077 elementMap[accessor.identifier] = accessor; | |
| 1078 } | |
| 1008 resummarizedElements[absoluteUri] = elementMap; | 1079 resummarizedElements[absoluteUri] = elementMap; |
| 1009 unitHolder = null; | 1080 unitHolder = null; |
| 1010 prelinkedUnit = null; | 1081 prelinkedUnit = null; |
| 1011 unlinkedUnit = null; | 1082 unlinkedUnit = null; |
| 1012 } | 1083 } |
| 1013 } | 1084 } |
| OLD | NEW |