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

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

Issue 1602883003: Introduce code for computing an unlinked summary directly from an AST. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 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
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/summary_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
new file mode 100644
index 0000000000000000000000000000000000000000..642563cfc59bf58783180d3c8d42593a906075ef
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -0,0 +1,813 @@
+// 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/analyzer.dart';
+import 'package:analyzer/src/generated/ast.dart';
Brian Wilkerson 2016/01/19 17:53:44 nit: After this weekend, this library is now empty
Paul Berry 2016/01/19 18:21:48 Done.
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/public_namespace_computer.dart';
+
+/**
+ * Serialize all the declarations in [compilationUnit] to an unlinked summary.
+ */
+UnlinkedUnitBuilder serializeAstUnlinked(CompilationUnit compilationUnit) {
+ return new _SummarizeAstVisitor().serializeCompilationUnit(compilationUnit);
+}
+
+/**
+ * An [_OtherScopedEntity] is a [_ScopedEntity] that does not refer to a type
+ * parameter. Since we don't need to track any special information about these
+ * types of scoped entities, it is a singleton class.
+ */
+class _OtherScopedEntity extends _ScopedEntity {
+ static final _OtherScopedEntity _instance = new _OtherScopedEntity._();
+
+ factory _OtherScopedEntity() => _instance;
+
+ _OtherScopedEntity._();
+}
+
+/**
+ * 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;
+ }
+}
+
+/**
+ * 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 SimpleAstVisitor {
+ /**
+ * 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]
+ * or [UnlinkedClass.executables].
+ */
+ List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[];
Brian Wilkerson 2016/01/19 17:53:44 Seems strange that some lists are 'final' and some
Paul Berry 2016/01/19 18:21:48 `setters` and `variables` were the only lists that
+
+ /**
+ * List of objects which should be written to [UnlinkedUnit.exports].
+ */
+ List<UnlinkedExportNonPublicBuilder> exports =
+ <UnlinkedExportNonPublicBuilder>[];
+
+ /**
+ * List of objects which should be written to [UnlinkedUnit.parts].
+ */
+ 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] or
+ * [UnlinkedClass.fields].
+ */
+ 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()];
+
+ /**
+ * The [ClassDeclaration] currently being summarized, or `null` if we are not
+ * currently visiting a [ClassDeclaration].
+ */
+ ClassDeclaration currentClassDeclaration;
+
+ /**
+ * 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.
+ */
+ 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>>{};
+
+ /**
+ * 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). Othrwise `null`.
+ */
+ UnlinkedDocumentationCommentBuilder libraryDocumentationComment;
+
+ /**
+ * Build a [_Scope] object containing the names defined within the body of a
+ * class declaration.
+ */
+ _Scope buildClassMemberScope(NodeList<ClassMember> members) {
+ _Scope scope = new _Scope();
+ for (ClassMember member in members) {
+ // TODO(paulbery): consider replacing these if-tests with dynamic method
+ // dispatch.
+ if (member is MethodDeclaration) {
+ if (member.isSetter || member.isOperator) {
+ // We don't have to handle setters or operators because the only
+ // thing we look up is type names.
+ } else {
+ scope[member.name.name] = new _OtherScopedEntity();
+ }
+ } 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 thing we look up is type names.
+ scope[field.name.name] = new _OtherScopedEntity();
+ }
+ }
+ }
+ return scope;
+ }
+
+ /**
+ * Try to find a field with the given [name] in the current class declaration
+ * and return its type. If no field is found, or there isn't a current
+ * class declaration, return null.
+ */
+ TypeName getFieldType(String name) {
+ if (currentClassDeclaration == null) {
+ return null;
+ }
+ for (ClassMember member in currentClassDeclaration.members) {
+ if (member is FieldDeclaration) {
+ for (VariableDeclaration variable in member.fields.variables) {
+ if (variable.name.name == name) {
+ return member.fields.type;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass]
+ * and store the result in [classes].
+ */
+ void serializeClass(
+ Token abstractKeyword,
+ String name,
+ int nameOffset,
+ TypeParameterList typeParameters,
+ TypeName superclass,
+ WithClause withClause,
+ ImplementsClause implementsClause,
+ NodeList<ClassMember> members,
+ bool isMixinApplication,
+ Comment documentationComment) {
+ 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);
+ }
+ 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(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);
+ classes.add(b);
+ scopes.removeLast();
+ assert(scopes.length == oldScopesLength);
+ executables = oldExecutables;
+ variables = oldVariables;
+ }
+
+ /**
+ * 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();
+ } 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.libraryName = libraryName;
+ b.libraryNameOffset = libraryNameOffset;
+ b.libraryNameLength = libraryNameLength;
+ b.libraryDocumentationComment = libraryDocumentationComment;
+ 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 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,
+ offset: documentationComment.offset,
+ length: documentationComment.length);
+ }
+
+ /**
+ * Serialize a [FunctionDeclaration] or [MethodDeclaration] into an
+ * [UnlinkedExecutable].
+ */
+ UnlinkedExecutableBuilder serializeExecutable(
+ SimpleIdentifier name,
+ bool isGetter,
+ bool isSetter,
+ TypeName returnType,
+ FormalParameterList formalParameters,
+ FunctionBody body,
+ bool isTopLevel,
+ bool isStatic,
+ Comment documentationComment,
+ TypeParameterList typeParameters,
+ bool isExternal) {
+ int oldScopesLength = scopes.length;
+ _TypeParameterScope typeParameterScope = new _TypeParameterScope();
+ scopes.add(typeParameterScope);
+ UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
+ String nameString = name.name;
+ if (isGetter) {
+ b.kind = UnlinkedExecutableKind.getter;
+ } else if (isSetter) {
+ b.kind = UnlinkedExecutableKind.setter;
+ nameString = '$nameString=';
+ } else {
+ b.kind = UnlinkedExecutableKind.functionOrMethod;
+ }
+ b.isAbstract = body is EmptyFunctionBody;
+ b.name = nameString;
+ b.nameOffset = name.offset;
+ b.typeParameters =
+ serializeTypeParameters(typeParameters, typeParameterScope);
+ if (!isTopLevel) {
+ b.isStatic = isStatic;
+ }
+ b.returnType = serializeTypeName(returnType, allowVoid: true);
+ b.hasImplicitReturnType = returnType == null;
+ b.isExternal = isExternal;
+ if (formalParameters != null) {
+ b.parameters = formalParameters.parameters
+ .map((FormalParameter p) => p.accept(this))
+ .toList();
+ }
+ b.documentationComment = serializeDocumentation(documentationComment);
+ scopes.removeLast();
+ assert(scopes.length == oldScopesLength);
+ return b;
+ }
+
+ /**
+ * 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) {
+ UnlinkedTypeRefBuilder serializedReturnType =
+ serializeTypeName(returnType, allowVoid: true);
+ if (serializedReturnType != null) {
+ b.type = serializedReturnType;
+ }
+ b.parameters = parameters.parameters
+ .map((FormalParameter p) => p.accept(this))
+ .toList();
+ }
+
+ /**
+ * 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;
+ 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, () {
+ assert(name != 'dynamic');
+ int index = unlinkedReferences.length;
+ unlinkedReferences.add(new UnlinkedReferenceBuilder(
+ prefixReference: prefixIndex, name: name));
+ return index;
+ });
+
+ /**
+ * 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
+ * an [UnlinkedTypeRef]. 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).
+ */
+ UnlinkedTypeRefBuilder serializeTypeName(TypeName node,
+ {bool allowVoid: false}) {
+ UnlinkedTypeRefBuilder b = new UnlinkedTypeRefBuilder();
+ if (node != null) {
+ Identifier identifier = node.name;
+ 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`.
+ return b;
+ }
+ }
+ if (scope is _TypeParameterScope) {
+ indexOffset += scope.length;
+ }
+ }
+ if (allowVoid && name == 'void') {
+ return null;
+ }
+ if (name != 'dynamic') {
+ b.reference = serializeReference(null, name);
+ }
+ } else if (identifier is PrefixedIdentifier) {
+ int prefixIndex = prefixIndices.putIfAbsent(identifier.prefix.name,
+ () => serializeReference(null, identifier.prefix.name));
+ b.reference =
+ serializeReference(prefixIndex, identifier.identifier.name);
+ } else {
+ throw new StateError(
+ 'Unexpected identifier type: ${identifier.runtimeType}');
+ }
+ if (node.typeArguments != null &&
+ node.typeArguments.arguments.any(isNotDynamic)) {
+ b.typeArguments =
+ node.typeArguments.arguments.map(serializeTypeName).toList();
+ }
+ }
+ return b;
+ }
+
+ /**
+ * 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(VariableDeclarationList variables, bool isStatic,
+ Comment documentationComment) {
+ for (VariableDeclaration variable in variables.variables) {
+ UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
+ b.isFinal = variables.isFinal;
+ b.isConst = variables.isConst;
+ b.isStatic = isStatic;
+ b.name = variable.name.name;
+ b.nameOffset = variable.name.offset;
+ b.type = serializeTypeName(variables.type);
+ b.hasImplicitType = variables.type == null;
+ b.documentationComment = serializeDocumentation(documentationComment);
+ this.variables.add(b);
+ }
+ }
+
+ @override
+ void visitClassDeclaration(ClassDeclaration node) {
+ currentClassDeclaration = node;
+ TypeName superclass =
+ node.extendsClause == null ? null : node.extendsClause.superclass;
+ serializeClass(
+ node.abstractKeyword,
+ node.name.name,
+ node.name.offset,
+ node.typeParameters,
+ superclass,
+ node.withClause,
+ node.implementsClause,
+ node.members,
+ false,
+ node.documentationComment);
+ currentClassDeclaration = null;
+ }
+
+ @override
+ void visitClassTypeAlias(ClassTypeAlias node) {
+ serializeClass(
+ node.abstractKeyword,
+ node.name.name,
+ node.name.offset,
+ node.typeParameters,
+ node.superclass,
+ node.withClause,
+ node.implementsClause,
+ null,
+ true,
+ node.documentationComment);
+ }
+
+ @override
+ void visitConstructorDeclaration(ConstructorDeclaration node) {
+ UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
+ if (node.name != null) {
+ b.name = node.name.name;
+ b.nameOffset = node.name.offset;
+ } else {
+ b.nameOffset = node.returnType.offset;
+ }
+ b.parameters = node.parameters.parameters
+ .map((FormalParameter p) => p.accept(this))
+ .toList();
+ b.kind = UnlinkedExecutableKind.constructor;
+ b.isFactory = node.factoryKeyword != null;
+ b.isConst = node.constKeyword != null;
+ b.isExternal = node.externalKeyword != null;
+ b.documentationComment = serializeDocumentation(node.documentationComment);
+ executables.add(b);
+ }
+
+ @override
+ UnlinkedParamBuilder visitDefaultFormalParameter(
+ DefaultFormalParameter node) {
+ return node.parameter.accept(this);
+ }
+
+ @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(
+ name: value.name.name, nameOffset: value.name.offset))
+ .toList();
+ b.documentationComment = serializeDocumentation(node.documentationComment);
+ enums.add(b);
+ }
+
+ @override
+ void visitExportDirective(ExportDirective node) {
+ UnlinkedExportNonPublicBuilder b = new UnlinkedExportNonPublicBuilder(
+ uriOffset: node.uri.offset, uriEnd: node.uri.end, offset: node.offset);
+ exports.add(b);
+ }
+
+ @override
+ void visitFieldDeclaration(FieldDeclaration node) {
+ serializeVariables(
+ node.fields, node.staticKeyword != null, node.documentationComment);
+ }
+
+ @override
+ UnlinkedParamBuilder visitFieldFormalParameter(FieldFormalParameter node) {
+ UnlinkedParamBuilder b = serializeParameter(node);
+ b.isInitializingFormal = true;
+ if (node.type == null && node.parameters == null) {
+ b.hasImplicitType = true;
+ } else {
+ b.isFunctionTyped = node.parameters != null;
+ if (node.parameters != null) {
+ serializeFunctionTypedParameterDetails(b, node.type, node.parameters);
+ } else {
+ TypeName typeName = node.type;
+ if (typeName == null) {
+ typeName = getFieldType(node.identifier.name);
+ }
+ b.type = serializeTypeName(typeName);
+ }
+ }
+ return b;
+ }
+
+ @override
+ void visitFunctionDeclaration(FunctionDeclaration node) {
+ executables.add(serializeExecutable(
+ node.name,
+ node.isGetter,
+ node.isSetter,
+ node.returnType,
+ node.functionExpression.parameters,
+ node.functionExpression.body,
+ true,
+ false,
+ node.documentationComment,
+ node.functionExpression.typeParameters,
+ node.externalKeyword != null));
+ }
+
+ @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);
+ UnlinkedTypeRefBuilder serializedReturnType =
+ serializeTypeName(node.returnType, allowVoid: true);
+ if (serializedReturnType != null) {
+ b.returnType = serializedReturnType;
+ }
+ b.parameters = node.parameters.parameters
+ .map((FormalParameter p) => p.accept(this))
+ .toList();
+ b.documentationComment = serializeDocumentation(node.documentationComment);
+ 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();
+ if (node.uri.stringValue == 'dart:core') {
+ hasCoreBeenImported = true;
+ }
+ b.offset = node.offset;
+ b.combinators = node.combinators.map(serializeCombinator).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 visitLibraryDirective(LibraryDirective node) {
+ libraryName =
+ node.name.components.map((SimpleIdentifier id) => id.name).join('.');
+ libraryNameOffset = node.name.offset;
+ libraryNameLength = node.name.length;
+ libraryDocumentationComment =
+ serializeDocumentation(node.documentationComment);
+ }
+
+ @override
+ void visitMethodDeclaration(MethodDeclaration node) {
+ executables.add(serializeExecutable(
+ node.name,
+ node.isGetter,
+ node.isSetter,
+ node.returnType,
+ node.parameters,
+ node.body,
+ false,
+ node.isStatic,
+ node.documentationComment,
+ node.typeParameters,
+ node.externalKeyword != null));
+ }
+
+ @override
+ void visitPartDirective(PartDirective node) {
+ parts.add(new UnlinkedPartBuilder(
+ uriOffset: node.uri.offset, uriEnd: node.uri.end));
+ }
+
+ @override
+ void visitPartOfDirective(PartOfDirective node) {}
+
+ @override
+ UnlinkedParamBuilder visitSimpleFormalParameter(SimpleFormalParameter node) {
+ UnlinkedParamBuilder b = serializeParameter(node);
+ b.type = serializeTypeName(node.type);
+ b.hasImplicitType = node.type == null;
+ return b;
+ }
+
+ @override
+ void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ serializeVariables(node.variables, false, node.documentationComment);
+ }
+
+ @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);
+ }
+ return b;
+ }
+
+ /**
+ * Helper method to determine if a given [typeName] refers to `dynamic`.
+ */
+ static bool isNotDynamic(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 | « no previous file | pkg/analyzer/test/src/summary/summary_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698