OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 serialization.summarize_ast; | 5 library serialization.summarize_ast; |
6 | 6 |
7 import 'package:analyzer/dart/ast/ast.dart'; | 7 import 'package:analyzer/dart/ast/ast.dart'; |
8 import 'package:analyzer/dart/ast/token.dart'; | 8 import 'package:analyzer/dart/ast/token.dart'; |
9 import 'package:analyzer/dart/ast/visitor.dart'; | 9 import 'package:analyzer/dart/ast/visitor.dart'; |
10 import 'package:analyzer/dart/element/type.dart' show DartType; | 10 import 'package:analyzer/dart/element/type.dart' show DartType; |
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 } | 636 } |
637 } | 637 } |
638 b.documentationComment = serializeDocumentation(documentationComment); | 638 b.documentationComment = serializeDocumentation(documentationComment); |
639 b.annotations = serializeAnnotations(annotations); | 639 b.annotations = serializeAnnotations(annotations); |
640 b.codeRange = serializeCodeRange(node); | 640 b.codeRange = serializeCodeRange(node); |
641 if (returnType == null && !isSemanticallyStatic) { | 641 if (returnType == null && !isSemanticallyStatic) { |
642 b.inferredReturnTypeSlot = assignSlot(); | 642 b.inferredReturnTypeSlot = assignSlot(); |
643 } | 643 } |
644 b.visibleOffset = enclosingBlock?.offset; | 644 b.visibleOffset = enclosingBlock?.offset; |
645 b.visibleLength = enclosingBlock?.length; | 645 b.visibleLength = enclosingBlock?.length; |
646 serializeFunctionBody(b, null, body); | 646 serializeFunctionBody(b, null, body, false); |
647 scopes.removeLast(); | 647 scopes.removeLast(); |
648 assert(scopes.length == oldScopesLength); | 648 assert(scopes.length == oldScopesLength); |
649 return b; | 649 return b; |
650 } | 650 } |
651 | 651 |
652 /** | 652 /** |
653 * Record local functions and variables into the given executable. The given | 653 * Record local functions and variables into the given executable. The given |
654 * [body] is usually an actual [FunctionBody], but may be an [Expression] | 654 * [body] is usually an actual [FunctionBody], but may be an [Expression] |
655 * when we process a synthetic variable initializer function. | 655 * when we process a synthetic variable initializer function. |
656 * | 656 * |
657 * If [initializers] is non-`null`, closures occurring inside the initializers | 657 * If [initializers] is non-`null`, closures occurring inside the initializers |
658 * are serialized first. | 658 * are serialized first. |
| 659 * |
| 660 * If [serializeBodyExpr] is `true`, then the function definition is stored |
| 661 * in [UnlinkedExecutableBuilder.bodyExpr]. |
| 662 * |
| 663 * The return value is a map whose keys are the offsets of local function |
| 664 * nodes representing closures inside [initializers] and [body], and whose |
| 665 * values are the indices of those local functions relative to their siblings. |
659 */ | 666 */ |
660 void serializeFunctionBody(UnlinkedExecutableBuilder b, | 667 Map<int, int> serializeFunctionBody( |
661 List<ConstructorInitializer> initializers, AstNode body) { | 668 UnlinkedExecutableBuilder b, |
| 669 List<ConstructorInitializer> initializers, |
| 670 AstNode body, |
| 671 bool serializeBodyExpr) { |
662 if (body is BlockFunctionBody || body is ExpressionFunctionBody) { | 672 if (body is BlockFunctionBody || body is ExpressionFunctionBody) { |
663 for (UnlinkedParamBuilder parameter in b.parameters) { | 673 for (UnlinkedParamBuilder parameter in b.parameters) { |
664 parameter.visibleOffset = body.offset; | 674 parameter.visibleOffset = body.offset; |
665 parameter.visibleLength = body.length; | 675 parameter.visibleLength = body.length; |
666 } | 676 } |
667 } | 677 } |
668 List<UnlinkedExecutableBuilder> oldExecutables = executables; | 678 List<UnlinkedExecutableBuilder> oldExecutables = executables; |
669 List<UnlinkedLabelBuilder> oldLabels = labels; | 679 List<UnlinkedLabelBuilder> oldLabels = labels; |
670 List<UnlinkedVariableBuilder> oldVariables = variables; | 680 List<UnlinkedVariableBuilder> oldVariables = variables; |
| 681 Map<int, int> oldLocalClosureIndexMap = _localClosureIndexMap; |
671 executables = <UnlinkedExecutableBuilder>[]; | 682 executables = <UnlinkedExecutableBuilder>[]; |
672 labels = <UnlinkedLabelBuilder>[]; | 683 labels = <UnlinkedLabelBuilder>[]; |
673 variables = <UnlinkedVariableBuilder>[]; | 684 variables = <UnlinkedVariableBuilder>[]; |
| 685 _localClosureIndexMap = <int, int>{}; |
674 if (initializers != null) { | 686 if (initializers != null) { |
675 for (ConstructorInitializer initializer in initializers) { | 687 for (ConstructorInitializer initializer in initializers) { |
676 initializer.accept(this); | 688 initializer.accept(this); |
677 } | 689 } |
678 } | 690 } |
679 body.accept(this); | 691 body.accept(this); |
| 692 if (serializeBodyExpr) { |
| 693 if (body is Expression) { |
| 694 b.bodyExpr = serializeConstExpr(_localClosureIndexMap, body); |
| 695 } else { |
| 696 // TODO(paulberry): serialize other types of function bodies. |
| 697 } |
| 698 } |
680 b.localFunctions = executables; | 699 b.localFunctions = executables; |
681 b.localLabels = labels; | 700 b.localLabels = labels; |
682 b.localVariables = variables; | 701 b.localVariables = variables; |
| 702 Map<int, int> localClosureIndexMap = _localClosureIndexMap; |
683 executables = oldExecutables; | 703 executables = oldExecutables; |
684 labels = oldLabels; | 704 labels = oldLabels; |
685 variables = oldVariables; | 705 variables = oldVariables; |
| 706 _localClosureIndexMap = oldLocalClosureIndexMap; |
| 707 return localClosureIndexMap; |
686 } | 708 } |
687 | 709 |
688 /** | 710 /** |
689 * Serialize the return type and parameters of a function-typed formal | 711 * Serialize the return type and parameters of a function-typed formal |
690 * parameter and store them in [b]. | 712 * parameter and store them in [b]. |
691 */ | 713 */ |
692 void serializeFunctionTypedParameterDetails(UnlinkedParamBuilder b, | 714 void serializeFunctionTypedParameterDetails(UnlinkedParamBuilder b, |
693 TypeName returnType, FormalParameterList parameters) { | 715 TypeName returnType, FormalParameterList parameters) { |
694 EntityRefBuilder serializedReturnType = serializeTypeName(returnType); | 716 EntityRefBuilder serializedReturnType = serializeTypeName(returnType); |
695 if (serializedReturnType != null) { | 717 if (serializedReturnType != null) { |
696 b.type = serializedReturnType; | 718 b.type = serializedReturnType; |
697 } | 719 } |
698 b.parameters = parameters.parameters | 720 b.parameters = parameters.parameters |
699 .map((FormalParameter p) => p.accept(this)) | 721 .map((FormalParameter p) => p.accept(this)) |
700 .toList(); | 722 .toList(); |
701 } | 723 } |
702 | 724 |
703 /** | 725 /** |
704 * If the given [expression] is not `null`, serialize it as an | 726 * If the given [expression] is not `null`, serialize it as an |
705 * [UnlinkedExecutableBuilder], otherwise return `null`. | 727 * [UnlinkedExecutableBuilder], otherwise return `null`. |
| 728 * |
| 729 * If [serializeBodyExpr] is `true`, then the initializer expression is stored |
| 730 * in [UnlinkedExecutableBuilder.bodyExpr]. |
706 */ | 731 */ |
707 UnlinkedExecutableBuilder serializeInitializerFunction( | 732 UnlinkedExecutableBuilder serializeInitializerFunction( |
708 Expression expression) { | 733 Expression expression, bool serializeBodyExpr) { |
709 if (expression == null) { | 734 if (expression == null) { |
710 return null; | 735 return null; |
711 } | 736 } |
712 UnlinkedExecutableBuilder initializer = | 737 UnlinkedExecutableBuilder initializer = |
713 new UnlinkedExecutableBuilder(nameOffset: expression.offset); | 738 new UnlinkedExecutableBuilder(nameOffset: expression.offset); |
714 serializeFunctionBody(initializer, null, expression); | 739 serializeFunctionBody(initializer, null, expression, serializeBodyExpr); |
715 initializer.inferredReturnTypeSlot = assignSlot(); | 740 initializer.inferredReturnTypeSlot = assignSlot(); |
716 return initializer; | 741 return initializer; |
717 } | 742 } |
718 | 743 |
719 /** | 744 /** |
720 * Serialize a [FieldFormalParameter], [FunctionTypedFormalParameter], or | 745 * Serialize a [FieldFormalParameter], [FunctionTypedFormalParameter], or |
721 * [SimpleFormalParameter] into an [UnlinkedParam]. | 746 * [SimpleFormalParameter] into an [UnlinkedParam]. |
722 */ | 747 */ |
723 UnlinkedParamBuilder serializeParameter(NormalFormalParameter node) { | 748 UnlinkedParamBuilder serializeParameter(NormalFormalParameter node) { |
724 UnlinkedParamBuilder b = new UnlinkedParamBuilder(); | 749 UnlinkedParamBuilder b = new UnlinkedParamBuilder(); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(); | 911 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(); |
887 b.isFinal = variables.isFinal; | 912 b.isFinal = variables.isFinal; |
888 b.isConst = variables.isConst; | 913 b.isConst = variables.isConst; |
889 b.isStatic = isDeclaredStatic; | 914 b.isStatic = isDeclaredStatic; |
890 b.name = variable.name.name; | 915 b.name = variable.name.name; |
891 b.nameOffset = variable.name.offset; | 916 b.nameOffset = variable.name.offset; |
892 b.type = serializeTypeName(variables.type); | 917 b.type = serializeTypeName(variables.type); |
893 b.documentationComment = serializeDocumentation(documentationComment); | 918 b.documentationComment = serializeDocumentation(documentationComment); |
894 b.annotations = serializeAnnotations(annotations); | 919 b.annotations = serializeAnnotations(annotations); |
895 b.codeRange = serializeCodeRange(variables.parent); | 920 b.codeRange = serializeCodeRange(variables.parent); |
896 Map<int, int> localClosureIndexMap = _withLocalClosureIndexMap(() { | 921 bool serializeBodyExpr = variable.isConst || |
897 b.initializer = serializeInitializerFunction(variable.initializer); | |
898 }); | |
899 if (variable.isConst || | |
900 variable.isFinal && isField && !isDeclaredStatic || | 922 variable.isFinal && isField && !isDeclaredStatic || |
901 variables.type == null) { | 923 variables.type == null; |
902 Expression initializer = variable.initializer; | 924 b.initializer = |
903 if (initializer != null) { | 925 serializeInitializerFunction(variable.initializer, serializeBodyExpr); |
904 b.initializer.bodyExpr = | |
905 serializeConstExpr(localClosureIndexMap, initializer); | |
906 } | |
907 } | |
908 if (variable.initializer != null && | 926 if (variable.initializer != null && |
909 (variables.isFinal || variables.isConst)) { | 927 (variables.isFinal || variables.isConst)) { |
910 b.propagatedTypeSlot = assignSlot(); | 928 b.propagatedTypeSlot = assignSlot(); |
911 } | 929 } |
912 bool isSemanticallyStatic = !isField || isDeclaredStatic; | 930 bool isSemanticallyStatic = !isField || isDeclaredStatic; |
913 if (variables.type == null && | 931 if (variables.type == null && |
914 (variable.initializer != null || !isSemanticallyStatic)) { | 932 (variable.initializer != null || !isSemanticallyStatic)) { |
915 b.inferredTypeSlot = assignSlot(); | 933 b.inferredTypeSlot = assignSlot(); |
916 } | 934 } |
917 b.visibleOffset = scopeNode?.offset; | 935 b.visibleOffset = scopeNode?.offset; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 } | 1034 } |
1017 } | 1035 } |
1018 if (node.constKeyword != null) { | 1036 if (node.constKeyword != null) { |
1019 b.isConst = true; | 1037 b.isConst = true; |
1020 b.constCycleSlot = assignSlot(); | 1038 b.constCycleSlot = assignSlot(); |
1021 } | 1039 } |
1022 b.isExternal = node.externalKeyword != null; | 1040 b.isExternal = node.externalKeyword != null; |
1023 b.documentationComment = serializeDocumentation(node.documentationComment); | 1041 b.documentationComment = serializeDocumentation(node.documentationComment); |
1024 b.annotations = serializeAnnotations(node.metadata); | 1042 b.annotations = serializeAnnotations(node.metadata); |
1025 b.codeRange = serializeCodeRange(node); | 1043 b.codeRange = serializeCodeRange(node); |
1026 Map<int, int> localClosureIndexMap = _withLocalClosureIndexMap(() { | 1044 Map<int, int> localClosureIndexMap = serializeFunctionBody( |
1027 serializeFunctionBody(b, node.initializers, node.body); | 1045 b, node.initializers, node.body, node.constKeyword != null); |
1028 }); | |
1029 if (node.constKeyword != null) { | 1046 if (node.constKeyword != null) { |
1030 Set<String> constructorParameterNames = | 1047 Set<String> constructorParameterNames = |
1031 node.parameters.parameters.map((p) => p.identifier.name).toSet(); | 1048 node.parameters.parameters.map((p) => p.identifier.name).toSet(); |
1032 b.constantInitializers = node.initializers | 1049 b.constantInitializers = node.initializers |
1033 .map((ConstructorInitializer initializer) => | 1050 .map((ConstructorInitializer initializer) => |
1034 serializeConstructorInitializer(initializer, (Expression expr) { | 1051 serializeConstructorInitializer(initializer, (Expression expr) { |
1035 return serializeConstExpr( | 1052 return serializeConstExpr( |
1036 localClosureIndexMap, expr, constructorParameterNames); | 1053 localClosureIndexMap, expr, constructorParameterNames); |
1037 })) | 1054 })) |
1038 .toList(); | 1055 .toList(); |
1039 } | 1056 } |
1040 executables.add(b); | 1057 executables.add(b); |
1041 } | 1058 } |
1042 | 1059 |
1043 @override | 1060 @override |
1044 UnlinkedParamBuilder visitDefaultFormalParameter( | 1061 UnlinkedParamBuilder visitDefaultFormalParameter( |
1045 DefaultFormalParameter node) { | 1062 DefaultFormalParameter node) { |
1046 UnlinkedParamBuilder b = node.parameter.accept(this); | 1063 UnlinkedParamBuilder b = node.parameter.accept(this); |
1047 b.initializer = serializeInitializerFunction(node.defaultValue); | 1064 b.initializer = serializeInitializerFunction(node.defaultValue, true); |
1048 if (node.defaultValue != null) { | 1065 if (node.defaultValue != null) { |
1049 // Closures can't appear inside default values, so we don't need a | |
1050 // localClosureIndexMap. | |
1051 Map<int, int> localClosureIndexMap = null; | |
1052 b.initializer?.bodyExpr = | |
1053 serializeConstExpr(localClosureIndexMap, node.defaultValue); | |
1054 b.defaultValueCode = node.defaultValue.toSource(); | 1066 b.defaultValueCode = node.defaultValue.toSource(); |
1055 } | 1067 } |
1056 b.codeRange = serializeCodeRange(node); | 1068 b.codeRange = serializeCodeRange(node); |
1057 return b; | 1069 return b; |
1058 } | 1070 } |
1059 | 1071 |
1060 @override | 1072 @override |
1061 void visitEnumDeclaration(EnumDeclaration node) { | 1073 void visitEnumDeclaration(EnumDeclaration node) { |
1062 UnlinkedEnumBuilder b = new UnlinkedEnumBuilder(); | 1074 UnlinkedEnumBuilder b = new UnlinkedEnumBuilder(); |
1063 b.name = node.name.name; | 1075 b.name = node.name.name; |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 return b; | 1322 return b; |
1311 } | 1323 } |
1312 | 1324 |
1313 @override | 1325 @override |
1314 void visitVariableDeclarationStatement(VariableDeclarationStatement node) { | 1326 void visitVariableDeclarationStatement(VariableDeclarationStatement node) { |
1315 serializeVariables( | 1327 serializeVariables( |
1316 enclosingBlock, node.variables, false, null, null, false); | 1328 enclosingBlock, node.variables, false, null, null, false); |
1317 } | 1329 } |
1318 | 1330 |
1319 /** | 1331 /** |
1320 * Execute [callback], gathering any local closures in | |
1321 * [_localClosureIndexMap], and return the resulting map. | |
1322 * | |
1323 * Properly handles cases where one closure is nested within another. | |
1324 */ | |
1325 Map<int, int> _withLocalClosureIndexMap(void callback()) { | |
1326 Map<int, int> prevLocalClosureIndexMap = _localClosureIndexMap; | |
1327 _localClosureIndexMap = <int, int>{}; | |
1328 callback(); | |
1329 Map<int, int> localClosureIndexMap = _localClosureIndexMap; | |
1330 _localClosureIndexMap = prevLocalClosureIndexMap; | |
1331 return localClosureIndexMap; | |
1332 } | |
1333 | |
1334 /** | |
1335 * Helper method to determine if a given [typeName] refers to `dynamic`. | 1332 * Helper method to determine if a given [typeName] refers to `dynamic`. |
1336 */ | 1333 */ |
1337 static bool isDynamic(TypeName typeName) { | 1334 static bool isDynamic(TypeName typeName) { |
1338 Identifier name = typeName.name; | 1335 Identifier name = typeName.name; |
1339 return name is SimpleIdentifier && name.name == 'dynamic'; | 1336 return name is SimpleIdentifier && name.name == 'dynamic'; |
1340 } | 1337 } |
1341 } | 1338 } |
1342 | 1339 |
1343 /** | 1340 /** |
1344 * A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s. | 1341 * A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s. |
1345 */ | 1342 */ |
1346 class _TypeParameterScope extends _Scope { | 1343 class _TypeParameterScope extends _Scope { |
1347 /** | 1344 /** |
1348 * Get the number of [_ScopedTypeParameter]s defined in this | 1345 * Get the number of [_ScopedTypeParameter]s defined in this |
1349 * [_TypeParameterScope]. | 1346 * [_TypeParameterScope]. |
1350 */ | 1347 */ |
1351 int get length => _definedNames.length; | 1348 int get length => _definedNames.length; |
1352 } | 1349 } |
OLD | NEW |