| 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 'package:analyzer/analyzer.dart'; | 7 import 'package:analyzer/analyzer.dart'; |
| 8 import 'package:analyzer/src/generated/element.dart'; | 8 import 'package:analyzer/src/generated/element.dart'; |
| 9 import 'package:analyzer/src/generated/element_handle.dart'; | 9 import 'package:analyzer/src/generated/element_handle.dart'; |
| 10 import 'package:analyzer/src/generated/engine.dart'; | 10 import 'package:analyzer/src/generated/engine.dart'; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 final SourceFactory sourceFactory; | 105 final SourceFactory sourceFactory; |
| 106 | 106 |
| 107 /** | 107 /** |
| 108 * Cache of [Source] objects that have already been converted from URIs. | 108 * Cache of [Source] objects that have already been converted from URIs. |
| 109 */ | 109 */ |
| 110 final Map<String, Source> _sources = <String, Source>{}; | 110 final Map<String, Source> _sources = <String, Source>{}; |
| 111 | 111 |
| 112 /** | 112 /** |
| 113 * The [TypeProvider] used to obtain core types (such as Object, int, List, | 113 * The [TypeProvider] used to obtain core types (such as Object, int, List, |
| 114 * and dynamic) during resynthesis. | 114 * and dynamic) during resynthesis. |
| 115 * | |
| 116 * TODO(paulberry): will this create a chicken-and-egg problem when trying to | |
| 117 * resynthesize the core library from summaries? | |
| 118 */ | 115 */ |
| 119 final TypeProvider typeProvider; | 116 final TypeProvider typeProvider; |
| 120 | 117 |
| 121 /** | 118 /** |
| 122 * Map of top level elements resynthesized from summaries. The three map | 119 * Map of top level elements resynthesized from summaries. The three map |
| 123 * keys are the first three elements of the element's location (the library | 120 * keys are the first three elements of the element's location (the library |
| 124 * URI, the compilation unit URI, and the name of the top level declaration). | 121 * URI, the compilation unit URI, and the name of the top level declaration). |
| 125 */ | 122 */ |
| 126 final Map<String, Map<String, Map<String, Element>>> _resynthesizedElements = | 123 final Map<String, Map<String, Map<String, Element>>> _resynthesizedElements = |
| 127 <String, Map<String, Map<String, Element>>>{}; | 124 <String, Map<String, Map<String, Element>>>{}; |
| 128 | 125 |
| 129 /** | 126 /** |
| 130 * Map of libraries which have been resynthesized from summaries. The map | 127 * Map of libraries which have been resynthesized from summaries. The map |
| 131 * key is the library URI. | 128 * key is the library URI. |
| 132 */ | 129 */ |
| 133 final Map<String, LibraryElement> _resynthesizedLibraries = | 130 final Map<String, LibraryElement> _resynthesizedLibraries = |
| 134 <String, LibraryElement>{}; | 131 <String, LibraryElement>{}; |
| 135 | 132 |
| 136 SummaryResynthesizer(AnalysisContext context, this.getPrelinkedSummary, | 133 SummaryResynthesizer(AnalysisContext context, this.typeProvider, |
| 137 this.getUnlinkedSummary, this.sourceFactory) | 134 this.getPrelinkedSummary, this.getUnlinkedSummary, this.sourceFactory) |
| 138 : super(context), | 135 : super(context); |
| 139 typeProvider = context.typeProvider; | |
| 140 | 136 |
| 141 /** | 137 /** |
| 142 * Number of libraries that have been resynthesized so far. | 138 * Number of libraries that have been resynthesized so far. |
| 143 */ | 139 */ |
| 144 int get resynthesisCount => _resynthesizedLibraries.length; | 140 int get resynthesisCount => _resynthesizedLibraries.length; |
| 145 | 141 |
| 146 @override | 142 @override |
| 147 Element getElement(ElementLocation location) { | 143 Element getElement(ElementLocation location) { |
| 148 if (location.components.length == 1) { | 144 if (location.components.length == 1) { |
| 149 return getLibraryElement(location.components[0]); | 145 return getLibraryElement(location.components[0]); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 * Unlinked compilation units constituting the library to be resynthesized. | 217 * Unlinked compilation units constituting the library to be resynthesized. |
| 222 */ | 218 */ |
| 223 final List<UnlinkedUnit> unlinkedUnits; | 219 final List<UnlinkedUnit> unlinkedUnits; |
| 224 | 220 |
| 225 /** | 221 /** |
| 226 * [Source] object for the library to be resynthesized. | 222 * [Source] object for the library to be resynthesized. |
| 227 */ | 223 */ |
| 228 final Source librarySource; | 224 final Source librarySource; |
| 229 | 225 |
| 230 /** | 226 /** |
| 227 * Indicates whether [librarySource] is the `dart:core` library. |
| 228 */ |
| 229 bool isCoreLibrary; |
| 230 |
| 231 /** |
| 232 * Classes which should have their supertype set to "object" once |
| 233 * resynthesis is complete. Only used if [isCoreLibrary] is `true`. |
| 234 */ |
| 235 List<ClassElementImpl> delayedObjectSubclasses = <ClassElementImpl>[]; |
| 236 |
| 237 /** |
| 231 * [ElementHolder] into which resynthesized elements should be placed. This | 238 * [ElementHolder] into which resynthesized elements should be placed. This |
| 232 * object is recreated afresh for each unit in the library, and is used to | 239 * object is recreated afresh for each unit in the library, and is used to |
| 233 * populate the [CompilationUnitElement]. | 240 * populate the [CompilationUnitElement]. |
| 234 */ | 241 */ |
| 235 ElementHolder unitHolder; | 242 ElementHolder unitHolder; |
| 236 | 243 |
| 237 /** | 244 /** |
| 238 * The [PrelinkedUnit] from which elements are currently being resynthesized. | 245 * The [PrelinkedUnit] from which elements are currently being resynthesized. |
| 239 */ | 246 */ |
| 240 PrelinkedUnit prelinkedUnit; | 247 PrelinkedUnit prelinkedUnit; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 253 <String, Map<String, Element>>{}; | 260 <String, Map<String, Element>>{}; |
| 254 | 261 |
| 255 /** | 262 /** |
| 256 * Type parameters for the class or typedef currently being resynthesized. | 263 * Type parameters for the class or typedef currently being resynthesized. |
| 257 * | 264 * |
| 258 * TODO(paulberry): extend this to do the right thing for generic methods. | 265 * TODO(paulberry): extend this to do the right thing for generic methods. |
| 259 */ | 266 */ |
| 260 List<TypeParameterElement> currentTypeParameters; | 267 List<TypeParameterElement> currentTypeParameters; |
| 261 | 268 |
| 262 _LibraryResynthesizer(this.summaryResynthesizer, this.prelinkedLibrary, | 269 _LibraryResynthesizer(this.summaryResynthesizer, this.prelinkedLibrary, |
| 263 this.unlinkedUnits, this.librarySource); | 270 this.unlinkedUnits, this.librarySource) { |
| 271 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; |
| 272 } |
| 264 | 273 |
| 265 /** | 274 /** |
| 266 * Resynthesize a [ClassElement] and place it in [unitHolder]. | 275 * Resynthesize a [ClassElement] and place it in [unitHolder]. |
| 267 */ | 276 */ |
| 268 void buildClass(UnlinkedClass serializedClass) { | 277 void buildClass(UnlinkedClass serializedClass) { |
| 269 try { | 278 try { |
| 270 currentTypeParameters = | 279 currentTypeParameters = |
| 271 serializedClass.typeParameters.map(buildTypeParameter).toList(); | 280 serializedClass.typeParameters.map(buildTypeParameter).toList(); |
| 272 for (int i = 0; i < serializedClass.typeParameters.length; i++) { | 281 for (int i = 0; i < serializedClass.typeParameters.length; i++) { |
| 273 finishTypeParameter( | 282 finishTypeParameter( |
| 274 serializedClass.typeParameters[i], currentTypeParameters[i]); | 283 serializedClass.typeParameters[i], currentTypeParameters[i]); |
| 275 } | 284 } |
| 276 ClassElementImpl classElement = | 285 ClassElementImpl classElement = |
| 277 new ClassElementImpl(serializedClass.name, -1); | 286 new ClassElementImpl(serializedClass.name, -1); |
| 278 classElement.mixinApplication = serializedClass.isMixinApplication; | 287 classElement.mixinApplication = serializedClass.isMixinApplication; |
| 279 InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement); | 288 InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement); |
| 280 if (serializedClass.supertype != null) { | 289 if (serializedClass.supertype != null) { |
| 281 classElement.supertype = buildType(serializedClass.supertype); | 290 classElement.supertype = buildType(serializedClass.supertype); |
| 282 } else if (!serializedClass.hasNoSupertype) { | 291 } else if (!serializedClass.hasNoSupertype) { |
| 283 classElement.supertype = summaryResynthesizer.typeProvider.objectType; | 292 if (isCoreLibrary) { |
| 293 delayedObjectSubclasses.add(classElement); |
| 294 } else { |
| 295 classElement.supertype = summaryResynthesizer.typeProvider.objectType; |
| 296 } |
| 284 } | 297 } |
| 285 classElement.interfaces = | 298 classElement.interfaces = |
| 286 serializedClass.interfaces.map(buildType).toList(); | 299 serializedClass.interfaces.map(buildType).toList(); |
| 287 classElement.mixins = serializedClass.mixins.map(buildType).toList(); | 300 classElement.mixins = serializedClass.mixins.map(buildType).toList(); |
| 288 classElement.typeParameters = currentTypeParameters; | 301 classElement.typeParameters = currentTypeParameters; |
| 289 ElementHolder memberHolder = new ElementHolder(); | 302 ElementHolder memberHolder = new ElementHolder(); |
| 290 bool constructorFound = false; | 303 bool constructorFound = false; |
| 291 for (UnlinkedExecutable serializedExecutable | 304 for (UnlinkedExecutable serializedExecutable |
| 292 in serializedClass.executables) { | 305 in serializedClass.executables) { |
| 293 switch (serializedExecutable.kind) { | 306 switch (serializedExecutable.kind) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 constructorElement.factory = serializedExecutable.isFactory; | 373 constructorElement.factory = serializedExecutable.isFactory; |
| 361 constructorElement.const2 = serializedExecutable.isConst; | 374 constructorElement.const2 = serializedExecutable.isConst; |
| 362 holder.addConstructor(constructorElement); | 375 holder.addConstructor(constructorElement); |
| 363 } | 376 } |
| 364 | 377 |
| 365 /** | 378 /** |
| 366 * Resynthesize the [ClassElement] corresponding to an enum, along with the | 379 * Resynthesize the [ClassElement] corresponding to an enum, along with the |
| 367 * associated fields and implicit accessors. | 380 * associated fields and implicit accessors. |
| 368 */ | 381 */ |
| 369 void buildEnum(UnlinkedEnum serializedEnum) { | 382 void buildEnum(UnlinkedEnum serializedEnum) { |
| 383 assert(!isCoreLibrary); |
| 370 // TODO(paulberry): add offset support (for this element type and others) | 384 // TODO(paulberry): add offset support (for this element type and others) |
| 371 ClassElementImpl classElement = | 385 ClassElementImpl classElement = |
| 372 new ClassElementImpl(serializedEnum.name, -1); | 386 new ClassElementImpl(serializedEnum.name, -1); |
| 373 classElement.enum2 = true; | 387 classElement.enum2 = true; |
| 374 InterfaceType enumType = new InterfaceTypeImpl(classElement); | 388 InterfaceType enumType = new InterfaceTypeImpl(classElement); |
| 375 classElement.type = enumType; | 389 classElement.type = enumType; |
| 376 classElement.supertype = summaryResynthesizer.typeProvider.objectType; | 390 classElement.supertype = summaryResynthesizer.typeProvider.objectType; |
| 377 ElementHolder memberHolder = new ElementHolder(); | 391 ElementHolder memberHolder = new ElementHolder(); |
| 378 FieldElementImpl indexField = new FieldElementImpl('index', -1); | 392 FieldElementImpl indexField = new FieldElementImpl('index', -1); |
| 379 indexField.final2 = true; | 393 indexField.final2 = true; |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 element.setter = setter; | 579 element.setter = setter; |
| 566 } | 580 } |
| 567 } | 581 } |
| 568 | 582 |
| 569 /** | 583 /** |
| 570 * Build the implicit field associated with a getter or setter, and place it | 584 * Build the implicit field associated with a getter or setter, and place it |
| 571 * in [holder]. | 585 * in [holder]. |
| 572 */ | 586 */ |
| 573 FieldElementImpl buildImplicitField(String name, DartType type, | 587 FieldElementImpl buildImplicitField(String name, DartType type, |
| 574 UnlinkedExecutableKind kind, ElementHolder holder) { | 588 UnlinkedExecutableKind kind, ElementHolder holder) { |
| 575 if (holder.getField(name) == null) { | 589 FieldElementImpl field = holder.getField(name); |
| 576 FieldElementImpl field = new FieldElementImpl(name, -1); | 590 if (field == null) { |
| 591 field = new FieldElementImpl(name, -1); |
| 577 field.synthetic = true; | 592 field.synthetic = true; |
| 578 field.final2 = kind == UnlinkedExecutableKind.getter; | 593 field.final2 = kind == UnlinkedExecutableKind.getter; |
| 579 field.type = type; | 594 field.type = type; |
| 580 holder.addField(field); | 595 holder.addField(field); |
| 581 return field; | 596 return field; |
| 582 } else { | 597 } else { |
| 583 // TODO(paulberry): if adding a setter where there was previously | |
| 584 // only a getter, remove "final" modifier. | |
| 585 // TODO(paulberry): what if the getter and setter have a type mismatch? | 598 // TODO(paulberry): what if the getter and setter have a type mismatch? |
| 586 throw new UnimplementedError(); | 599 field.final2 = false; |
| 600 return field; |
| 587 } | 601 } |
| 588 } | 602 } |
| 589 | 603 |
| 590 /** | 604 /** |
| 591 * Build the implicit top level variable associated with a getter or setter, | 605 * Build the implicit top level variable associated with a getter or setter, |
| 592 * and place it in [holder]. | 606 * and place it in [holder]. |
| 593 */ | 607 */ |
| 594 PropertyInducingElementImpl buildImplicitTopLevelVariable( | 608 PropertyInducingElementImpl buildImplicitTopLevelVariable( |
| 595 String name, UnlinkedExecutableKind kind, ElementHolder holder) { | 609 String name, UnlinkedExecutableKind kind, ElementHolder holder) { |
| 596 if (holder.getTopLevelVariable(name) == null) { | 610 if (holder.getTopLevelVariable(name) == null) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 imports.add(buildImport(unlinkedDefiningUnit.imports[i], | 681 imports.add(buildImport(unlinkedDefiningUnit.imports[i], |
| 668 prelinkedLibrary.importDependencies[i])); | 682 prelinkedLibrary.importDependencies[i])); |
| 669 } | 683 } |
| 670 libraryElement.imports = imports; | 684 libraryElement.imports = imports; |
| 671 libraryElement.exports = | 685 libraryElement.exports = |
| 672 unlinkedDefiningUnit.exports.map(buildExport).toList(); | 686 unlinkedDefiningUnit.exports.map(buildExport).toList(); |
| 673 populateUnit(definingCompilationUnit, 0); | 687 populateUnit(definingCompilationUnit, 0); |
| 674 for (int i = 0; i < parts.length; i++) { | 688 for (int i = 0; i < parts.length; i++) { |
| 675 populateUnit(parts[i], i + 1); | 689 populateUnit(parts[i], i + 1); |
| 676 } | 690 } |
| 691 if (isCoreLibrary) { |
| 692 ClassElement objectElement = libraryElement.getType('Object'); |
| 693 assert(objectElement != null); |
| 694 for (ClassElementImpl classElement in delayedObjectSubclasses) { |
| 695 classElement.supertype = objectElement.type; |
| 696 } |
| 697 } |
| 677 return libraryElement; | 698 return libraryElement; |
| 678 } | 699 } |
| 679 | 700 |
| 680 /** | 701 /** |
| 681 * Resynthesize a [ParameterElement]. | 702 * Resynthesize a [ParameterElement]. |
| 682 */ | 703 */ |
| 683 ParameterElement buildParameter(UnlinkedParam serializedParameter) { | 704 ParameterElement buildParameter(UnlinkedParam serializedParameter) { |
| 684 ParameterElementImpl parameterElement = | 705 ParameterElementImpl parameterElement = |
| 685 new ParameterElementImpl(serializedParameter.name, -1); | 706 new ParameterElementImpl(serializedParameter.name, -1); |
| 686 if (serializedParameter.isFunctionTyped) { | 707 if (serializedParameter.isFunctionTyped) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 /** | 755 /** |
| 735 * Build a [DartType] object based on an [UnlinkedTypeRef]. This [DartType] | 756 * Build a [DartType] object based on an [UnlinkedTypeRef]. This [DartType] |
| 736 * may refer to elements in other libraries than the library being | 757 * may refer to elements in other libraries than the library being |
| 737 * deserialized, so handles are used to avoid having to deserialize other | 758 * deserialized, so handles are used to avoid having to deserialize other |
| 738 * libraries in the process. | 759 * libraries in the process. |
| 739 */ | 760 */ |
| 740 DartType buildType(UnlinkedTypeRef type) { | 761 DartType buildType(UnlinkedTypeRef type) { |
| 741 if (type.paramReference != 0) { | 762 if (type.paramReference != 0) { |
| 742 // TODO(paulberry): make this work for generic methods. | 763 // TODO(paulberry): make this work for generic methods. |
| 743 return currentTypeParameters[ | 764 return currentTypeParameters[ |
| 744 currentTypeParameters.length - type.paramReference].type; | 765 currentTypeParameters.length - type.paramReference] |
| 766 .type; |
| 745 } else { | 767 } else { |
| 746 // TODO(paulberry): handle references to things other than classes (note: | 768 // TODO(paulberry): handle references to things other than classes (note: |
| 747 // this should only occur in the case of erroneous code). | 769 // this should only occur in the case of erroneous code). |
| 748 // TODO(paulberry): test reference to something inside a part. | 770 // TODO(paulberry): test reference to something inside a part. |
| 749 // TODO(paulberry): test reference to something inside a part of the | 771 // TODO(paulberry): test reference to something inside a part of the |
| 750 // current lib. | 772 // current lib. |
| 751 UnlinkedReference reference = unlinkedUnit.references[type.reference]; | 773 UnlinkedReference reference = unlinkedUnit.references[type.reference]; |
| 752 PrelinkedReference referenceResolution = | 774 PrelinkedReference referenceResolution = |
| 753 prelinkedUnit.references[type.reference]; | 775 prelinkedUnit.references[type.reference]; |
| 754 String referencedLibraryUri; | 776 String referencedLibraryUri; |
| 755 String partUri; | 777 String partUri; |
| 756 if (referenceResolution.dependency != 0) { | 778 if (referenceResolution.dependency != 0) { |
| 757 PrelinkedDependency dependency = | 779 PrelinkedDependency dependency = |
| 758 prelinkedLibrary.dependencies[referenceResolution.dependency]; | 780 prelinkedLibrary.dependencies[referenceResolution.dependency]; |
| 759 Source referencedLibrarySource = summaryResynthesizer.sourceFactory | 781 Source referencedLibrarySource = summaryResynthesizer.sourceFactory |
| 760 .resolveUri(librarySource, dependency.uri); | 782 .resolveUri(librarySource, dependency.uri); |
| 761 referencedLibraryUri = referencedLibrarySource.uri.toString(); | 783 referencedLibraryUri = referencedLibrarySource.uri.toString(); |
| 762 // TODO(paulberry): consider changing Location format so that this is | 784 // TODO(paulberry): consider changing Location format so that this is |
| 763 // not necessary (2nd string in location should just be the unit | 785 // not necessary (2nd string in location should just be the unit |
| 764 // number). | 786 // number). |
| 765 if (referenceResolution.unit != 0) { | 787 if (referenceResolution.unit != 0) { |
| 766 UnlinkedUnit referencedLibraryDefiningUnit = | 788 UnlinkedUnit referencedLibraryDefiningUnit = |
| 767 summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri); | 789 summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri); |
| 768 String uri = referencedLibraryDefiningUnit.parts[0].uri; | 790 String uri = referencedLibraryDefiningUnit |
| 791 .parts[referenceResolution.unit - 1].uri; |
| 769 Source partSource = summaryResynthesizer.sourceFactory | 792 Source partSource = summaryResynthesizer.sourceFactory |
| 770 .resolveUri(referencedLibrarySource, uri); | 793 .resolveUri(referencedLibrarySource, uri); |
| 771 partUri = partSource.uri.toString(); | 794 partUri = partSource.uri.toString(); |
| 772 } else { | 795 } else { |
| 773 partUri = referencedLibraryUri; | 796 partUri = referencedLibraryUri; |
| 774 } | 797 } |
| 775 } else if (referenceResolution.kind == | 798 } else if (referenceResolution.kind == |
| 776 PrelinkedReferenceKind.unresolved) { | 799 PrelinkedReferenceKind.unresolved) { |
| 777 return summaryResynthesizer.typeProvider.undefinedType; | 800 return summaryResynthesizer.typeProvider.undefinedType; |
| 778 } else if (reference.name.isEmpty) { | 801 } else if (reference.name.isEmpty) { |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 } | 963 } |
| 941 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { | 964 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { |
| 942 elementMap[typeAlias.name] = typeAlias; | 965 elementMap[typeAlias.name] = typeAlias; |
| 943 } | 966 } |
| 944 resummarizedElements[absoluteUri] = elementMap; | 967 resummarizedElements[absoluteUri] = elementMap; |
| 945 unitHolder = null; | 968 unitHolder = null; |
| 946 prelinkedUnit = null; | 969 prelinkedUnit = null; |
| 947 unlinkedUnit = null; | 970 unlinkedUnit = null; |
| 948 } | 971 } |
| 949 } | 972 } |
| OLD | NEW |