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 '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 List<ClassElementImpl> delayedObjectSubclasses = <ClassElementImpl>[]; | |
|
Paul Berry
2015/12/24 03:31:09
Please add a doc comment for this field. Perhaps
scheglov
2015/12/24 03:36:06
Done.
| |
| 232 | |
| 233 /** | |
| 231 * [ElementHolder] into which resynthesized elements should be placed. This | 234 * [ElementHolder] into which resynthesized elements should be placed. This |
| 232 * object is recreated afresh for each unit in the library, and is used to | 235 * object is recreated afresh for each unit in the library, and is used to |
| 233 * populate the [CompilationUnitElement]. | 236 * populate the [CompilationUnitElement]. |
| 234 */ | 237 */ |
| 235 ElementHolder unitHolder; | 238 ElementHolder unitHolder; |
| 236 | 239 |
| 237 /** | 240 /** |
| 238 * The [PrelinkedUnit] from which elements are currently being resynthesized. | 241 * The [PrelinkedUnit] from which elements are currently being resynthesized. |
| 239 */ | 242 */ |
| 240 PrelinkedUnit prelinkedUnit; | 243 PrelinkedUnit prelinkedUnit; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 253 <String, Map<String, Element>>{}; | 256 <String, Map<String, Element>>{}; |
| 254 | 257 |
| 255 /** | 258 /** |
| 256 * Type parameters for the class or typedef currently being resynthesized. | 259 * Type parameters for the class or typedef currently being resynthesized. |
| 257 * | 260 * |
| 258 * TODO(paulberry): extend this to do the right thing for generic methods. | 261 * TODO(paulberry): extend this to do the right thing for generic methods. |
| 259 */ | 262 */ |
| 260 List<TypeParameterElement> currentTypeParameters; | 263 List<TypeParameterElement> currentTypeParameters; |
| 261 | 264 |
| 262 _LibraryResynthesizer(this.summaryResynthesizer, this.prelinkedLibrary, | 265 _LibraryResynthesizer(this.summaryResynthesizer, this.prelinkedLibrary, |
| 263 this.unlinkedUnits, this.librarySource); | 266 this.unlinkedUnits, this.librarySource) { |
| 267 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; | |
| 268 } | |
| 264 | 269 |
| 265 /** | 270 /** |
| 266 * Resynthesize a [ClassElement] and place it in [unitHolder]. | 271 * Resynthesize a [ClassElement] and place it in [unitHolder]. |
| 267 */ | 272 */ |
| 268 void buildClass(UnlinkedClass serializedClass) { | 273 void buildClass(UnlinkedClass serializedClass) { |
| 269 try { | 274 try { |
| 270 currentTypeParameters = | 275 currentTypeParameters = |
| 271 serializedClass.typeParameters.map(buildTypeParameter).toList(); | 276 serializedClass.typeParameters.map(buildTypeParameter).toList(); |
| 272 for (int i = 0; i < serializedClass.typeParameters.length; i++) { | 277 for (int i = 0; i < serializedClass.typeParameters.length; i++) { |
| 273 finishTypeParameter( | 278 finishTypeParameter( |
| 274 serializedClass.typeParameters[i], currentTypeParameters[i]); | 279 serializedClass.typeParameters[i], currentTypeParameters[i]); |
| 275 } | 280 } |
| 276 ClassElementImpl classElement = | 281 ClassElementImpl classElement = |
| 277 new ClassElementImpl(serializedClass.name, -1); | 282 new ClassElementImpl(serializedClass.name, -1); |
| 278 classElement.mixinApplication = serializedClass.isMixinApplication; | 283 classElement.mixinApplication = serializedClass.isMixinApplication; |
| 279 InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement); | 284 InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement); |
| 280 if (serializedClass.supertype != null) { | 285 if (serializedClass.supertype != null) { |
| 281 classElement.supertype = buildType(serializedClass.supertype); | 286 classElement.supertype = buildType(serializedClass.supertype); |
| 282 } else if (!serializedClass.hasNoSupertype) { | 287 } else if (!serializedClass.hasNoSupertype) { |
| 283 classElement.supertype = summaryResynthesizer.typeProvider.objectType; | 288 if (isCoreLibrary) { |
| 289 delayedObjectSubclasses.add(classElement); | |
| 290 } else { | |
| 291 classElement.supertype = summaryResynthesizer.typeProvider.objectType; | |
| 292 } | |
| 284 } | 293 } |
| 285 classElement.interfaces = | 294 classElement.interfaces = |
| 286 serializedClass.interfaces.map(buildType).toList(); | 295 serializedClass.interfaces.map(buildType).toList(); |
| 287 classElement.mixins = serializedClass.mixins.map(buildType).toList(); | 296 classElement.mixins = serializedClass.mixins.map(buildType).toList(); |
| 288 classElement.typeParameters = currentTypeParameters; | 297 classElement.typeParameters = currentTypeParameters; |
| 289 ElementHolder memberHolder = new ElementHolder(); | 298 ElementHolder memberHolder = new ElementHolder(); |
| 290 bool constructorFound = false; | 299 bool constructorFound = false; |
| 291 for (UnlinkedExecutable serializedExecutable | 300 for (UnlinkedExecutable serializedExecutable |
| 292 in serializedClass.executables) { | 301 in serializedClass.executables) { |
| 293 switch (serializedExecutable.kind) { | 302 switch (serializedExecutable.kind) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 constructorElement.factory = serializedExecutable.isFactory; | 369 constructorElement.factory = serializedExecutable.isFactory; |
| 361 constructorElement.const2 = serializedExecutable.isConst; | 370 constructorElement.const2 = serializedExecutable.isConst; |
| 362 holder.addConstructor(constructorElement); | 371 holder.addConstructor(constructorElement); |
| 363 } | 372 } |
| 364 | 373 |
| 365 /** | 374 /** |
| 366 * Resynthesize the [ClassElement] corresponding to an enum, along with the | 375 * Resynthesize the [ClassElement] corresponding to an enum, along with the |
| 367 * associated fields and implicit accessors. | 376 * associated fields and implicit accessors. |
| 368 */ | 377 */ |
| 369 void buildEnum(UnlinkedEnum serializedEnum) { | 378 void buildEnum(UnlinkedEnum serializedEnum) { |
| 379 assert(!isCoreLibrary); | |
| 370 // TODO(paulberry): add offset support (for this element type and others) | 380 // TODO(paulberry): add offset support (for this element type and others) |
| 371 ClassElementImpl classElement = | 381 ClassElementImpl classElement = |
| 372 new ClassElementImpl(serializedEnum.name, -1); | 382 new ClassElementImpl(serializedEnum.name, -1); |
| 373 classElement.enum2 = true; | 383 classElement.enum2 = true; |
| 374 InterfaceType enumType = new InterfaceTypeImpl(classElement); | 384 InterfaceType enumType = new InterfaceTypeImpl(classElement); |
| 375 classElement.type = enumType; | 385 classElement.type = enumType; |
| 376 classElement.supertype = summaryResynthesizer.typeProvider.objectType; | 386 classElement.supertype = summaryResynthesizer.typeProvider.objectType; |
| 377 ElementHolder memberHolder = new ElementHolder(); | 387 ElementHolder memberHolder = new ElementHolder(); |
| 378 FieldElementImpl indexField = new FieldElementImpl('index', -1); | 388 FieldElementImpl indexField = new FieldElementImpl('index', -1); |
| 379 indexField.final2 = true; | 389 indexField.final2 = true; |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 565 element.setter = setter; | 575 element.setter = setter; |
| 566 } | 576 } |
| 567 } | 577 } |
| 568 | 578 |
| 569 /** | 579 /** |
| 570 * Build the implicit field associated with a getter or setter, and place it | 580 * Build the implicit field associated with a getter or setter, and place it |
| 571 * in [holder]. | 581 * in [holder]. |
| 572 */ | 582 */ |
| 573 FieldElementImpl buildImplicitField(String name, DartType type, | 583 FieldElementImpl buildImplicitField(String name, DartType type, |
| 574 UnlinkedExecutableKind kind, ElementHolder holder) { | 584 UnlinkedExecutableKind kind, ElementHolder holder) { |
| 575 if (holder.getField(name) == null) { | 585 FieldElementImpl field = holder.getField(name); |
| 576 FieldElementImpl field = new FieldElementImpl(name, -1); | 586 if (field == null) { |
| 587 field = new FieldElementImpl(name, -1); | |
| 577 field.synthetic = true; | 588 field.synthetic = true; |
| 578 field.final2 = kind == UnlinkedExecutableKind.getter; | 589 field.final2 = kind == UnlinkedExecutableKind.getter; |
| 579 field.type = type; | 590 field.type = type; |
| 580 holder.addField(field); | 591 holder.addField(field); |
| 581 return field; | 592 return field; |
| 582 } else { | 593 } 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? | 594 // TODO(paulberry): what if the getter and setter have a type mismatch? |
| 586 throw new UnimplementedError(); | 595 field.final2 = false; |
| 596 return field; | |
| 587 } | 597 } |
| 588 } | 598 } |
| 589 | 599 |
| 590 /** | 600 /** |
| 591 * Build the implicit top level variable associated with a getter or setter, | 601 * Build the implicit top level variable associated with a getter or setter, |
| 592 * and place it in [holder]. | 602 * and place it in [holder]. |
| 593 */ | 603 */ |
| 594 PropertyInducingElementImpl buildImplicitTopLevelVariable( | 604 PropertyInducingElementImpl buildImplicitTopLevelVariable( |
| 595 String name, UnlinkedExecutableKind kind, ElementHolder holder) { | 605 String name, UnlinkedExecutableKind kind, ElementHolder holder) { |
| 596 if (holder.getTopLevelVariable(name) == null) { | 606 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], | 677 imports.add(buildImport(unlinkedDefiningUnit.imports[i], |
| 668 prelinkedLibrary.importDependencies[i])); | 678 prelinkedLibrary.importDependencies[i])); |
| 669 } | 679 } |
| 670 libraryElement.imports = imports; | 680 libraryElement.imports = imports; |
| 671 libraryElement.exports = | 681 libraryElement.exports = |
| 672 unlinkedDefiningUnit.exports.map(buildExport).toList(); | 682 unlinkedDefiningUnit.exports.map(buildExport).toList(); |
| 673 populateUnit(definingCompilationUnit, 0); | 683 populateUnit(definingCompilationUnit, 0); |
| 674 for (int i = 0; i < parts.length; i++) { | 684 for (int i = 0; i < parts.length; i++) { |
| 675 populateUnit(parts[i], i + 1); | 685 populateUnit(parts[i], i + 1); |
| 676 } | 686 } |
| 687 if (isCoreLibrary) { | |
| 688 ClassElement objectElement = libraryElement.getType('Object'); | |
| 689 assert(objectElement != null); | |
| 690 for (ClassElementImpl classElement in delayedObjectSubclasses) { | |
| 691 classElement.supertype = objectElement.type; | |
| 692 } | |
| 693 } | |
| 677 return libraryElement; | 694 return libraryElement; |
| 678 } | 695 } |
| 679 | 696 |
| 680 /** | 697 /** |
| 681 * Resynthesize a [ParameterElement]. | 698 * Resynthesize a [ParameterElement]. |
| 682 */ | 699 */ |
| 683 ParameterElement buildParameter(UnlinkedParam serializedParameter) { | 700 ParameterElement buildParameter(UnlinkedParam serializedParameter) { |
| 684 ParameterElementImpl parameterElement = | 701 ParameterElementImpl parameterElement = |
| 685 new ParameterElementImpl(serializedParameter.name, -1); | 702 new ParameterElementImpl(serializedParameter.name, -1); |
| 686 if (serializedParameter.isFunctionTyped) { | 703 if (serializedParameter.isFunctionTyped) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 734 /** | 751 /** |
| 735 * Build a [DartType] object based on an [UnlinkedTypeRef]. This [DartType] | 752 * Build a [DartType] object based on an [UnlinkedTypeRef]. This [DartType] |
| 736 * may refer to elements in other libraries than the library being | 753 * may refer to elements in other libraries than the library being |
| 737 * deserialized, so handles are used to avoid having to deserialize other | 754 * deserialized, so handles are used to avoid having to deserialize other |
| 738 * libraries in the process. | 755 * libraries in the process. |
| 739 */ | 756 */ |
| 740 DartType buildType(UnlinkedTypeRef type) { | 757 DartType buildType(UnlinkedTypeRef type) { |
| 741 if (type.paramReference != 0) { | 758 if (type.paramReference != 0) { |
| 742 // TODO(paulberry): make this work for generic methods. | 759 // TODO(paulberry): make this work for generic methods. |
| 743 return currentTypeParameters[ | 760 return currentTypeParameters[ |
| 744 currentTypeParameters.length - type.paramReference].type; | 761 currentTypeParameters.length - type.paramReference] |
| 762 .type; | |
| 745 } else { | 763 } else { |
| 746 // TODO(paulberry): handle references to things other than classes (note: | 764 // TODO(paulberry): handle references to things other than classes (note: |
| 747 // this should only occur in the case of erroneous code). | 765 // this should only occur in the case of erroneous code). |
| 748 // TODO(paulberry): test reference to something inside a part. | 766 // TODO(paulberry): test reference to something inside a part. |
| 749 // TODO(paulberry): test reference to something inside a part of the | 767 // TODO(paulberry): test reference to something inside a part of the |
| 750 // current lib. | 768 // current lib. |
| 751 UnlinkedReference reference = unlinkedUnit.references[type.reference]; | 769 UnlinkedReference reference = unlinkedUnit.references[type.reference]; |
| 752 PrelinkedReference referenceResolution = | 770 PrelinkedReference referenceResolution = |
| 753 prelinkedUnit.references[type.reference]; | 771 prelinkedUnit.references[type.reference]; |
| 754 String referencedLibraryUri; | 772 String referencedLibraryUri; |
| 755 String partUri; | 773 String partUri; |
| 756 if (referenceResolution.dependency != 0) { | 774 if (referenceResolution.dependency != 0) { |
| 757 PrelinkedDependency dependency = | 775 PrelinkedDependency dependency = |
| 758 prelinkedLibrary.dependencies[referenceResolution.dependency]; | 776 prelinkedLibrary.dependencies[referenceResolution.dependency]; |
| 759 Source referencedLibrarySource = summaryResynthesizer.sourceFactory | 777 Source referencedLibrarySource = summaryResynthesizer.sourceFactory |
| 760 .resolveUri(librarySource, dependency.uri); | 778 .resolveUri(librarySource, dependency.uri); |
| 761 referencedLibraryUri = referencedLibrarySource.uri.toString(); | 779 referencedLibraryUri = referencedLibrarySource.uri.toString(); |
| 762 // TODO(paulberry): consider changing Location format so that this is | 780 // TODO(paulberry): consider changing Location format so that this is |
| 763 // not necessary (2nd string in location should just be the unit | 781 // not necessary (2nd string in location should just be the unit |
| 764 // number). | 782 // number). |
| 765 if (referenceResolution.unit != 0) { | 783 if (referenceResolution.unit != 0) { |
| 766 UnlinkedUnit referencedLibraryDefiningUnit = | 784 UnlinkedUnit referencedLibraryDefiningUnit = |
| 767 summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri); | 785 summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri); |
| 768 String uri = referencedLibraryDefiningUnit.parts[0].uri; | 786 String uri = referencedLibraryDefiningUnit |
| 787 .parts[referenceResolution.unit - 1].uri; | |
| 769 Source partSource = summaryResynthesizer.sourceFactory | 788 Source partSource = summaryResynthesizer.sourceFactory |
| 770 .resolveUri(referencedLibrarySource, uri); | 789 .resolveUri(referencedLibrarySource, uri); |
| 771 partUri = partSource.uri.toString(); | 790 partUri = partSource.uri.toString(); |
| 772 } else { | 791 } else { |
| 773 partUri = referencedLibraryUri; | 792 partUri = referencedLibraryUri; |
| 774 } | 793 } |
| 775 } else if (referenceResolution.kind == | 794 } else if (referenceResolution.kind == |
| 776 PrelinkedReferenceKind.unresolved) { | 795 PrelinkedReferenceKind.unresolved) { |
| 777 return summaryResynthesizer.typeProvider.undefinedType; | 796 return summaryResynthesizer.typeProvider.undefinedType; |
| 778 } else if (reference.name.isEmpty) { | 797 } else if (reference.name.isEmpty) { |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 940 } | 959 } |
| 941 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { | 960 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { |
| 942 elementMap[typeAlias.name] = typeAlias; | 961 elementMap[typeAlias.name] = typeAlias; |
| 943 } | 962 } |
| 944 resummarizedElements[absoluteUri] = elementMap; | 963 resummarizedElements[absoluteUri] = elementMap; |
| 945 unitHolder = null; | 964 unitHolder = null; |
| 946 prelinkedUnit = null; | 965 prelinkedUnit = null; |
| 947 unlinkedUnit = null; | 966 unlinkedUnit = null; |
| 948 } | 967 } |
| 949 } | 968 } |
| OLD | NEW |