Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(752)

Side by Side Diff: pkg/analyzer/lib/src/summary/resynthesize.dart

Issue 1679923002: Resynthesize constructor initializers. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/testing/test_type_provider.dart ('k') | pkg/analyzer/test/src/summary/resynthesize_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698