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'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/element/element.dart'; | 10 import 'package:analyzer/dart/element/element.dart'; |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 428 _pushInstanceCreation(); | 428 _pushInstanceCreation(); |
| 429 break; | 429 break; |
| 430 case UnlinkedConstOperation.length: | 430 case UnlinkedConstOperation.length: |
| 431 Expression target = _pop(); | 431 Expression target = _pop(); |
| 432 SimpleIdentifier property = AstFactory.identifier3('length'); | 432 SimpleIdentifier property = AstFactory.identifier3('length'); |
| 433 property.staticElement = | 433 property.staticElement = |
| 434 resynthesizer._buildStringLengthPropertyAccessorElement(); | 434 resynthesizer._buildStringLengthPropertyAccessorElement(); |
| 435 _push(AstFactory.propertyAccess(target, property)); | 435 _push(AstFactory.propertyAccess(target, property)); |
| 436 break; | 436 break; |
| 437 case UnlinkedConstOperation.pushConstructorParameter: | 437 case UnlinkedConstOperation.pushConstructorParameter: |
| 438 // TODO(scheglov) implement | 438 String name = uc.strings[stringPtr++]; |
| 439 throw new UnimplementedError('$operation'); | 439 SimpleIdentifier identifier = AstFactory.identifier3(name); |
| 440 identifier.staticElement = resynthesizer.currentConstructor.parameters | |
| 441 .firstWhere((parameter) => parameter.name == name, | |
| 442 orElse: () => throw new StateError( | |
| 443 'Unable to resolve constructor parameter: $name')); | |
| 444 _push(identifier); | |
| 440 break; | 445 break; |
| 441 } | 446 } |
| 442 } | 447 } |
| 443 return stack.single; | 448 return stack.single; |
| 444 } | 449 } |
| 445 | 450 |
| 446 TypeName _buildTypeAst(DartType type) { | 451 TypeName _buildTypeAst(DartType type) { |
| 447 if (type is DynamicTypeImpl) { | 452 if (type is DynamicTypeImpl) { |
| 448 TypeName node = AstFactory.typeName4('dynamic'); | 453 TypeName node = AstFactory.typeName4('dynamic'); |
| 449 node.type = type; | 454 node.type = type; |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 686 */ | 691 */ |
| 687 Map<int, EntityRef> linkedTypeMap; | 692 Map<int, EntityRef> linkedTypeMap; |
| 688 | 693 |
| 689 /** | 694 /** |
| 690 * The [CompilationUnitElementImpl] for the compilation unit currently being | 695 * The [CompilationUnitElementImpl] for the compilation unit currently being |
| 691 * resynthesized. | 696 * resynthesized. |
| 692 */ | 697 */ |
| 693 CompilationUnitElementImpl currentCompilationUnit; | 698 CompilationUnitElementImpl currentCompilationUnit; |
| 694 | 699 |
| 695 /** | 700 /** |
| 701 * The [ConstructorElementImpl] for the constructor currently being | |
| 702 * resynthesized. | |
| 703 */ | |
| 704 ConstructorElementImpl currentConstructor; | |
| 705 | |
| 706 /** | |
| 696 * Map of top level elements that have been resynthesized so far. The first | 707 * Map of top level elements that have been resynthesized so far. The first |
| 697 * key is the URI of the compilation unit; the second is the name of the top | 708 * key is the URI of the compilation unit; the second is the name of the top |
| 698 * level element. | 709 * level element. |
| 699 */ | 710 */ |
| 700 final Map<String, Map<String, Element>> resummarizedElements = | 711 final Map<String, Map<String, Element>> resummarizedElements = |
| 701 <String, Map<String, Element>>{}; | 712 <String, Map<String, Element>>{}; |
| 702 | 713 |
| 703 /** | 714 /** |
| 704 * Type parameters for the generic class, typedef, or executable currently | 715 * Type parameters for the generic class, typedef, or executable currently |
| 705 * being resynthesized, if any. If multiple entities with type parameters | 716 * being resynthesized, if any. If multiple entities with type parameters |
| 706 * are nested (e.g. a generic executable inside a generic class), this is the | 717 * are nested (e.g. a generic executable inside a generic class), this is the |
| 707 * concatenation of all type parameters from all declarations currently in | 718 * concatenation of all type parameters from all declarations currently in |
| 708 * force, with the outermost declaration appearing first. If there are no | 719 * force, with the outermost declaration appearing first. If there are no |
| 709 * type parameters, or we are not currently resynthesizing a class, typedef, | 720 * type parameters, or we are not currently resynthesizing a class, typedef, |
| 710 * or executable, then this is an empty list. | 721 * or executable, then this is an empty list. |
| 711 */ | 722 */ |
| 712 List<TypeParameterElement> currentTypeParameters = <TypeParameterElement>[]; | 723 List<TypeParameterElement> currentTypeParameters = <TypeParameterElement>[]; |
| 713 | 724 |
| 714 /** | 725 /** |
| 715 * If a class is currently being resynthesized, map from field name to the | 726 * If a class is currently being resynthesized, map from field name to the |
| 716 * corresponding field element. This is used when resynthesizing | 727 * corresponding field element. This is used when resynthesizing |
| 717 * initializing formal parameters. | 728 * initializing formal parameters. |
| 718 */ | 729 */ |
| 719 Map<String, FieldElementImpl> fields; | 730 Map<String, FieldElementImpl> fields; |
| 720 | 731 |
| 721 /** | 732 /** |
| 733 * If a class is currently being resynthesized, map from constructor name to | |
| 734 * the corresponding constructor element. This is used when resynthesizing | |
| 735 * constructor initializers. | |
| 736 */ | |
| 737 Map<String, ConstructorElementImpl> constructors; | |
| 738 | |
| 739 /** | |
| 722 * List of [_ReferenceInfo] objects describing the references in the current | 740 * List of [_ReferenceInfo] objects describing the references in the current |
| 723 * compilation unit. | 741 * compilation unit. |
| 724 */ | 742 */ |
| 725 List<_ReferenceInfo> referenceInfos; | 743 List<_ReferenceInfo> referenceInfos; |
| 726 | 744 |
| 727 _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary, | 745 _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary, |
| 728 this.unlinkedUnits, this.librarySource) { | 746 this.unlinkedUnits, this.librarySource) { |
| 729 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; | 747 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; |
| 730 } | 748 } |
| 731 | 749 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 798 classElement.interfaces = | 816 classElement.interfaces = |
| 799 serializedClass.interfaces.map(buildType).toList(); | 817 serializedClass.interfaces.map(buildType).toList(); |
| 800 classElement.mixins = serializedClass.mixins.map(buildType).toList(); | 818 classElement.mixins = serializedClass.mixins.map(buildType).toList(); |
| 801 classElement.typeParameters = currentTypeParameters; | 819 classElement.typeParameters = currentTypeParameters; |
| 802 ElementHolder memberHolder = new ElementHolder(); | 820 ElementHolder memberHolder = new ElementHolder(); |
| 803 fields = <String, FieldElementImpl>{}; | 821 fields = <String, FieldElementImpl>{}; |
| 804 for (UnlinkedVariable serializedVariable in serializedClass.fields) { | 822 for (UnlinkedVariable serializedVariable in serializedClass.fields) { |
| 805 buildVariable(serializedVariable, memberHolder); | 823 buildVariable(serializedVariable, memberHolder); |
| 806 } | 824 } |
| 807 bool constructorFound = false; | 825 bool constructorFound = false; |
| 826 constructors = <String, ConstructorElementImpl>{}; | |
| 808 for (UnlinkedExecutable serializedExecutable | 827 for (UnlinkedExecutable serializedExecutable |
| 809 in serializedClass.executables) { | 828 in serializedClass.executables) { |
| 810 switch (serializedExecutable.kind) { | 829 switch (serializedExecutable.kind) { |
| 811 case UnlinkedExecutableKind.constructor: | 830 case UnlinkedExecutableKind.constructor: |
| 812 constructorFound = true; | 831 constructorFound = true; |
| 813 buildConstructor( | 832 buildConstructor( |
| 814 serializedExecutable, memberHolder, correspondingType); | 833 serializedExecutable, memberHolder, correspondingType); |
| 815 break; | 834 break; |
| 816 case UnlinkedExecutableKind.functionOrMethod: | 835 case UnlinkedExecutableKind.functionOrMethod: |
| 817 case UnlinkedExecutableKind.getter: | 836 case UnlinkedExecutableKind.getter: |
| 818 case UnlinkedExecutableKind.setter: | 837 case UnlinkedExecutableKind.setter: |
| 819 buildExecutable(serializedExecutable, memberHolder); | 838 buildExecutable(serializedExecutable, memberHolder); |
| 820 break; | 839 break; |
| 821 } | 840 } |
| 822 } | 841 } |
| 823 if (!serializedClass.isMixinApplication) { | 842 if (!serializedClass.isMixinApplication) { |
| 824 if (!constructorFound) { | 843 if (!constructorFound) { |
| 825 // Synthesize implicit constructors. | 844 // Synthesize implicit constructors. |
| 826 ConstructorElementImpl constructor = | 845 ConstructorElementImpl constructor = |
| 827 new ConstructorElementImpl('', -1); | 846 new ConstructorElementImpl('', -1); |
| 828 constructor.synthetic = true; | 847 constructor.synthetic = true; |
| 829 constructor.returnType = correspondingType; | 848 constructor.returnType = correspondingType; |
| 830 constructor.type = new FunctionTypeImpl.elementWithNameAndArgs( | 849 constructor.type = new FunctionTypeImpl.elementWithNameAndArgs( |
| 831 constructor, null, currentTypeArguments, false); | 850 constructor, null, currentTypeArguments, false); |
| 851 // constructor.constantInitializers = <ConstructorInitializer>[]; | |
|
Paul Berry
2016/02/08 20:40:55
Accidental debug code?
| |
| 832 memberHolder.addConstructor(constructor); | 852 memberHolder.addConstructor(constructor); |
| 833 } | 853 } |
| 834 classElement.constructors = memberHolder.constructors; | 854 classElement.constructors = memberHolder.constructors; |
| 835 } | 855 } |
| 836 classElement.accessors = memberHolder.accessors; | 856 classElement.accessors = memberHolder.accessors; |
| 837 classElement.fields = memberHolder.fields; | 857 classElement.fields = memberHolder.fields; |
| 838 classElement.methods = memberHolder.methods; | 858 classElement.methods = memberHolder.methods; |
| 839 correspondingType.typeArguments = currentTypeArguments; | 859 correspondingType.typeArguments = currentTypeArguments; |
| 840 classElement.type = correspondingType; | 860 classElement.type = correspondingType; |
| 841 buildDocumentation(classElement, serializedClass.documentationComment); | 861 buildDocumentation(classElement, serializedClass.documentationComment); |
| 842 buildAnnotations(classElement, serializedClass.annotations); | 862 buildAnnotations(classElement, serializedClass.annotations); |
| 863 resolveConstructorInitializers(classElement); | |
| 843 unitHolder.addType(classElement); | 864 unitHolder.addType(classElement); |
| 844 } finally { | 865 } finally { |
| 845 currentTypeParameters = <TypeParameterElement>[]; | 866 currentTypeParameters = <TypeParameterElement>[]; |
| 846 fields = null; | 867 fields = null; |
| 868 constructors = null; | |
| 847 } | 869 } |
| 848 } | 870 } |
| 849 | 871 |
| 850 /** | 872 /** |
| 851 * Resynthesize a [NamespaceCombinator]. | 873 * Resynthesize a [NamespaceCombinator]. |
| 852 */ | 874 */ |
| 853 NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) { | 875 NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) { |
| 854 if (serializedCombinator.shows.isNotEmpty) { | 876 if (serializedCombinator.shows.isNotEmpty) { |
| 855 ShowElementCombinatorImpl combinator = new ShowElementCombinatorImpl(); | 877 ShowElementCombinatorImpl combinator = new ShowElementCombinatorImpl(); |
| 856 // Note: we call toList() so that we don't retain a reference to the | 878 // Note: we call toList() so that we don't retain a reference to the |
| 857 // deserialized data structure. | 879 // deserialized data structure. |
| 858 combinator.shownNames = serializedCombinator.shows.toList(); | 880 combinator.shownNames = serializedCombinator.shows.toList(); |
| 859 return combinator; | 881 return combinator; |
| 860 } else { | 882 } else { |
| 861 HideElementCombinatorImpl combinator = new HideElementCombinatorImpl(); | 883 HideElementCombinatorImpl combinator = new HideElementCombinatorImpl(); |
| 862 // Note: we call toList() so that we don't retain a reference to the | 884 // Note: we call toList() so that we don't retain a reference to the |
| 863 // deserialized data structure. | 885 // deserialized data structure. |
| 864 combinator.hiddenNames = serializedCombinator.hides.toList(); | 886 combinator.hiddenNames = serializedCombinator.hides.toList(); |
| 865 return combinator; | 887 return combinator; |
| 866 } | 888 } |
| 867 } | 889 } |
| 868 | 890 |
| 869 /** | 891 /** |
| 892 * Resynthesize the [ConstructorInitializer] in context of | |
| 893 * [currentConstructor], which is used to resolve constructor parameter names. | |
| 894 */ | |
| 895 ConstructorInitializer buildConstantInitializer( | |
| 896 UnlinkedConstructorInitializer serialized) { | |
| 897 UnlinkedConstructorInitializerKind kind = serialized.kind; | |
| 898 String name = serialized.name; | |
| 899 List<Expression> arguments = | |
| 900 serialized.arguments.map(_buildConstExpression).toList(); | |
| 901 switch (kind) { | |
| 902 case UnlinkedConstructorInitializerKind.field: | |
| 903 return AstFactory.constructorFieldInitializer( | |
| 904 false, name, _buildConstExpression(serialized.expression)); | |
| 905 case UnlinkedConstructorInitializerKind.superInvocation: | |
| 906 return AstFactory.superConstructorInvocation2( | |
| 907 name.isNotEmpty ? name : null, arguments); | |
| 908 case UnlinkedConstructorInitializerKind.thisInvocation: | |
| 909 return AstFactory.redirectingConstructorInvocation2( | |
| 910 name.isNotEmpty ? name : null, arguments); | |
| 911 } | |
| 912 } | |
| 913 | |
| 914 /** | |
| 870 * Resynthesize a [ConstructorElement] and place it in the given [holder]. | 915 * Resynthesize a [ConstructorElement] and place it in the given [holder]. |
| 871 * [classType] is the type of the class for which this element is a | 916 * [classType] is the type of the class for which this element is a |
| 872 * constructor. | 917 * constructor. |
| 873 */ | 918 */ |
| 874 void buildConstructor(UnlinkedExecutable serializedExecutable, | 919 void buildConstructor(UnlinkedExecutable serializedExecutable, |
| 875 ElementHolder holder, InterfaceType classType) { | 920 ElementHolder holder, InterfaceType classType) { |
| 876 assert(serializedExecutable.kind == UnlinkedExecutableKind.constructor); | 921 assert(serializedExecutable.kind == UnlinkedExecutableKind.constructor); |
| 877 ConstructorElementImpl constructorElement = new ConstructorElementImpl( | 922 currentConstructor = new ConstructorElementImpl( |
| 878 serializedExecutable.name, serializedExecutable.nameOffset); | 923 serializedExecutable.name, serializedExecutable.nameOffset); |
| 879 constructorElement.returnType = classType; | 924 constructors[serializedExecutable.name] = currentConstructor; |
| 880 buildExecutableCommonParts(constructorElement, serializedExecutable); | 925 currentConstructor.returnType = classType; |
| 881 constructorElement.factory = serializedExecutable.isFactory; | 926 buildExecutableCommonParts(currentConstructor, serializedExecutable); |
| 882 constructorElement.const2 = serializedExecutable.isConst; | 927 currentConstructor.factory = serializedExecutable.isFactory; |
| 883 holder.addConstructor(constructorElement); | 928 currentConstructor.const2 = serializedExecutable.isConst; |
| 929 currentConstructor.constantInitializers = serializedExecutable | |
| 930 .constantInitializers | |
| 931 .map(buildConstantInitializer) | |
| 932 .toList(); | |
| 933 holder.addConstructor(currentConstructor); | |
| 934 currentConstructor = null; | |
| 884 } | 935 } |
| 885 | 936 |
| 886 /** | 937 /** |
| 887 * Build the documentation for the given [element]. Does nothing if | 938 * Build the documentation for the given [element]. Does nothing if |
| 888 * [serializedDocumentationComment] is `null`. | 939 * [serializedDocumentationComment] is `null`. |
| 889 */ | 940 */ |
| 890 void buildDocumentation(ElementImpl element, | 941 void buildDocumentation(ElementImpl element, |
| 891 UnlinkedDocumentationComment serializedDocumentationComment) { | 942 UnlinkedDocumentationComment serializedDocumentationComment) { |
| 892 if (serializedDocumentationComment != null) { | 943 if (serializedDocumentationComment != null) { |
| 893 element.documentationComment = serializedDocumentationComment.text; | 944 element.documentationComment = serializedDocumentationComment.text; |
| (...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1782 unlinkedUnit = unlinkedUnits[unitNum]; | 1833 unlinkedUnit = unlinkedUnits[unitNum]; |
| 1783 linkedTypeMap = <int, EntityRef>{}; | 1834 linkedTypeMap = <int, EntityRef>{}; |
| 1784 currentCompilationUnit = unit; | 1835 currentCompilationUnit = unit; |
| 1785 for (EntityRef t in linkedUnit.types) { | 1836 for (EntityRef t in linkedUnit.types) { |
| 1786 linkedTypeMap[t.slot] = t; | 1837 linkedTypeMap[t.slot] = t; |
| 1787 } | 1838 } |
| 1788 populateReferenceInfos(); | 1839 populateReferenceInfos(); |
| 1789 unitHolder = new ElementHolder(); | 1840 unitHolder = new ElementHolder(); |
| 1790 } | 1841 } |
| 1791 | 1842 |
| 1843 /** | |
| 1844 * Constructor initializers can reference fields and other constructors of | |
| 1845 * the same class, including forward references. So, we need to delay | |
| 1846 * resolution until after class elements are built. | |
| 1847 */ | |
| 1848 void resolveConstructorInitializers(ClassElementImpl classElement) { | |
| 1849 for (ConstructorElementImpl constructor in constructors.values) { | |
| 1850 for (ConstructorInitializer initializer | |
| 1851 in constructor.constantInitializers) { | |
| 1852 if (initializer is ConstructorFieldInitializer) { | |
| 1853 SimpleIdentifier nameNode = initializer.fieldName; | |
| 1854 nameNode.staticElement = fields[nameNode.name]; | |
| 1855 } else if (initializer is SuperConstructorInvocation) { | |
| 1856 SimpleIdentifier nameNode = initializer.constructorName; | |
| 1857 ConstructorElement element = new _DeferredConstructorElement( | |
| 1858 classElement.supertype, nameNode?.name ?? ''); | |
| 1859 initializer.staticElement = element; | |
| 1860 nameNode?.staticElement = element; | |
| 1861 } else if (initializer is RedirectingConstructorInvocation) { | |
| 1862 SimpleIdentifier nameNode = initializer.constructorName; | |
| 1863 ConstructorElement element = constructors[nameNode?.name ?? '']; | |
| 1864 initializer.staticElement = element; | |
| 1865 nameNode?.staticElement = element; | |
| 1866 } | |
| 1867 } | |
| 1868 } | |
| 1869 } | |
| 1870 | |
| 1792 Expression _buildConstExpression(UnlinkedConst uc) { | 1871 Expression _buildConstExpression(UnlinkedConst uc) { |
| 1793 return new _ConstExprBuilder(this, uc).build(); | 1872 return new _ConstExprBuilder(this, uc).build(); |
| 1794 } | 1873 } |
| 1795 | 1874 |
| 1796 /** | 1875 /** |
| 1797 * Return the new handle of the `String.length` getter element. | 1876 * Return the new handle of the `String.length` getter element. |
| 1798 */ | 1877 */ |
| 1799 PropertyAccessorElementHandle _buildStringLengthPropertyAccessorElement() => | 1878 PropertyAccessorElementHandle _buildStringLengthPropertyAccessorElement() => |
| 1800 new PropertyAccessorElementHandle( | 1879 new PropertyAccessorElementHandle( |
| 1801 summaryResynthesizer, | 1880 summaryResynthesizer, |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1936 } | 2015 } |
| 1937 : () => this.element; | 2016 : () => this.element; |
| 1938 // TODO(paulberry): Is it a bug that we have to pass `false` for | 2017 // TODO(paulberry): Is it a bug that we have to pass `false` for |
| 1939 // isInstantiated? | 2018 // isInstantiated? |
| 1940 return new DeferredFunctionTypeImpl(computer, null, typeArguments, false); | 2019 return new DeferredFunctionTypeImpl(computer, null, typeArguments, false); |
| 1941 } else { | 2020 } else { |
| 1942 return null; | 2021 return null; |
| 1943 } | 2022 } |
| 1944 } | 2023 } |
| 1945 } | 2024 } |
| OLD | NEW |