| 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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 | 193 |
| 194 /** | 194 /** |
| 195 * Map of top level elements that have been resynthesized so far. The first | 195 * Map of top level elements that have been resynthesized so far. The first |
| 196 * key is the URI of the compilation unit; the second is the name of the top | 196 * key is the URI of the compilation unit; the second is the name of the top |
| 197 * level element. | 197 * level element. |
| 198 */ | 198 */ |
| 199 final Map<String, Map<String, Element>> resummarizedElements = | 199 final Map<String, Map<String, Element>> resummarizedElements = |
| 200 <String, Map<String, Element>>{}; | 200 <String, Map<String, Element>>{}; |
| 201 | 201 |
| 202 /** | 202 /** |
| 203 * Type parameters for the class or typedef currently being resynthesized. | 203 * Type parameters for the generic class, typedef, or executable currently |
| 204 * | 204 * being resynthesized, if any. If multiple entities with type parameters |
| 205 * TODO(paulberry): extend this to do the right thing for generic methods. | 205 * are nested (e.g. a generic executable inside a generic class), this is the |
| 206 * concatenation of all type parameters from all declarations currently in |
| 207 * force, with the outermost declaration appearing first. If there are no |
| 208 * type parameters, or we are not currently resynthesizing a class, typedef, |
| 209 * or executable, then this is an empty list. |
| 206 */ | 210 */ |
| 207 List<TypeParameterElement> currentTypeParameters; | 211 List<TypeParameterElement> currentTypeParameters = <TypeParameterElement>[]; |
| 208 | 212 |
| 209 _LibraryResynthesizer(this.summaryResynthesizer, this.prelinkedLibrary, | 213 _LibraryResynthesizer(this.summaryResynthesizer, this.prelinkedLibrary, |
| 210 this.unlinkedUnits, this.librarySource) { | 214 this.unlinkedUnits, this.librarySource) { |
| 211 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; | 215 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; |
| 212 } | 216 } |
| 213 | 217 |
| 214 /** | 218 /** |
| 215 * Return a list of type arguments corresponding to [currentTypeParameters]. | 219 * Return a list of type arguments corresponding to [currentTypeParameters]. |
| 216 */ | 220 */ |
| 217 List<TypeParameterType> get currentTypeArguments => currentTypeParameters | 221 List<TypeParameterType> get currentTypeArguments => currentTypeParameters |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 buildVariable(serializedVariable, memberHolder); | 271 buildVariable(serializedVariable, memberHolder); |
| 268 } | 272 } |
| 269 if (!serializedClass.isMixinApplication) { | 273 if (!serializedClass.isMixinApplication) { |
| 270 if (!constructorFound) { | 274 if (!constructorFound) { |
| 271 // Synthesize implicit constructors. | 275 // Synthesize implicit constructors. |
| 272 ConstructorElementImpl constructor = | 276 ConstructorElementImpl constructor = |
| 273 new ConstructorElementImpl('', -1); | 277 new ConstructorElementImpl('', -1); |
| 274 constructor.synthetic = true; | 278 constructor.synthetic = true; |
| 275 constructor.returnType = correspondingType; | 279 constructor.returnType = correspondingType; |
| 276 constructor.type = new FunctionTypeImpl.elementWithNameAndArgs( | 280 constructor.type = new FunctionTypeImpl.elementWithNameAndArgs( |
| 277 constructor, null, currentTypeArguments); | 281 constructor, null, currentTypeArguments, false); |
| 278 memberHolder.addConstructor(constructor); | 282 memberHolder.addConstructor(constructor); |
| 279 } | 283 } |
| 280 classElement.constructors = memberHolder.constructors; | 284 classElement.constructors = memberHolder.constructors; |
| 281 } | 285 } |
| 282 classElement.accessors = memberHolder.accessors; | 286 classElement.accessors = memberHolder.accessors; |
| 283 classElement.fields = memberHolder.fields; | 287 classElement.fields = memberHolder.fields; |
| 284 classElement.methods = memberHolder.methods; | 288 classElement.methods = memberHolder.methods; |
| 285 correspondingType.typeArguments = currentTypeArguments; | 289 correspondingType.typeArguments = currentTypeArguments; |
| 286 classElement.type = correspondingType; | 290 classElement.type = correspondingType; |
| 287 unitHolder.addType(classElement); | 291 unitHolder.addType(classElement); |
| 288 } finally { | 292 } finally { |
| 289 currentTypeParameters = null; | 293 currentTypeParameters = <TypeParameterElement>[]; |
| 290 } | 294 } |
| 291 } | 295 } |
| 292 | 296 |
| 293 /** | 297 /** |
| 294 * Resynthesize a [NamespaceCombinator]. | 298 * Resynthesize a [NamespaceCombinator]. |
| 295 */ | 299 */ |
| 296 NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) { | 300 NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) { |
| 297 if (serializedCombinator.shows.isNotEmpty) { | 301 if (serializedCombinator.shows.isNotEmpty) { |
| 298 ShowElementCombinatorImpl combinator = new ShowElementCombinatorImpl(); | 302 ShowElementCombinatorImpl combinator = new ShowElementCombinatorImpl(); |
| 299 // Note: we call toList() so that we don't retain a reference to the | 303 // Note: we call toList() so that we don't retain a reference to the |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 assert(false); | 448 assert(false); |
| 445 } | 449 } |
| 446 } | 450 } |
| 447 | 451 |
| 448 /** | 452 /** |
| 449 * Handle the parts of an executable element that are common to constructors, | 453 * Handle the parts of an executable element that are common to constructors, |
| 450 * functions, methods, getters, and setters. | 454 * functions, methods, getters, and setters. |
| 451 */ | 455 */ |
| 452 void buildExecutableCommonParts(ExecutableElementImpl executableElement, | 456 void buildExecutableCommonParts(ExecutableElementImpl executableElement, |
| 453 UnlinkedExecutable serializedExecutable) { | 457 UnlinkedExecutable serializedExecutable) { |
| 458 List<TypeParameterType> oldTypeArguments = currentTypeArguments; |
| 459 int oldTypeParametersLength = currentTypeParameters.length; |
| 460 if (serializedExecutable.typeParameters.isNotEmpty) { |
| 461 executableElement.typeParameters = |
| 462 serializedExecutable.typeParameters.map(buildTypeParameter).toList(); |
| 463 currentTypeParameters.addAll(executableElement.typeParameters); |
| 464 } |
| 454 executableElement.parameters = | 465 executableElement.parameters = |
| 455 serializedExecutable.parameters.map(buildParameter).toList(); | 466 serializedExecutable.parameters.map(buildParameter).toList(); |
| 456 if (serializedExecutable.returnType != null) { | 467 if (serializedExecutable.returnType != null) { |
| 457 executableElement.returnType = buildType(serializedExecutable.returnType); | 468 executableElement.returnType = buildType(serializedExecutable.returnType); |
| 458 } else if (serializedExecutable.kind == | 469 } else if (serializedExecutable.kind == |
| 459 UnlinkedExecutableKind.constructor) { | 470 UnlinkedExecutableKind.constructor) { |
| 460 // Return type was set by the caller. | 471 // Return type was set by the caller. |
| 461 } else { | 472 } else { |
| 462 executableElement.returnType = VoidTypeImpl.instance; | 473 executableElement.returnType = VoidTypeImpl.instance; |
| 463 } | 474 } |
| 464 executableElement.type = new FunctionTypeImpl.elementWithNameAndArgs( | 475 executableElement.type = new FunctionTypeImpl.elementWithNameAndArgs( |
| 465 executableElement, null, currentTypeArguments); | 476 executableElement, null, oldTypeArguments, false); |
| 466 executableElement.hasImplicitReturnType = | 477 executableElement.hasImplicitReturnType = |
| 467 serializedExecutable.hasImplicitReturnType; | 478 serializedExecutable.hasImplicitReturnType; |
| 468 executableElement.external = serializedExecutable.isExternal; | 479 executableElement.external = serializedExecutable.isExternal; |
| 480 currentTypeParameters.removeRange( |
| 481 oldTypeParametersLength, currentTypeParameters.length); |
| 469 } | 482 } |
| 470 | 483 |
| 471 /** | 484 /** |
| 472 * Resynthesize an [ExportElement], | 485 * Resynthesize an [ExportElement], |
| 473 */ | 486 */ |
| 474 ExportElement buildExport(UnlinkedExport serializedExport) { | 487 ExportElement buildExport(UnlinkedExport serializedExport) { |
| 475 ExportElementImpl exportElement = new ExportElementImpl(0); | 488 ExportElementImpl exportElement = new ExportElementImpl(0); |
| 476 String exportedLibraryUri = summaryResynthesizer.sourceFactory | 489 String exportedLibraryUri = summaryResynthesizer.sourceFactory |
| 477 .resolveUri(librarySource, serializedExport.uri) | 490 .resolveUri(librarySource, serializedExport.uri) |
| 478 .uri | 491 .uri |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 parameterElement.parameters = | 681 parameterElement.parameters = |
| 669 serializedParameter.parameters.map(buildParameter).toList(); | 682 serializedParameter.parameters.map(buildParameter).toList(); |
| 670 parameterTypeElement.enclosingElement = parameterElement; | 683 parameterTypeElement.enclosingElement = parameterElement; |
| 671 parameterTypeElement.shareParameters(parameterElement.parameters); | 684 parameterTypeElement.shareParameters(parameterElement.parameters); |
| 672 if (serializedParameter.type != null) { | 685 if (serializedParameter.type != null) { |
| 673 parameterTypeElement.returnType = buildType(serializedParameter.type); | 686 parameterTypeElement.returnType = buildType(serializedParameter.type); |
| 674 } else { | 687 } else { |
| 675 parameterTypeElement.returnType = VoidTypeImpl.instance; | 688 parameterTypeElement.returnType = VoidTypeImpl.instance; |
| 676 } | 689 } |
| 677 parameterElement.type = new FunctionTypeImpl.elementWithNameAndArgs( | 690 parameterElement.type = new FunctionTypeImpl.elementWithNameAndArgs( |
| 678 parameterTypeElement, null, currentTypeArguments); | 691 parameterTypeElement, null, currentTypeArguments, false); |
| 679 } else { | 692 } else { |
| 680 parameterElement.type = buildType(serializedParameter.type); | 693 parameterElement.type = buildType(serializedParameter.type); |
| 681 parameterElement.hasImplicitType = serializedParameter.hasImplicitType; | 694 parameterElement.hasImplicitType = serializedParameter.hasImplicitType; |
| 682 } | 695 } |
| 683 switch (serializedParameter.kind) { | 696 switch (serializedParameter.kind) { |
| 684 case UnlinkedParamKind.named: | 697 case UnlinkedParamKind.named: |
| 685 parameterElement.parameterKind = ParameterKind.NAMED; | 698 parameterElement.parameterKind = ParameterKind.NAMED; |
| 686 break; | 699 break; |
| 687 case UnlinkedParamKind.positional: | 700 case UnlinkedParamKind.positional: |
| 688 parameterElement.parameterKind = ParameterKind.POSITIONAL; | 701 parameterElement.parameterKind = ParameterKind.POSITIONAL; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 713 /** | 726 /** |
| 714 * Build a [DartType] object based on an [UnlinkedTypeRef]. This [DartType] | 727 * Build a [DartType] object based on an [UnlinkedTypeRef]. This [DartType] |
| 715 * may refer to elements in other libraries than the library being | 728 * may refer to elements in other libraries than the library being |
| 716 * deserialized, so handles are used to avoid having to deserialize other | 729 * deserialized, so handles are used to avoid having to deserialize other |
| 717 * libraries in the process. | 730 * libraries in the process. |
| 718 */ | 731 */ |
| 719 DartType buildType(UnlinkedTypeRef type) { | 732 DartType buildType(UnlinkedTypeRef type) { |
| 720 if (type.paramReference != 0) { | 733 if (type.paramReference != 0) { |
| 721 // TODO(paulberry): make this work for generic methods. | 734 // TODO(paulberry): make this work for generic methods. |
| 722 return currentTypeParameters[ | 735 return currentTypeParameters[ |
| 723 currentTypeParameters.length - type.paramReference] | 736 currentTypeParameters.length - type.paramReference].type; |
| 724 .type; | |
| 725 } else { | 737 } else { |
| 726 // TODO(paulberry): handle references to things other than classes (note: | 738 // TODO(paulberry): handle references to things other than classes (note: |
| 727 // this should only occur in the case of erroneous code). | 739 // this should only occur in the case of erroneous code). |
| 728 // TODO(paulberry): test reference to something inside a part. | 740 // TODO(paulberry): test reference to something inside a part. |
| 729 // TODO(paulberry): test reference to something inside a part of the | 741 // TODO(paulberry): test reference to something inside a part of the |
| 730 // current lib. | 742 // current lib. |
| 731 UnlinkedReference reference = unlinkedUnit.references[type.reference]; | 743 UnlinkedReference reference = unlinkedUnit.references[type.reference]; |
| 732 PrelinkedReference referenceResolution = | 744 PrelinkedReference referenceResolution = |
| 733 prelinkedUnit.references[type.reference]; | 745 prelinkedUnit.references[type.reference]; |
| 734 String referencedLibraryUri; | 746 String referencedLibraryUri; |
| 735 String partUri; | 747 String partUri; |
| 736 if (referenceResolution.dependency != 0) { | 748 if (referenceResolution.dependency != 0) { |
| 737 PrelinkedDependency dependency = | 749 PrelinkedDependency dependency = |
| 738 prelinkedLibrary.dependencies[referenceResolution.dependency]; | 750 prelinkedLibrary.dependencies[referenceResolution.dependency]; |
| 739 Source referencedLibrarySource = summaryResynthesizer.sourceFactory | 751 Source referencedLibrarySource = summaryResynthesizer.sourceFactory |
| 740 .resolveUri(librarySource, dependency.uri); | 752 .resolveUri(librarySource, dependency.uri); |
| 741 referencedLibraryUri = referencedLibrarySource.uri.toString(); | 753 referencedLibraryUri = referencedLibrarySource.uri.toString(); |
| 742 // TODO(paulberry): consider changing Location format so that this is | 754 // TODO(paulberry): consider changing Location format so that this is |
| 743 // not necessary (2nd string in location should just be the unit | 755 // not necessary (2nd string in location should just be the unit |
| 744 // number). | 756 // number). |
| 745 if (referenceResolution.unit != 0) { | 757 if (referenceResolution.unit != 0) { |
| 746 UnlinkedUnit referencedLibraryDefiningUnit = | 758 UnlinkedUnit referencedLibraryDefiningUnit = |
| 747 summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri); | 759 summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri); |
| 748 String uri = referencedLibraryDefiningUnit | 760 String uri = referencedLibraryDefiningUnit.publicNamespace.parts[ |
| 749 .publicNamespace.parts[referenceResolution.unit - 1].uri; | 761 referenceResolution.unit - 1].uri; |
| 750 Source partSource = summaryResynthesizer.sourceFactory | 762 Source partSource = summaryResynthesizer.sourceFactory |
| 751 .resolveUri(referencedLibrarySource, uri); | 763 .resolveUri(referencedLibrarySource, uri); |
| 752 partUri = partSource.uri.toString(); | 764 partUri = partSource.uri.toString(); |
| 753 } else { | 765 } else { |
| 754 partUri = referencedLibraryUri; | 766 partUri = referencedLibraryUri; |
| 755 } | 767 } |
| 756 } else if (referenceResolution.kind == | 768 } else if (referenceResolution.kind == |
| 757 PrelinkedReferenceKind.unresolved) { | 769 PrelinkedReferenceKind.unresolved) { |
| 758 return summaryResynthesizer.typeProvider.undefinedType; | 770 return summaryResynthesizer.typeProvider.undefinedType; |
| 759 } else if (reference.name.isEmpty) { | 771 } else if (reference.name.isEmpty) { |
| 760 return summaryResynthesizer.typeProvider.dynamicType; | 772 return summaryResynthesizer.typeProvider.dynamicType; |
| 761 } else { | 773 } else { |
| 762 referencedLibraryUri = librarySource.uri.toString(); | 774 referencedLibraryUri = librarySource.uri.toString(); |
| 763 if (referenceResolution.unit != 0) { | 775 if (referenceResolution.unit != 0) { |
| 764 String uri = unlinkedUnits[0] | 776 String uri = unlinkedUnits[0].publicNamespace.parts[ |
| 765 .publicNamespace | 777 referenceResolution.unit - 1].uri; |
| 766 .parts[referenceResolution.unit - 1] | |
| 767 .uri; | |
| 768 Source partSource = | 778 Source partSource = |
| 769 summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri); | 779 summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri); |
| 770 partUri = partSource.uri.toString(); | 780 partUri = partSource.uri.toString(); |
| 771 } else { | 781 } else { |
| 772 partUri = referencedLibraryUri; | 782 partUri = referencedLibraryUri; |
| 773 } | 783 } |
| 774 } | 784 } |
| 775 ElementLocationImpl location = new ElementLocationImpl.con3( | 785 ElementLocationImpl location = new ElementLocationImpl.con3( |
| 776 <String>[referencedLibraryUri, partUri, reference.name]); | 786 <String>[referencedLibraryUri, partUri, reference.name]); |
| 777 List<DartType> typeArguments = const <DartType>[]; | 787 List<DartType> typeArguments = const <DartType>[]; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 789 case PrelinkedReferenceKind.classOrEnum: | 799 case PrelinkedReferenceKind.classOrEnum: |
| 790 return new InterfaceTypeImpl.elementWithNameAndArgs( | 800 return new InterfaceTypeImpl.elementWithNameAndArgs( |
| 791 new ClassElementHandle(summaryResynthesizer, location), | 801 new ClassElementHandle(summaryResynthesizer, location), |
| 792 reference.name, | 802 reference.name, |
| 793 typeArguments); | 803 typeArguments); |
| 794 case PrelinkedReferenceKind.typedef: | 804 case PrelinkedReferenceKind.typedef: |
| 795 return new FunctionTypeImpl.elementWithNameAndArgs( | 805 return new FunctionTypeImpl.elementWithNameAndArgs( |
| 796 new FunctionTypeAliasElementHandle( | 806 new FunctionTypeAliasElementHandle( |
| 797 summaryResynthesizer, location), | 807 summaryResynthesizer, location), |
| 798 reference.name, | 808 reference.name, |
| 799 typeArguments); | 809 typeArguments, |
| 810 typeArguments.isNotEmpty); |
| 800 default: | 811 default: |
| 801 // TODO(paulberry): figure out how to handle this case (which should | 812 // TODO(paulberry): figure out how to handle this case (which should |
| 802 // only occur in the event of erroneous code). | 813 // only occur in the event of erroneous code). |
| 803 throw new UnimplementedError(); | 814 throw new UnimplementedError(); |
| 804 } | 815 } |
| 805 } | 816 } |
| 806 } | 817 } |
| 807 | 818 |
| 808 /** | 819 /** |
| 809 * Resynthesize a [FunctionTypeAliasElement] and place it in the | 820 * Resynthesize a [FunctionTypeAliasElement] and place it in the |
| (...skipping 15 matching lines...) Expand all Loading... |
| 825 functionTypeAliasElement.returnType = | 836 functionTypeAliasElement.returnType = |
| 826 buildType(serializedTypedef.returnType); | 837 buildType(serializedTypedef.returnType); |
| 827 } else { | 838 } else { |
| 828 functionTypeAliasElement.returnType = VoidTypeImpl.instance; | 839 functionTypeAliasElement.returnType = VoidTypeImpl.instance; |
| 829 } | 840 } |
| 830 functionTypeAliasElement.type = | 841 functionTypeAliasElement.type = |
| 831 new FunctionTypeImpl.forTypedef(functionTypeAliasElement); | 842 new FunctionTypeImpl.forTypedef(functionTypeAliasElement); |
| 832 functionTypeAliasElement.typeParameters = currentTypeParameters; | 843 functionTypeAliasElement.typeParameters = currentTypeParameters; |
| 833 unitHolder.addTypeAlias(functionTypeAliasElement); | 844 unitHolder.addTypeAlias(functionTypeAliasElement); |
| 834 } finally { | 845 } finally { |
| 835 currentTypeParameters = null; | 846 currentTypeParameters = <TypeParameterElement>[]; |
| 836 } | 847 } |
| 837 } | 848 } |
| 838 | 849 |
| 839 /** | 850 /** |
| 840 * Resynthesize a [TypeParameterElement], handling all parts of its except | 851 * Resynthesize a [TypeParameterElement], handling all parts of its except |
| 841 * its bound. | 852 * its bound. |
| 842 * | 853 * |
| 843 * The bound is deferred until later since it may refer to other type | 854 * The bound is deferred until later since it may refer to other type |
| 844 * parameters that have not been resynthesized yet. To handle the bound, | 855 * parameters that have not been resynthesized yet. To handle the bound, |
| 845 * call [finishTypeParameter]. | 856 * call [finishTypeParameter]. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 } | 939 } |
| 929 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { | 940 for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) { |
| 930 elementMap[typeAlias.name] = typeAlias; | 941 elementMap[typeAlias.name] = typeAlias; |
| 931 } | 942 } |
| 932 resummarizedElements[absoluteUri] = elementMap; | 943 resummarizedElements[absoluteUri] = elementMap; |
| 933 unitHolder = null; | 944 unitHolder = null; |
| 934 prelinkedUnit = null; | 945 prelinkedUnit = null; |
| 935 unlinkedUnit = null; | 946 unlinkedUnit = null; |
| 936 } | 947 } |
| 937 } | 948 } |
| OLD | NEW |