Chromium Code Reviews| 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 8b8d5a23074bcfebf51cf0a685a522af2d7f1fae..baf0614901c622f5b65f32a703ca7236f8a51fe1 100644 |
| --- a/pkg/analyzer/lib/src/summary/summarize_ast.dart |
| +++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart |
| @@ -29,12 +29,21 @@ class _ConstExprSerializer extends AbstractConstExprSerializer { |
| final _SummarizeAstVisitor visitor; |
| /** |
| + * If the expression being serialized can contain closures, map whose |
| + * keys are the offsets of local function nodes representing those closures, |
| + * and whose values are indices of those local functions relative to their |
| + * siblings. |
| + */ |
| + final Map<int, int> localClosureIndexMap; |
| + |
| + /** |
| * If a constructor initializer expression is being serialized, the names of |
| * the constructor parameters. Otherwise `null`. |
| */ |
| final Set<String> constructorParameterNames; |
| - _ConstExprSerializer(this.visitor, this.constructorParameterNames); |
| + _ConstExprSerializer( |
| + this.visitor, this.localClosureIndexMap, this.constructorParameterNames); |
| @override |
| bool isConstructorParameterName(String name) { |
| @@ -74,6 +83,18 @@ class _ConstExprSerializer extends AbstractConstExprSerializer { |
| } |
| } |
| + @override |
| + List<int> serializeFunctionExpression(FunctionExpression functionExpression) { |
| + int localIndex; |
| + if (localClosureIndexMap == null) { |
| + return null; |
| + } else { |
| + localIndex = localClosureIndexMap[functionExpression.offset]; |
| + assert(localIndex != null); |
| + return <int>[0, localIndex]; |
| + } |
| + } |
| + |
| EntityRefBuilder serializeIdentifier(Identifier identifier) { |
| EntityRefBuilder b = new EntityRefBuilder(); |
| if (identifier is SimpleIdentifier) { |
| @@ -317,6 +338,14 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor { |
| Block enclosingBlock = null; |
| /** |
| + * If an expression is being serialized which can contain closures, map whose |
| + * keys are the offsets of local function nodes representing those closures, |
| + * and whose values are indices of those local functions relative to their |
| + * siblings. |
| + */ |
| + Map<int, int> _localClosureIndexMap; |
| + |
| + /** |
| * Create a slot id for storing a propagated or inferred type or const cycle |
| * info. |
| */ |
| @@ -359,7 +388,9 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor { |
| return const <UnlinkedConstBuilder>[]; |
| } |
| return annotations.map((Annotation a) { |
| - _ConstExprSerializer serializer = new _ConstExprSerializer(this, null); |
| + var localClosureIndexMap = null; // TODO(paulberry): fix. |
|
scheglov
2016/05/10 21:47:03
Do we want to have types for these variables?
Paul Berry
2016/05/10 22:04:15
Good point. Fixed.
|
| + _ConstExprSerializer serializer = |
| + new _ConstExprSerializer(this, localClosureIndexMap, null); |
| serializer.serializeAnnotation(a); |
| return serializer.toBuilder(); |
| }).toList(); |
| @@ -487,10 +518,11 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor { |
| /** |
| * Serialize the given [expression], creating an [UnlinkedConstBuilder]. |
| */ |
| - UnlinkedConstBuilder serializeConstExpr(Expression expression, |
| + UnlinkedConstBuilder serializeConstExpr( |
| + Map<int, int> localClosureIndexMap, Expression expression, |
| [Set<String> constructorParameterNames]) { |
| - _ConstExprSerializer serializer = |
| - new _ConstExprSerializer(this, constructorParameterNames); |
| + _ConstExprSerializer serializer = new _ConstExprSerializer( |
| + this, localClosureIndexMap, constructorParameterNames); |
| serializer.serialize(expression); |
| return serializer.toBuilder(); |
| } |
| @@ -850,12 +882,15 @@ 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 || |
| variable.isFinal && isField && !isDeclaredStatic || |
| variables.type == null) { |
| Expression initializer = variable.initializer; |
| if (initializer != null) { |
| - b.constExpr = serializeConstExpr(initializer); |
| + b.constExpr = serializeConstExpr(localClosureIndexMap, initializer); |
| } |
| } |
| if (variable.initializer != null && |
| @@ -869,7 +904,6 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor { |
| } |
| b.visibleOffset = scopeNode?.offset; |
| b.visibleLength = scopeNode?.length; |
| - b.initializer = serializeInitializerFunction(variable.initializer); |
| this.variables.add(b); |
| } |
| } |
| @@ -953,9 +987,11 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor { |
| if (node.redirectedConstructor != null) { |
| b.isRedirectedConstructor = true; |
| TypeName typeName = node.redirectedConstructor.type; |
| - b.redirectedConstructor = new _ConstExprSerializer(this, null) |
| - .serializeConstructorRef(null, typeName.name, |
| - typeName.typeArguments, node.redirectedConstructor.name); |
| + var localClosureIndexMap = null; // TODO(paulberry): fix. |
| + b.redirectedConstructor = |
| + new _ConstExprSerializer(this, localClosureIndexMap, null) |
| + .serializeConstructorRef(null, typeName.name, |
| + typeName.typeArguments, node.redirectedConstructor.name); |
| } |
| } else { |
| for (ConstructorInitializer initializer in node.initializers) { |
| @@ -976,10 +1012,12 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor { |
| if (node.constKeyword != null) { |
| Set<String> constructorParameterNames = |
| node.parameters.parameters.map((p) => p.identifier.name).toSet(); |
| + var localClosureIndexMap = null; // TODO(paulberry): fix. |
| b.constantInitializers = node.initializers |
| .map((ConstructorInitializer initializer) => |
| serializeConstructorInitializer(initializer, (Expression expr) { |
| - return serializeConstExpr(expr, constructorParameterNames); |
| + return serializeConstExpr( |
| + localClosureIndexMap, expr, constructorParameterNames); |
| })) |
| .toList(); |
| } |
| @@ -992,7 +1030,9 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor { |
| DefaultFormalParameter node) { |
| UnlinkedParamBuilder b = node.parameter.accept(this); |
| if (node.defaultValue != null) { |
| - b.defaultValue = serializeConstExpr(node.defaultValue); |
| + var localClosureIndexMap = null; // TODO(paulberry): fix. |
| + b.defaultValue = |
| + serializeConstExpr(localClosureIndexMap, node.defaultValue); |
| b.defaultValueCode = node.defaultValue.toSource(); |
| } |
| b.initializer = serializeInitializerFunction(node.defaultValue); |
| @@ -1095,6 +1135,9 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor { |
| @override |
| void visitFunctionExpression(FunctionExpression node) { |
| if (node.parent is! FunctionDeclaration) { |
| + if (_localClosureIndexMap != null) { |
| + _localClosureIndexMap[node.offset] = executables.length; |
| + } |
| executables.add(serializeExecutable( |
| node, |
| null, |
| @@ -1257,6 +1300,21 @@ 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) { |