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

Unified Diff: packages/analyzer/lib/src/summary/summarize_ast.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: packages/analyzer/lib/src/summary/summarize_ast.dart
diff --git a/packages/analyzer/lib/src/summary/summarize_ast.dart b/packages/analyzer/lib/src/summary/summarize_ast.dart
new file mode 100644
index 0000000000000000000000000000000000000000..82d596e55a91cfbb507f9ba248fb9051cbaccfb9
--- /dev/null
+++ b/packages/analyzer/lib/src/summary/summarize_ast.dart
@@ -0,0 +1,1400 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library serialization.summarize_ast;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/type.dart' show DartType;
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/public_namespace_computer.dart';
+import 'package:analyzer/src/summary/summarize_const_expr.dart';
+
+/**
+ * Serialize all the declarations in [compilationUnit] to an unlinked summary.
+ */
+UnlinkedUnitBuilder serializeAstUnlinked(CompilationUnit compilationUnit) {
+ return new _SummarizeAstVisitor().serializeCompilationUnit(compilationUnit);
+}
+
+/**
+ * Instances of this class keep track of intermediate state during
+ * serialization of a single constant [Expression].
+ */
+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 the expression being serialized appears inside a function body, the names
+ * of parameters that are in scope. Otherwise `null`.
+ */
+ final Set<String> parameterNames;
+
+ _ConstExprSerializer(
+ this.visitor, this.localClosureIndexMap, this.parameterNames);
+
+ @override
+ bool isParameterName(String name) {
+ return parameterNames?.contains(name) ?? false;
+ }
+
+ @override
+ void serializeAnnotation(Annotation annotation) {
+ if (annotation.arguments == null) {
+ assert(annotation.constructorName == null);
+ serialize(annotation.name);
+ } else {
+ Identifier name = annotation.name;
+ EntityRefBuilder constructor;
+ if (name is PrefixedIdentifier && annotation.constructorName == null) {
+ constructor =
+ serializeConstructorRef(null, name.prefix, null, name.identifier);
+ } else {
+ constructor = serializeConstructorRef(
+ null, annotation.name, null, annotation.constructorName);
+ }
+ serializeInstanceCreation(constructor, annotation.arguments);
+ }
+ }
+
+ @override
+ EntityRefBuilder serializeConstructorRef(DartType type, Identifier typeName,
+ TypeArgumentList typeArguments, SimpleIdentifier name) {
+ EntityRefBuilder typeBuilder = serializeType(type, typeName, typeArguments);
+ if (name == null) {
+ return typeBuilder;
+ } else {
+ int nameRef =
+ visitor.serializeReference(typeBuilder.reference, name.name);
+ return new EntityRefBuilder(
+ reference: nameRef, typeArguments: typeBuilder.typeArguments);
+ }
+ }
+
+ @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) {
+ int index = visitor.serializeSimpleReference(identifier.name,
+ allowTypeParameter: true);
+ if (index < 0) {
+ b.paramReference = -index;
+ } else {
+ b.reference = index;
+ }
+ } else if (identifier is PrefixedIdentifier) {
+ int prefix = visitor.serializeSimpleReference(identifier.prefix.name);
+ b.reference =
+ visitor.serializeReference(prefix, identifier.identifier.name);
+ } else {
+ throw new StateError(
+ 'Unexpected identifier type: ${identifier.runtimeType}');
+ }
+ return b;
+ }
+
+ @override
+ EntityRefBuilder serializeIdentifierSequence(Expression expr) {
+ if (expr is Identifier) {
+ AstNode parent = expr.parent;
+ if (parent is MethodInvocation &&
+ parent.methodName == expr &&
+ parent.target != null) {
+ int targetId = serializeIdentifierSequence(parent.target).reference;
+ int nameId = visitor.serializeReference(targetId, expr.name);
+ return new EntityRefBuilder(reference: nameId);
+ }
+ return serializeIdentifier(expr);
+ }
+ if (expr is PropertyAccess) {
+ int targetId = serializeIdentifierSequence(expr.target).reference;
+ int nameId = visitor.serializeReference(targetId, expr.propertyName.name);
+ return new EntityRefBuilder(reference: nameId);
+ } else {
+ throw new StateError('Unexpected node type: ${expr.runtimeType}');
+ }
+ }
+
+ @override
+ EntityRefBuilder serializeType(
+ DartType type, Identifier name, TypeArgumentList arguments) {
+ return visitor.serializeType(name, arguments);
+ }
+}
+
+/**
+ * A [_Scope] represents a set of name/value pairs defined locally within a
+ * limited span of a compilation unit. (Note that the spec also uses the term
+ * "scope" to refer to the set of names defined at top level within a
+ * compilation unit, but we do not use [_Scope] for that purpose).
+ */
+class _Scope {
+ /**
+ * Names defined in this scope, and their meanings.
+ */
+ Map<String, _ScopedEntity> _definedNames = <String, _ScopedEntity>{};
+
+ /**
+ * Look up the meaning associated with the given [name], and return it. If
+ * [name] is not defined in this scope, return `null`.
+ */
+ _ScopedEntity operator [](String name) => _definedNames[name];
+
+ /**
+ * Let the given [name] refer to [entity] within this scope.
+ */
+ void operator []=(String name, _ScopedEntity entity) {
+ _definedNames[name] = entity;
+ }
+}
+
+/**
+ * A [_ScopedClassMember] is a [_ScopedEntity] refers to a member of a class.
+ */
+class _ScopedClassMember extends _ScopedEntity {
+ /**
+ * The name of the class.
+ */
+ final String className;
+
+ _ScopedClassMember(this.className);
+}
+
+/**
+ * Base class for entities that can live inside a scope.
+ */
+abstract class _ScopedEntity {}
+
+/**
+ * A [_ScopedTypeParameter] is a [_ScopedEntity] that refers to a type
+ * parameter of a class, typedef, or executable.
+ */
+class _ScopedTypeParameter extends _ScopedEntity {
+ /**
+ * Index of the type parameter within this scope. Since summaries use De
+ * Bruijn indices to refer to type parameters, which count upwards from the
+ * innermost bound name, the last type parameter in the scope has an index of
+ * 1, and each preceding type parameter has the next higher index.
+ */
+ final int index;
+
+ _ScopedTypeParameter(this.index);
+}
+
+/**
+ * Visitor used to create a summary from an AST.
+ */
+class _SummarizeAstVisitor extends RecursiveAstVisitor {
+ /**
+ * List of objects which should be written to [UnlinkedUnit.classes].
+ */
+ final List<UnlinkedClassBuilder> classes = <UnlinkedClassBuilder>[];
+
+ /**
+ * List of objects which should be written to [UnlinkedUnit.enums].
+ */
+ final List<UnlinkedEnumBuilder> enums = <UnlinkedEnumBuilder>[];
+
+ /**
+ * List of objects which should be written to [UnlinkedUnit.executables],
+ * [UnlinkedClass.executables] or [UnlinkedExecutable.localFunctions].
+ */
+ List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[];
+
+ /**
+ * List of objects which should be written to [UnlinkedUnit.exports].
+ */
+ final List<UnlinkedExportNonPublicBuilder> exports =
+ <UnlinkedExportNonPublicBuilder>[];
+
+ /**
+ * List of objects which should be written to
+ * [UnlinkedExecutable.localLabels].
+ */
+ List<UnlinkedLabelBuilder> labels = <UnlinkedLabelBuilder>[];
+
+ /**
+ * List of objects which should be written to [UnlinkedUnit.parts].
+ */
+ final List<UnlinkedPartBuilder> parts = <UnlinkedPartBuilder>[];
+
+ /**
+ * List of objects which should be written to [UnlinkedUnit.typedefs].
+ */
+ final List<UnlinkedTypedefBuilder> typedefs = <UnlinkedTypedefBuilder>[];
+
+ /**
+ * List of objects which should be written to [UnlinkedUnit.variables],
+ * [UnlinkedClass.fields] or [UnlinkedExecutable.localVariables].
+ */
+ List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[];
+
+ /**
+ * The unlinked portion of the "imports table". This is the list of objects
+ * which should be written to [UnlinkedUnit.imports].
+ */
+ final List<UnlinkedImportBuilder> unlinkedImports = <UnlinkedImportBuilder>[];
+
+ /**
+ * The unlinked portion of the "references table". This is the list of
+ * objects which should be written to [UnlinkedUnit.references].
+ */
+ final List<UnlinkedReferenceBuilder> unlinkedReferences =
+ <UnlinkedReferenceBuilder>[new UnlinkedReferenceBuilder()];
+
+ /**
+ * Map associating names used as prefixes in this compilation unit with their
+ * associated indices into [UnlinkedUnit.references].
+ */
+ final Map<String, int> prefixIndices = <String, int>{};
+
+ /**
+ * List of [_Scope]s currently in effect. This is used to resolve type names
+ * to type parameters within classes, typedefs, and executables, as well as
+ * references to class members.
+ */
+ final List<_Scope> scopes = <_Scope>[];
+
+ /**
+ * True if 'dart:core' has been explicitly imported.
+ */
+ bool hasCoreBeenImported = false;
+
+ /**
+ * Names referenced by this compilation unit. Structured as a map from
+ * prefix index to (map from name to reference table index), where "prefix
+ * index" means the index into [UnlinkedUnit.references] of the prefix (or
+ * `null` if there is no prefix), and "reference table index" means the index
+ * into [UnlinkedUnit.references] for the name itself.
+ */
+ final Map<int, Map<String, int>> nameToReference = <int, Map<String, int>>{};
+
+ /**
+ * True if the 'dart:core' library is been summarized.
+ */
+ bool isCoreLibrary = false;
+
+ /**
+ * If the library has a library directive, the library name derived from it.
+ * Otherwise `null`.
+ */
+ String libraryName;
+
+ /**
+ * If the library has a library directive, the offset of the library name.
+ * Otherwise `null`.
+ */
+ int libraryNameOffset;
+
+ /**
+ * If the library has a library directive, the length of the library name, as
+ * it appears in the source file. Otherwise `null`.
+ */
+ int libraryNameLength;
+
+ /**
+ * If the library has a library directive, the documentation comment for it
+ * (if any). Otherwise `null`.
+ */
+ UnlinkedDocumentationCommentBuilder libraryDocumentationComment;
+
+ /**
+ * If the library has a library directive, the annotations for it (if any).
+ * Otherwise `null`.
+ */
+ List<UnlinkedConst> libraryAnnotations = const <UnlinkedConstBuilder>[];
+
+ /**
+ * The number of slot ids which have been assigned to this compilation unit.
+ */
+ int numSlots = 0;
+
+ /**
+ * The [Block] that is being visited now, or `null` for non-local contexts.
+ */
+ 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;
+
+ /**
+ * Indicates whether closure function bodies should be serialized. This flag
+ * is set while visiting the bodies of initializer expressions that will be
+ * needed by type inference.
+ */
+ bool _serializeClosureBodyExprs = false;
+
+ /**
+ * If a closure function body is being serialized, the set of closure
+ * parameter names which are currently in scope. Otherwise `null`.
+ */
+ Set<String> _parameterNames;
+
+ /**
+ * Indicates whether parameters found during visitors might inherit
+ * covariance.
+ */
+ bool _parametersMayInheritCovariance = false;
+
+ /**
+ * Create a slot id for storing a propagated or inferred type or const cycle
+ * info.
+ */
+ int assignSlot() => ++numSlots;
+
+ /**
+ * Build a [_Scope] object containing the names defined within the body of a
+ * class declaration.
+ */
+ _Scope buildClassMemberScope(
+ String className, NodeList<ClassMember> members) {
+ _Scope scope = new _Scope();
+ for (ClassMember member in members) {
+ if (member is MethodDeclaration) {
+ if (member.isSetter || member.isOperator) {
+ // We don't have to handle setters or operators because the only
+ // things we look up are type names and identifiers.
+ } else {
+ scope[member.name.name] = new _ScopedClassMember(className);
+ }
+ } else if (member is FieldDeclaration) {
+ for (VariableDeclaration field in member.fields.variables) {
+ // A field declaration introduces two names, one with a trailing `=`.
+ // We don't have to worry about the one with a trailing `=` because
+ // the only things we look up are type names and identifiers.
+ scope[field.name.name] = new _ScopedClassMember(className);
+ }
+ }
+ }
+ return scope;
+ }
+
+ /**
+ * Serialize the given list of [annotations]. If there are no annotations,
+ * the empty list is returned.
+ */
+ List<UnlinkedConstBuilder> serializeAnnotations(
+ NodeList<Annotation> annotations) {
+ if (annotations == null || annotations.isEmpty) {
+ return const <UnlinkedConstBuilder>[];
+ }
+ return annotations.map((Annotation a) {
+ // Closures can't appear inside annotations, so we don't need a
+ // localClosureIndexMap.
+ Map<int, int> localClosureIndexMap = null;
+ _ConstExprSerializer serializer =
+ new _ConstExprSerializer(this, localClosureIndexMap, null);
+ serializer.serializeAnnotation(a);
+ return serializer.toBuilder();
+ }).toList();
+ }
+
+ /**
+ * Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass]
+ * and store the result in [classes].
+ */
+ void serializeClass(
+ AstNode node,
+ Token abstractKeyword,
+ String name,
+ int nameOffset,
+ TypeParameterList typeParameters,
+ TypeName superclass,
+ WithClause withClause,
+ ImplementsClause implementsClause,
+ NodeList<ClassMember> members,
+ bool isMixinApplication,
+ Comment documentationComment,
+ NodeList<Annotation> annotations) {
+ int oldScopesLength = scopes.length;
+ List<UnlinkedExecutableBuilder> oldExecutables = executables;
+ executables = <UnlinkedExecutableBuilder>[];
+ List<UnlinkedVariableBuilder> oldVariables = variables;
+ variables = <UnlinkedVariableBuilder>[];
+ _TypeParameterScope typeParameterScope = new _TypeParameterScope();
+ scopes.add(typeParameterScope);
+ UnlinkedClassBuilder b = new UnlinkedClassBuilder();
+ b.name = name;
+ b.nameOffset = nameOffset;
+ b.isMixinApplication = isMixinApplication;
+ b.typeParameters =
+ serializeTypeParameters(typeParameters, typeParameterScope);
+ if (superclass != null) {
+ b.supertype = serializeTypeName(superclass);
+ } else {
+ b.hasNoSupertype = isCoreLibrary && name == 'Object';
+ }
+ if (withClause != null) {
+ b.mixins = withClause.mixinTypes.map(serializeTypeName).toList();
+ }
+ if (implementsClause != null) {
+ b.interfaces =
+ implementsClause.interfaces.map(serializeTypeName).toList();
+ }
+ if (members != null) {
+ scopes.add(buildClassMemberScope(name, members));
+ for (ClassMember member in members) {
+ member.accept(this);
+ }
+ scopes.removeLast();
+ }
+ b.executables = executables;
+ b.fields = variables;
+ b.isAbstract = abstractKeyword != null;
+ b.documentationComment = serializeDocumentation(documentationComment);
+ b.annotations = serializeAnnotations(annotations);
+ b.codeRange = serializeCodeRange(node);
+ classes.add(b);
+ scopes.removeLast();
+ assert(scopes.length == oldScopesLength);
+ executables = oldExecutables;
+ variables = oldVariables;
+ }
+
+ /**
+ * Create a [CodeRangeBuilder] for the given [node].
+ */
+ CodeRangeBuilder serializeCodeRange(AstNode node) {
+ return new CodeRangeBuilder(offset: node.offset, length: node.length);
+ }
+
+ /**
+ * Serialize a [Combinator] into an [UnlinkedCombinator].
+ */
+ UnlinkedCombinatorBuilder serializeCombinator(Combinator combinator) {
+ UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder();
+ if (combinator is ShowCombinator) {
+ b.shows =
+ combinator.shownNames.map((SimpleIdentifier id) => id.name).toList();
+ b.offset = combinator.offset;
+ b.end = combinator.end;
+ } else if (combinator is HideCombinator) {
+ b.hides =
+ combinator.hiddenNames.map((SimpleIdentifier id) => id.name).toList();
+ } else {
+ throw new StateError(
+ 'Unexpected combinator type: ${combinator.runtimeType}');
+ }
+ return b;
+ }
+
+ /**
+ * Main entry point for serializing an AST.
+ */
+ UnlinkedUnitBuilder serializeCompilationUnit(
+ CompilationUnit compilationUnit) {
+ compilationUnit.directives.accept(this);
+ if (!hasCoreBeenImported) {
+ unlinkedImports.add(new UnlinkedImportBuilder(isImplicit: true));
+ }
+ compilationUnit.declarations.accept(this);
+ UnlinkedUnitBuilder b = new UnlinkedUnitBuilder();
+ b.lineStarts = compilationUnit.lineInfo?.lineStarts;
+ b.libraryName = libraryName;
+ b.libraryNameOffset = libraryNameOffset;
+ b.libraryNameLength = libraryNameLength;
+ b.libraryDocumentationComment = libraryDocumentationComment;
+ b.libraryAnnotations = libraryAnnotations;
+ b.codeRange = serializeCodeRange(compilationUnit);
+ b.classes = classes;
+ b.enums = enums;
+ b.executables = executables;
+ b.exports = exports;
+ b.imports = unlinkedImports;
+ b.parts = parts;
+ b.references = unlinkedReferences;
+ b.typedefs = typedefs;
+ b.variables = variables;
+ b.publicNamespace = computePublicNamespace(compilationUnit);
+ return b;
+ }
+
+ /**
+ * Serialize the given [expression], creating an [UnlinkedConstBuilder].
+ */
+ UnlinkedConstBuilder serializeConstExpr(
+ Map<int, int> localClosureIndexMap, Expression expression,
+ [Set<String> parameterNames]) {
+ _ConstExprSerializer serializer =
+ new _ConstExprSerializer(this, localClosureIndexMap, parameterNames);
+ serializer.serialize(expression);
+ return serializer.toBuilder();
+ }
+
+ /**
+ * Serialize the given [declaredIdentifier] into [UnlinkedVariable], and
+ * store it in [variables].
+ */
+ void serializeDeclaredIdentifier(
+ AstNode scopeNode,
+ Comment documentationComment,
+ NodeList<Annotation> annotations,
+ bool isFinal,
+ bool isConst,
+ TypeName type,
+ bool assignPropagatedTypeSlot,
+ SimpleIdentifier declaredIdentifier) {
+ UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
+ b.isFinal = isFinal;
+ b.isConst = isConst;
+ b.name = declaredIdentifier.name;
+ b.nameOffset = declaredIdentifier.offset;
+ b.type = serializeTypeName(type);
+ b.documentationComment = serializeDocumentation(documentationComment);
+ b.annotations = serializeAnnotations(annotations);
+ b.codeRange = serializeCodeRange(declaredIdentifier);
+ if (assignPropagatedTypeSlot) {
+ b.propagatedTypeSlot = assignSlot();
+ }
+ b.visibleOffset = scopeNode?.offset;
+ b.visibleLength = scopeNode?.length;
+ this.variables.add(b);
+ }
+
+ /**
+ * Serialize a [Comment] node into an [UnlinkedDocumentationComment] object.
+ */
+ UnlinkedDocumentationCommentBuilder serializeDocumentation(
+ Comment documentationComment) {
+ if (documentationComment == null) {
+ return null;
+ }
+ String text = documentationComment.tokens
+ .map((Token t) => t.toString())
+ .join()
+ .replaceAll('\r\n', '\n');
+ return new UnlinkedDocumentationCommentBuilder(text: text);
+ }
+
+ /**
+ * Serialize a [FunctionDeclaration] or [MethodDeclaration] into an
+ * [UnlinkedExecutable].
+ *
+ * If [serializeBodyExpr] is `true`, then the function definition is stored
+ * in [UnlinkedExecutableBuilder.bodyExpr].
+ */
+ UnlinkedExecutableBuilder serializeExecutable(
+ AstNode node,
+ String name,
+ int nameOffset,
+ bool isGetter,
+ bool isSetter,
+ TypeName returnType,
+ FormalParameterList formalParameters,
+ FunctionBody body,
+ bool isTopLevel,
+ bool isDeclaredStatic,
+ Comment documentationComment,
+ NodeList<Annotation> annotations,
+ TypeParameterList typeParameters,
+ bool isExternal,
+ bool serializeBodyExpr) {
+ int oldScopesLength = scopes.length;
+ _TypeParameterScope typeParameterScope = new _TypeParameterScope();
+ scopes.add(typeParameterScope);
+ UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
+ String nameString = name;
+ if (isGetter) {
+ b.kind = UnlinkedExecutableKind.getter;
+ } else if (isSetter) {
+ b.kind = UnlinkedExecutableKind.setter;
+ nameString = '$nameString=';
+ } else {
+ b.kind = UnlinkedExecutableKind.functionOrMethod;
+ }
+ b.isExternal = isExternal;
+ b.isAbstract = !isExternal && body is EmptyFunctionBody;
+ b.isAsynchronous = body.isAsynchronous;
+ b.isGenerator = body.isGenerator;
+ b.name = nameString;
+ b.nameOffset = nameOffset;
+ b.typeParameters =
+ serializeTypeParameters(typeParameters, typeParameterScope);
+ if (!isTopLevel) {
+ b.isStatic = isDeclaredStatic;
+ }
+ b.returnType = serializeTypeName(returnType);
+ bool isSemanticallyStatic = isTopLevel || isDeclaredStatic;
+ if (formalParameters != null) {
+ bool oldMayInheritCovariance = _parametersMayInheritCovariance;
+ _parametersMayInheritCovariance = !isTopLevel && !isDeclaredStatic;
+ b.parameters = formalParameters.parameters
+ .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
+ .toList();
+ _parametersMayInheritCovariance = oldMayInheritCovariance;
+ if (!isSemanticallyStatic) {
+ for (int i = 0; i < formalParameters.parameters.length; i++) {
+ if (!b.parameters[i].isFunctionTyped &&
+ b.parameters[i].type == null) {
+ b.parameters[i].inferredTypeSlot = assignSlot();
+ }
+ }
+ }
+ }
+ b.documentationComment = serializeDocumentation(documentationComment);
+ b.annotations = serializeAnnotations(annotations);
+ b.codeRange = serializeCodeRange(node);
+ if (returnType == null && !isSemanticallyStatic) {
+ b.inferredReturnTypeSlot = assignSlot();
+ }
+ b.visibleOffset = enclosingBlock?.offset;
+ b.visibleLength = enclosingBlock?.length;
+ Set<String> oldParameterNames = _parameterNames;
+ if (formalParameters != null && formalParameters.parameters.isNotEmpty) {
+ _parameterNames =
+ _parameterNames == null ? new Set<String>() : _parameterNames.toSet();
+ _parameterNames.addAll(formalParameters.parameters
+ .map((FormalParameter p) => p.identifier.name));
+ }
+ serializeFunctionBody(b, null, body, serializeBodyExpr);
+ _parameterNames = oldParameterNames;
+ scopes.removeLast();
+ assert(scopes.length == oldScopesLength);
+ return b;
+ }
+
+ /**
+ * Record local functions and variables into the given executable. The given
+ * [body] is usually an actual [FunctionBody], but may be an [Expression]
+ * when we process a synthetic variable initializer function.
+ *
+ * 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], and closures occurring inside
+ * [initializers] and [body] have their function bodies serialized as well.
+ *
+ * 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.
+ */
+ 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;
+ parameter.visibleLength = body.length;
+ }
+ }
+ List<UnlinkedExecutableBuilder> oldExecutables = executables;
+ List<UnlinkedLabelBuilder> oldLabels = labels;
+ List<UnlinkedVariableBuilder> oldVariables = variables;
+ Map<int, int> oldLocalClosureIndexMap = _localClosureIndexMap;
+ bool oldSerializeClosureBodyExprs = _serializeClosureBodyExprs;
+ executables = <UnlinkedExecutableBuilder>[];
+ labels = <UnlinkedLabelBuilder>[];
+ variables = <UnlinkedVariableBuilder>[];
+ _localClosureIndexMap = <int, int>{};
+ _serializeClosureBodyExprs = serializeBodyExpr;
+ 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, _parameterNames);
+ } else if (body is ExpressionFunctionBody) {
+ b.bodyExpr = serializeConstExpr(
+ _localClosureIndexMap, body.expression, _parameterNames);
+ } 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;
+ _serializeClosureBodyExprs = oldSerializeClosureBodyExprs;
+ return localClosureIndexMap;
+ }
+
+ /**
+ * Serialize the return type and parameters of a function-typed formal
+ * parameter and store them in [b].
+ */
+ void serializeFunctionTypedParameterDetails(UnlinkedParamBuilder b,
+ TypeName returnType, FormalParameterList parameters) {
+ EntityRefBuilder serializedReturnType = serializeTypeName(returnType);
+ if (serializedReturnType != null) {
+ b.type = serializedReturnType;
+ }
+ bool oldMayInheritCovariance = _parametersMayInheritCovariance;
+ _parametersMayInheritCovariance = false;
+ b.parameters = parameters.parameters
+ .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
+ .toList();
+ _parametersMayInheritCovariance = oldMayInheritCovariance;
+ }
+
+ /**
+ * 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, bool serializeBodyExpr) {
+ if (expression == null) {
+ return null;
+ }
+ UnlinkedExecutableBuilder initializer =
+ new UnlinkedExecutableBuilder(nameOffset: expression.offset);
+ serializeFunctionBody(initializer, null, expression, serializeBodyExpr);
+ initializer.inferredReturnTypeSlot = assignSlot();
+ return initializer;
+ }
+
+ /**
+ * Serialize a [FieldFormalParameter], [FunctionTypedFormalParameter], or
+ * [SimpleFormalParameter] into an [UnlinkedParam].
+ */
+ UnlinkedParamBuilder serializeParameter(NormalFormalParameter node) {
+ UnlinkedParamBuilder b = new UnlinkedParamBuilder();
+ b.name = node.identifier.name;
+ b.nameOffset = node.identifier.offset;
+ b.annotations = serializeAnnotations(node.metadata);
+ b.codeRange = serializeCodeRange(node);
+ if (_parametersMayInheritCovariance) {
+ b.inheritsCovariantSlot = assignSlot();
+ }
+ switch (node.kind) {
+ case ParameterKind.REQUIRED:
+ b.kind = UnlinkedParamKind.required;
+ break;
+ case ParameterKind.POSITIONAL:
+ b.kind = UnlinkedParamKind.positional;
+ break;
+ case ParameterKind.NAMED:
+ b.kind = UnlinkedParamKind.named;
+ break;
+ default:
+ throw new StateError('Unexpected parameter kind: ${node.kind}');
+ }
+ return b;
+ }
+
+ /**
+ * Serialize a reference to a top level name declared elsewhere, by adding an
+ * entry to the references table if necessary. If [prefixIndex] is not null,
+ * the reference is associated with the prefix having the given index in the
+ * references table.
+ */
+ int serializeReference(int prefixIndex, String name) => nameToReference
+ .putIfAbsent(prefixIndex, () => <String, int>{})
+ .putIfAbsent(name, () {
+ int index = unlinkedReferences.length;
+ unlinkedReferences.add(new UnlinkedReferenceBuilder(
+ prefixReference: prefixIndex, name: name));
+ return index;
+ });
+
+ /**
+ * Serialize a reference to a name declared either at top level or in a
+ * nested scope.
+ *
+ * If [allowTypeParameter] is `true`, then references to type
+ * parameters are allowed, and are returned as negative numbers.
+ */
+ int serializeSimpleReference(String name, {bool allowTypeParameter: false}) {
+ int indexOffset = 0;
+ for (int i = scopes.length - 1; i >= 0; i--) {
+ _Scope scope = scopes[i];
+ _ScopedEntity entity = scope[name];
+ if (entity != null) {
+ if (entity is _ScopedClassMember) {
+ return serializeReference(
+ serializeReference(null, entity.className), name);
+ } else if (allowTypeParameter && entity is _ScopedTypeParameter) {
+ int paramReference = indexOffset + entity.index;
+ return -paramReference;
+ } else {
+ // Invalid reference to a type parameter. Should never happen in
+ // legal Dart code.
+ // TODO(paulberry): could this exception ever be uncaught in illegal
+ // code?
+ throw new StateError('Invalid identifier reference');
+ }
+ }
+ if (scope is _TypeParameterScope) {
+ indexOffset += scope.length;
+ }
+ }
+ return serializeReference(null, name);
+ }
+
+ /**
+ * Serialize a type name (which might be defined in a nested scope, at top
+ * level within this library, or at top level within an imported library) to
+ * a [EntityRef]. Note that this method does the right thing if the
+ * name doesn't refer to an entity other than a type (e.g. a class member).
+ */
+ EntityRefBuilder serializeType(
+ Identifier identifier, TypeArgumentList typeArguments) {
+ if (identifier == null) {
+ return null;
+ } else {
+ EntityRefBuilder b = new EntityRefBuilder();
+ if (identifier is SimpleIdentifier) {
+ String name = identifier.name;
+ int indexOffset = 0;
+ for (int i = scopes.length - 1; i >= 0; i--) {
+ _Scope scope = scopes[i];
+ _ScopedEntity entity = scope[name];
+ if (entity != null) {
+ if (entity is _ScopedTypeParameter) {
+ b.paramReference = indexOffset + entity.index;
+ return b;
+ } else {
+ // None of the other things that can be declared in local scopes
+ // are types, so this is an error and should be treated as a
+ // reference to `dynamic`.
+ b.reference = serializeReference(null, 'dynamic');
+ return b;
+ }
+ }
+ if (scope is _TypeParameterScope) {
+ indexOffset += scope.length;
+ }
+ }
+ b.reference = serializeReference(null, name);
+ } else if (identifier is PrefixedIdentifier) {
+ int prefixIndex = prefixIndices.putIfAbsent(identifier.prefix.name,
+ () => serializeSimpleReference(identifier.prefix.name));
+ b.reference =
+ serializeReference(prefixIndex, identifier.identifier.name);
+ } else {
+ throw new StateError(
+ 'Unexpected identifier type: ${identifier.runtimeType}');
+ }
+ if (typeArguments != null) {
+ b.typeArguments =
+ typeArguments.arguments.map(serializeTypeName).toList();
+ }
+ return b;
+ }
+ }
+
+ /**
+ * Serialize a type name (which might be defined in a nested scope, at top
+ * level within this library, or at top level within an imported library) to
+ * a [EntityRef]. Note that this method does the right thing if the
+ * name doesn't refer to an entity other than a type (e.g. a class member).
+ */
+ EntityRefBuilder serializeTypeName(TypeName node) {
+ return serializeType(node?.name, node?.typeArguments);
+ }
+
+ /**
+ * Serialize the given [typeParameters] into a list of [UnlinkedTypeParam]s,
+ * and also store them in [typeParameterScope].
+ */
+ List<UnlinkedTypeParamBuilder> serializeTypeParameters(
+ TypeParameterList typeParameters,
+ _TypeParameterScope typeParameterScope) {
+ if (typeParameters != null) {
+ for (int i = 0; i < typeParameters.typeParameters.length; i++) {
+ TypeParameter typeParameter = typeParameters.typeParameters[i];
+ typeParameterScope[typeParameter.name.name] =
+ new _ScopedTypeParameter(typeParameters.typeParameters.length - i);
+ }
+ return typeParameters.typeParameters.map(visitTypeParameter).toList();
+ }
+ return const <UnlinkedTypeParamBuilder>[];
+ }
+
+ /**
+ * Serialize the given [variables] into [UnlinkedVariable]s, and store them
+ * in [this.variables].
+ */
+ void serializeVariables(
+ AstNode scopeNode,
+ VariableDeclarationList variables,
+ bool isDeclaredStatic,
+ Comment documentationComment,
+ NodeList<Annotation> annotations,
+ bool isField) {
+ for (VariableDeclaration variable in variables.variables) {
+ UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
+ b.isFinal = variables.isFinal;
+ b.isConst = variables.isConst;
+ b.isStatic = isDeclaredStatic;
+ b.name = variable.name.name;
+ b.nameOffset = variable.name.offset;
+ b.type = serializeTypeName(variables.type);
+ b.documentationComment = serializeDocumentation(documentationComment);
+ b.annotations = serializeAnnotations(annotations);
+ b.codeRange = serializeCodeRange(variables.parent);
+ bool serializeBodyExpr = variable.isConst ||
+ variable.isFinal && isField && !isDeclaredStatic ||
+ variables.type == null;
+ b.initializer =
+ serializeInitializerFunction(variable.initializer, serializeBodyExpr);
+ if (variable.initializer != null &&
+ (variables.isFinal || variables.isConst)) {
+ b.propagatedTypeSlot = assignSlot();
+ }
+ bool isSemanticallyStatic = !isField || isDeclaredStatic;
+ if (variables.type == null &&
+ (variable.initializer != null || !isSemanticallyStatic)) {
+ b.inferredTypeSlot = assignSlot();
+ }
+ b.visibleOffset = scopeNode?.offset;
+ b.visibleLength = scopeNode?.length;
+ this.variables.add(b);
+ }
+ }
+
+ @override
+ void visitBlock(Block node) {
+ Block oldBlock = enclosingBlock;
+ enclosingBlock = node;
+ super.visitBlock(node);
+ enclosingBlock = oldBlock;
+ }
+
+ @override
+ void visitCatchClause(CatchClause node) {
+ SimpleIdentifier exception = node.exceptionParameter;
+ SimpleIdentifier st = node.stackTraceParameter;
+ if (exception != null) {
+ serializeDeclaredIdentifier(
+ node, null, null, false, false, node.exceptionType, false, exception);
+ }
+ if (st != null) {
+ serializeDeclaredIdentifier(
+ node, null, null, false, false, null, false, st);
+ }
+ super.visitCatchClause(node);
+ }
+
+ @override
+ void visitClassDeclaration(ClassDeclaration node) {
+ TypeName superclass =
+ node.extendsClause == null ? null : node.extendsClause.superclass;
+ serializeClass(
+ node,
+ node.abstractKeyword,
+ node.name.name,
+ node.name.offset,
+ node.typeParameters,
+ superclass,
+ node.withClause,
+ node.implementsClause,
+ node.members,
+ false,
+ node.documentationComment,
+ node.metadata);
+ }
+
+ @override
+ void visitClassTypeAlias(ClassTypeAlias node) {
+ serializeClass(
+ node,
+ node.abstractKeyword,
+ node.name.name,
+ node.name.offset,
+ node.typeParameters,
+ node.superclass,
+ node.withClause,
+ node.implementsClause,
+ null,
+ true,
+ node.documentationComment,
+ node.metadata);
+ }
+
+ @override
+ void visitConstructorDeclaration(ConstructorDeclaration node) {
+ UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
+ if (node.name != null) {
+ b.name = node.name.name;
+ b.nameOffset = node.name.offset;
+ b.periodOffset = node.period.offset;
+ b.nameEnd = node.name.end;
+ } else {
+ b.nameOffset = node.returnType.offset;
+ }
+ b.parameters = node.parameters.parameters
+ .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
+ .toList();
+ b.kind = UnlinkedExecutableKind.constructor;
+ if (node.factoryKeyword != null) {
+ b.isFactory = true;
+ if (node.redirectedConstructor != null) {
+ b.isRedirectedConstructor = true;
+ TypeName typeName = node.redirectedConstructor.type;
+ // Closures can't appear inside factory constructor redirections, so we
+ // don't need a localClosureIndexMap.
+ Map<int, int> localClosureIndexMap = null;
+ b.redirectedConstructor =
+ new _ConstExprSerializer(this, localClosureIndexMap, null)
+ .serializeConstructorRef(null, typeName.name,
+ typeName.typeArguments, node.redirectedConstructor.name);
+ }
+ } else {
+ for (ConstructorInitializer initializer in node.initializers) {
+ if (initializer is RedirectingConstructorInvocation) {
+ b.isRedirectedConstructor = true;
+ b.redirectedConstructorName = initializer.constructorName?.name;
+ }
+ }
+ }
+ if (node.constKeyword != null) {
+ b.isConst = true;
+ b.constCycleSlot = assignSlot();
+ }
+ b.isExternal = node.externalKeyword != null;
+ b.documentationComment = serializeDocumentation(node.documentationComment);
+ b.annotations = serializeAnnotations(node.metadata);
+ b.codeRange = serializeCodeRange(node);
+ 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();
+ b.constantInitializers = node.initializers
+ .map((ConstructorInitializer initializer) =>
+ serializeConstructorInitializer(initializer, (Expression expr) {
+ return serializeConstExpr(
+ localClosureIndexMap, expr, constructorParameterNames);
+ }))
+ .toList();
+ }
+ executables.add(b);
+ }
+
+ @override
+ UnlinkedParamBuilder visitDefaultFormalParameter(
+ DefaultFormalParameter node) {
+ UnlinkedParamBuilder b =
+ node.parameter.accept(this) as UnlinkedParamBuilder;
+ b.initializer = serializeInitializerFunction(node.defaultValue, true);
+ if (node.defaultValue != null) {
+ b.defaultValueCode = node.defaultValue.toSource();
+ }
+ b.codeRange = serializeCodeRange(node);
+ return b;
+ }
+
+ @override
+ void visitEnumDeclaration(EnumDeclaration node) {
+ UnlinkedEnumBuilder b = new UnlinkedEnumBuilder();
+ b.name = node.name.name;
+ b.nameOffset = node.name.offset;
+ b.values = node.constants
+ .map((EnumConstantDeclaration value) => new UnlinkedEnumValueBuilder(
+ documentationComment:
+ serializeDocumentation(value.documentationComment),
+ name: value.name.name,
+ nameOffset: value.name.offset))
+ .toList();
+ b.documentationComment = serializeDocumentation(node.documentationComment);
+ b.annotations = serializeAnnotations(node.metadata);
+ b.codeRange = serializeCodeRange(node);
+ enums.add(b);
+ }
+
+ @override
+ void visitExportDirective(ExportDirective node) {
+ UnlinkedExportNonPublicBuilder b = new UnlinkedExportNonPublicBuilder(
+ uriOffset: node.uri.offset, uriEnd: node.uri.end, offset: node.offset);
+ b.annotations = serializeAnnotations(node.metadata);
+ exports.add(b);
+ }
+
+ @override
+ void visitFieldDeclaration(FieldDeclaration node) {
+ serializeVariables(null, node.fields, node.staticKeyword != null,
+ node.documentationComment, node.metadata, true);
+ }
+
+ @override
+ UnlinkedParamBuilder visitFieldFormalParameter(FieldFormalParameter node) {
+ UnlinkedParamBuilder b = serializeParameter(node);
+ b.isInitializingFormal = true;
+ if (node.type != null || node.parameters != null) {
+ b.isFunctionTyped = node.parameters != null;
+ if (node.parameters != null) {
+ serializeFunctionTypedParameterDetails(b, node.type, node.parameters);
+ } else {
+ b.type = serializeTypeName(node.type);
+ }
+ }
+ return b;
+ }
+
+ @override
+ void visitForEachStatement(ForEachStatement node) {
+ DeclaredIdentifier loopVariable = node.loopVariable;
+ if (loopVariable != null) {
+ serializeDeclaredIdentifier(
+ node,
+ loopVariable.documentationComment,
+ loopVariable.metadata,
+ loopVariable.isFinal,
+ loopVariable.isConst,
+ loopVariable.type,
+ true,
+ loopVariable.identifier);
+ }
+ super.visitForEachStatement(node);
+ }
+
+ @override
+ void visitForStatement(ForStatement node) {
+ VariableDeclarationList declaredVariables = node.variables;
+ if (declaredVariables != null) {
+ serializeVariables(node, declaredVariables, false, null, null, false);
+ }
+ super.visitForStatement(node);
+ }
+
+ @override
+ void visitFunctionDeclaration(FunctionDeclaration node) {
+ executables.add(serializeExecutable(
+ node,
+ node.name.name,
+ node.name.offset,
+ node.isGetter,
+ node.isSetter,
+ node.returnType,
+ node.functionExpression.parameters,
+ node.functionExpression.body,
+ true,
+ false,
+ node.documentationComment,
+ node.metadata,
+ node.functionExpression.typeParameters,
+ node.externalKeyword != null,
+ false));
+ }
+
+ @override
+ void visitFunctionExpression(FunctionExpression node) {
+ if (node.parent is! FunctionDeclaration) {
+ if (_localClosureIndexMap != null) {
+ _localClosureIndexMap[node.offset] = executables.length;
+ }
+ executables.add(serializeExecutable(
+ node,
+ null,
+ node.offset,
+ false,
+ false,
+ null,
+ node.parameters,
+ node.body,
+ false,
+ false,
+ null,
+ null,
+ node.typeParameters,
+ false,
+ _serializeClosureBodyExprs));
+ }
+ }
+
+ @override
+ void visitFunctionTypeAlias(FunctionTypeAlias node) {
+ int oldScopesLength = scopes.length;
+ _TypeParameterScope typeParameterScope = new _TypeParameterScope();
+ scopes.add(typeParameterScope);
+ UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
+ b.name = node.name.name;
+ b.nameOffset = node.name.offset;
+ b.typeParameters =
+ serializeTypeParameters(node.typeParameters, typeParameterScope);
+ EntityRefBuilder serializedReturnType = serializeTypeName(node.returnType);
+ if (serializedReturnType != null) {
+ b.returnType = serializedReturnType;
+ }
+ b.parameters = node.parameters.parameters
+ .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
+ .toList();
+ b.documentationComment = serializeDocumentation(node.documentationComment);
+ b.annotations = serializeAnnotations(node.metadata);
+ b.codeRange = serializeCodeRange(node);
+ typedefs.add(b);
+ scopes.removeLast();
+ assert(scopes.length == oldScopesLength);
+ }
+
+ @override
+ UnlinkedParamBuilder visitFunctionTypedFormalParameter(
+ FunctionTypedFormalParameter node) {
+ UnlinkedParamBuilder b = serializeParameter(node);
+ b.isFunctionTyped = true;
+ serializeFunctionTypedParameterDetails(b, node.returnType, node.parameters);
+ return b;
+ }
+
+ @override
+ void visitImportDirective(ImportDirective node) {
+ UnlinkedImportBuilder b = new UnlinkedImportBuilder();
+ b.annotations = serializeAnnotations(node.metadata);
+ if (node.uri.stringValue == 'dart:core') {
+ hasCoreBeenImported = true;
+ }
+ b.offset = node.offset;
+ b.combinators = node.combinators.map(serializeCombinator).toList();
+ b.configurations = node.configurations.map(serializeConfiguration).toList();
+ if (node.prefix != null) {
+ b.prefixReference = serializeReference(null, node.prefix.name);
+ b.prefixOffset = node.prefix.offset;
+ }
+ b.isDeferred = node.deferredKeyword != null;
+ b.uri = node.uri.stringValue;
+ b.uriOffset = node.uri.offset;
+ b.uriEnd = node.uri.end;
+ unlinkedImports.add(b);
+ }
+
+ @override
+ void visitLabel(Label node) {
+ AstNode parent = node.parent;
+ if (parent is! NamedExpression) {
+ labels.add(new UnlinkedLabelBuilder(
+ name: node.label.name,
+ nameOffset: node.offset,
+ isOnSwitchMember: parent is SwitchMember,
+ isOnSwitchStatement: parent is LabeledStatement &&
+ parent.statement is SwitchStatement));
+ }
+ }
+
+ @override
+ void visitLibraryDirective(LibraryDirective node) {
+ libraryName =
+ node.name.components.map((SimpleIdentifier id) => id.name).join('.');
+ libraryNameOffset = node.name.offset;
+ libraryNameLength = node.name.length;
+ isCoreLibrary = libraryName == 'dart.core';
+ libraryDocumentationComment =
+ serializeDocumentation(node.documentationComment);
+ libraryAnnotations = serializeAnnotations(node.metadata);
+ }
+
+ @override
+ void visitMethodDeclaration(MethodDeclaration node) {
+ executables.add(serializeExecutable(
+ node,
+ node.name.name,
+ node.name.offset,
+ node.isGetter,
+ node.isSetter,
+ node.returnType,
+ node.parameters,
+ node.body,
+ false,
+ node.isStatic,
+ node.documentationComment,
+ node.metadata,
+ node.typeParameters,
+ node.externalKeyword != null,
+ false));
+ }
+
+ @override
+ void visitPartDirective(PartDirective node) {
+ parts.add(new UnlinkedPartBuilder(
+ uriOffset: node.uri.offset,
+ uriEnd: node.uri.end,
+ annotations: serializeAnnotations(node.metadata)));
+ }
+
+ @override
+ void visitPartOfDirective(PartOfDirective node) {
+ isCoreLibrary = node.libraryName.name == 'dart.core';
+ }
+
+ @override
+ UnlinkedParamBuilder visitSimpleFormalParameter(SimpleFormalParameter node) {
+ UnlinkedParamBuilder b = serializeParameter(node);
+ b.type = serializeTypeName(node.type);
+ return b;
+ }
+
+ @override
+ void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ serializeVariables(null, node.variables, false, node.documentationComment,
+ node.metadata, false);
+ }
+
+ @override
+ UnlinkedTypeParamBuilder visitTypeParameter(TypeParameter node) {
+ UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder();
+ b.name = node.name.name;
+ b.nameOffset = node.name.offset;
+ if (node.bound != null) {
+ b.bound = serializeTypeName(node.bound);
+ }
+ b.annotations = serializeAnnotations(node.metadata);
+ b.codeRange = serializeCodeRange(node);
+ return b;
+ }
+
+ @override
+ void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+ serializeVariables(
+ enclosingBlock, node.variables, false, null, null, false);
+ }
+
+ /**
+ * Helper method to determine if a given [typeName] refers to `dynamic`.
+ */
+ static bool isDynamic(TypeName typeName) {
+ Identifier name = typeName.name;
+ return name is SimpleIdentifier && name.name == 'dynamic';
+ }
+}
+
+/**
+ * A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s.
+ */
+class _TypeParameterScope extends _Scope {
+ /**
+ * Get the number of [_ScopedTypeParameter]s defined in this
+ * [_TypeParameterScope].
+ */
+ int get length => _definedNames.length;
+}
« no previous file with comments | « packages/analyzer/lib/src/summary/resynthesize.dart ('k') | packages/analyzer/lib/src/summary/summarize_const_expr.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698