| Index: pkg/analyzer/lib/src/summary/summarize_ast.dart
|
| diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
|
| index 139a4c2175fb12de7852baa99dae5c58f2d80147..fe6e10350028a13a7e193a30127757036d7800fd 100644
|
| --- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
|
| +++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
|
| @@ -643,7 +643,7 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
|
| }
|
| b.visibleOffset = enclosingBlock?.offset;
|
| b.visibleLength = enclosingBlock?.length;
|
| - serializeFunctionBody(b, null, body);
|
| + serializeFunctionBody(b, null, body, false);
|
| scopes.removeLast();
|
| assert(scopes.length == oldScopesLength);
|
| return b;
|
| @@ -656,9 +656,19 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
|
| *
|
| * If [initializers] is non-`null`, closures occurring inside the initializers
|
| * are serialized first.
|
| + *
|
| + * If [serializeBodyExpr] is `true`, then the function definition is stored
|
| + * in [UnlinkedExecutableBuilder.bodyExpr].
|
| + *
|
| + * The return value is a map whose keys are the offsets of local function
|
| + * nodes representing closures inside [initializers] and [body], and whose
|
| + * values are the indices of those local functions relative to their siblings.
|
| */
|
| - void serializeFunctionBody(UnlinkedExecutableBuilder b,
|
| - List<ConstructorInitializer> initializers, AstNode body) {
|
| + Map<int, int> serializeFunctionBody(
|
| + UnlinkedExecutableBuilder b,
|
| + List<ConstructorInitializer> initializers,
|
| + AstNode body,
|
| + bool serializeBodyExpr) {
|
| if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
|
| for (UnlinkedParamBuilder parameter in b.parameters) {
|
| parameter.visibleOffset = body.offset;
|
| @@ -668,21 +678,33 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
|
| List<UnlinkedExecutableBuilder> oldExecutables = executables;
|
| List<UnlinkedLabelBuilder> oldLabels = labels;
|
| List<UnlinkedVariableBuilder> oldVariables = variables;
|
| + Map<int, int> oldLocalClosureIndexMap = _localClosureIndexMap;
|
| executables = <UnlinkedExecutableBuilder>[];
|
| labels = <UnlinkedLabelBuilder>[];
|
| variables = <UnlinkedVariableBuilder>[];
|
| + _localClosureIndexMap = <int, int>{};
|
| if (initializers != null) {
|
| for (ConstructorInitializer initializer in initializers) {
|
| initializer.accept(this);
|
| }
|
| }
|
| body.accept(this);
|
| + if (serializeBodyExpr) {
|
| + if (body is Expression) {
|
| + b.bodyExpr = serializeConstExpr(_localClosureIndexMap, body);
|
| + } else {
|
| + // TODO(paulberry): serialize other types of function bodies.
|
| + }
|
| + }
|
| b.localFunctions = executables;
|
| b.localLabels = labels;
|
| b.localVariables = variables;
|
| + Map<int, int> localClosureIndexMap = _localClosureIndexMap;
|
| executables = oldExecutables;
|
| labels = oldLabels;
|
| variables = oldVariables;
|
| + _localClosureIndexMap = oldLocalClosureIndexMap;
|
| + return localClosureIndexMap;
|
| }
|
|
|
| /**
|
| @@ -703,15 +725,18 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
|
| /**
|
| * If the given [expression] is not `null`, serialize it as an
|
| * [UnlinkedExecutableBuilder], otherwise return `null`.
|
| + *
|
| + * If [serializeBodyExpr] is `true`, then the initializer expression is stored
|
| + * in [UnlinkedExecutableBuilder.bodyExpr].
|
| */
|
| UnlinkedExecutableBuilder serializeInitializerFunction(
|
| - Expression expression) {
|
| + Expression expression, bool serializeBodyExpr) {
|
| if (expression == null) {
|
| return null;
|
| }
|
| UnlinkedExecutableBuilder initializer =
|
| new UnlinkedExecutableBuilder(nameOffset: expression.offset);
|
| - serializeFunctionBody(initializer, null, expression);
|
| + serializeFunctionBody(initializer, null, expression, serializeBodyExpr);
|
| initializer.inferredReturnTypeSlot = assignSlot();
|
| return initializer;
|
| }
|
| @@ -893,18 +918,11 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
|
| b.documentationComment = serializeDocumentation(documentationComment);
|
| b.annotations = serializeAnnotations(annotations);
|
| b.codeRange = serializeCodeRange(variables.parent);
|
| - Map<int, int> localClosureIndexMap = _withLocalClosureIndexMap(() {
|
| - b.initializer = serializeInitializerFunction(variable.initializer);
|
| - });
|
| - if (variable.isConst ||
|
| + bool serializeBodyExpr = variable.isConst ||
|
| variable.isFinal && isField && !isDeclaredStatic ||
|
| - variables.type == null) {
|
| - Expression initializer = variable.initializer;
|
| - if (initializer != null) {
|
| - b.initializer.bodyExpr =
|
| - serializeConstExpr(localClosureIndexMap, initializer);
|
| - }
|
| - }
|
| + variables.type == null;
|
| + b.initializer =
|
| + serializeInitializerFunction(variable.initializer, serializeBodyExpr);
|
| if (variable.initializer != null &&
|
| (variables.isFinal || variables.isConst)) {
|
| b.propagatedTypeSlot = assignSlot();
|
| @@ -1023,9 +1041,8 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
|
| b.documentationComment = serializeDocumentation(node.documentationComment);
|
| b.annotations = serializeAnnotations(node.metadata);
|
| b.codeRange = serializeCodeRange(node);
|
| - Map<int, int> localClosureIndexMap = _withLocalClosureIndexMap(() {
|
| - serializeFunctionBody(b, node.initializers, node.body);
|
| - });
|
| + Map<int, int> localClosureIndexMap = serializeFunctionBody(
|
| + b, node.initializers, node.body, node.constKeyword != null);
|
| if (node.constKeyword != null) {
|
| Set<String> constructorParameterNames =
|
| node.parameters.parameters.map((p) => p.identifier.name).toSet();
|
| @@ -1044,13 +1061,8 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
|
| UnlinkedParamBuilder visitDefaultFormalParameter(
|
| DefaultFormalParameter node) {
|
| UnlinkedParamBuilder b = node.parameter.accept(this);
|
| - b.initializer = serializeInitializerFunction(node.defaultValue);
|
| + b.initializer = serializeInitializerFunction(node.defaultValue, true);
|
| if (node.defaultValue != null) {
|
| - // Closures can't appear inside default values, so we don't need a
|
| - // localClosureIndexMap.
|
| - Map<int, int> localClosureIndexMap = null;
|
| - b.initializer?.bodyExpr =
|
| - serializeConstExpr(localClosureIndexMap, node.defaultValue);
|
| b.defaultValueCode = node.defaultValue.toSource();
|
| }
|
| b.codeRange = serializeCodeRange(node);
|
| @@ -1317,21 +1329,6 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
|
| }
|
|
|
| /**
|
| - * Execute [callback], gathering any local closures in
|
| - * [_localClosureIndexMap], and return the resulting map.
|
| - *
|
| - * Properly handles cases where one closure is nested within another.
|
| - */
|
| - Map<int, int> _withLocalClosureIndexMap(void callback()) {
|
| - Map<int, int> prevLocalClosureIndexMap = _localClosureIndexMap;
|
| - _localClosureIndexMap = <int, int>{};
|
| - callback();
|
| - Map<int, int> localClosureIndexMap = _localClosureIndexMap;
|
| - _localClosureIndexMap = prevLocalClosureIndexMap;
|
| - return localClosureIndexMap;
|
| - }
|
| -
|
| - /**
|
| * Helper method to determine if a given [typeName] refers to `dynamic`.
|
| */
|
| static bool isDynamic(TypeName typeName) {
|
|
|