| 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 |