| Index: pkg/analyzer/lib/src/summary/fasta/model.dart
|
| diff --git a/pkg/analyzer/lib/src/summary/fasta/model.dart b/pkg/analyzer/lib/src/summary/fasta/model.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..373ad9825c401ae2540cf5d06bcab37d0e4006a5
|
| --- /dev/null
|
| +++ b/pkg/analyzer/lib/src/summary/fasta/model.dart
|
| @@ -0,0 +1,189 @@
|
| +// Copyright (c) 2017, 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.
|
| +
|
| +/// Additional data model classes used by the summary builder.
|
| +///
|
| +/// The summary builder uses 4 pieces of data:
|
| +///
|
| +/// * Unlinked**Builders: builder classes for each piece of output in the
|
| +/// summary (see format.dart).
|
| +///
|
| +/// * A simplified expression syntax: model relevant pieces of initializers
|
| +/// and constants before serializing them (see expressions.dart).
|
| +///
|
| +/// * Lazy references: a way to model references on the fly so we can build
|
| +/// summaries in a single pass.
|
| +///
|
| +/// * Scopes: used to track the current context of the parser, used in great
|
| +/// part to easily resolve lazy references at the end of the build process.
|
| +library summary.src.scope;
|
| +
|
| +import 'package:analyzer/src/summary/format.dart';
|
| +import 'package:analyzer/src/summary/idl.dart';
|
| +
|
| +export 'package:analyzer/src/summary/format.dart';
|
| +export 'package:analyzer/src/summary/idl.dart';
|
| +export 'package:analyzer/src/summary/api_signature.dart';
|
| +export 'expressions.dart';
|
| +export 'visitor.dart';
|
| +
|
| +/// A scope corresponding to a scope in the program like units, classes, or
|
| +/// enums.
|
| +///
|
| +/// It is used to hold results that correspond to a given scope in the program
|
| +/// and to lazily resolve name references.
|
| +abstract class Scope {
|
| + Scope get parent;
|
| +
|
| + TopScope get top {
|
| + var s = this;
|
| + while (s.parent != null) s = s.parent;
|
| + return s;
|
| + }
|
| +
|
| + void computeReference(LazyEntityRef ref);
|
| +}
|
| +
|
| +/// Top scope, where the top-level unit is built.
|
| +class TopScope extends Scope {
|
| + get parent => null;
|
| + toString() => "<top-scope>";
|
| +
|
| + /// Results of parsing the unit.
|
| + final UnlinkedUnitBuilder unit = new UnlinkedUnitBuilder(
|
| + classes: [],
|
| + enums: [],
|
| + executables: [],
|
| + exports: [],
|
| + imports: [],
|
| + parts: [],
|
| + references: [new UnlinkedReferenceBuilder()],
|
| + typedefs: [],
|
| + variables: []);
|
| +
|
| + /// Stores publicly visible names exported from the unit.
|
| + final UnlinkedPublicNamespaceBuilder publicNamespace =
|
| + new UnlinkedPublicNamespaceBuilder(names: [], exports: [], parts: []);
|
| +
|
| + /// Lazy references that need to be expanded after all scope information is
|
| + /// known.
|
| + List<LazyEntityRef> _toExpand = [];
|
| +
|
| + void expandLazyReferences() {
|
| + _toExpand.forEach((r) => r.expand());
|
| + }
|
| +
|
| + TopScope() {
|
| + unit.publicNamespace = publicNamespace;
|
| + }
|
| +
|
| + final Map<int, Map<String, int>> nameToReference = <int, Map<String, int>>{};
|
| + int serializeReference(int prefixIndex, String name) => nameToReference
|
| + .putIfAbsent(prefixIndex, () => <String, int>{})
|
| + .putIfAbsent(name, () {
|
| + int index = unit.references.length;
|
| + unit.references.add(new UnlinkedReferenceBuilder(
|
| + prefixReference: prefixIndex, name: name));
|
| + return index;
|
| + });
|
| +
|
| + void computeReference(LazyEntityRef ref) {
|
| + ref.reference = serializeReference(null, ref.name);
|
| + }
|
| +}
|
| +
|
| +class TypeParameterScope extends Scope {
|
| + final Scope parent;
|
| + TypeParameterScope(this.parent);
|
| +
|
| + List<String> typeParameters = [];
|
| +
|
| + void computeReference(LazyEntityRef ref) {
|
| + var i = typeParameters.indexOf(ref.name);
|
| + if (i < 0) return parent.computeReference(ref);
|
| + // Note: there is no indexOffset here because we don't go into functions at
|
| + // all (so there is no nesting of type-parameter scopes).
|
| + ref.paramReference = typeParameters.length - i;
|
| + }
|
| +}
|
| +
|
| +class ClassScope extends TypeParameterScope {
|
| + String className;
|
| + UnlinkedClassBuilder currentClass = new UnlinkedClassBuilder();
|
| + UnlinkedPublicNameBuilder publicName = new UnlinkedPublicNameBuilder();
|
| + Set<String> members = new Set<String>();
|
| + toString() => "<class-scope: $className>";
|
| +
|
| + ClassScope(Scope parent) : super(parent);
|
| +
|
| + void computeReference(LazyEntityRef ref) {
|
| + if (!members.contains(ref.name)) {
|
| + return super.computeReference(ref);
|
| + }
|
| + ref.reference = top.serializeReference(
|
| + top.serializeReference(null, className), ref.name);
|
| + }
|
| +}
|
| +
|
| +class EnumScope extends Scope {
|
| + final Scope parent;
|
| + UnlinkedEnumBuilder currentEnum = new UnlinkedEnumBuilder();
|
| +
|
| + EnumScope(this.parent);
|
| +
|
| + void computeReference(LazyEntityRef ref) => throw "unexpected";
|
| +}
|
| +
|
| +
|
| +/// A lazily encoded reference.
|
| +///
|
| +/// References in summaries are encoded based on the scope where they appear.
|
| +/// Most top-level references can be encoded eagerly, but references in the
|
| +/// scope of a class need to check whether a name is a member of such class.
|
| +/// Because we don't have such list of members available upfront, we create
|
| +/// these lazy references and finalize them after we finish going through the
|
| +/// program.
|
| +class LazyEntityRef extends EntityRefBuilder {
|
| + Scope scope;
|
| + String name;
|
| + LazyEntityRef(this.name, this.scope) : super() {
|
| + scope.top._toExpand.add(this);
|
| + }
|
| +
|
| +
|
| + bool wasExpanded = false;
|
| + expand() {
|
| + if (!wasExpanded) {
|
| + scope.computeReference(this);
|
| + wasExpanded = true;
|
| + }
|
| + }
|
| +
|
| + @override
|
| + int get reference {
|
| + expand();
|
| + return super.reference;
|
| + }
|
| +
|
| + @override
|
| + int get paramReference {
|
| + expand();
|
| + return super.paramReference;
|
| + }
|
| +}
|
| +
|
| +/// A nested lazy reference, modeling something like `a.b.c`.
|
| +class NestedLazyEntityRef extends LazyEntityRef {
|
| + EntityRef prefix;
|
| + NestedLazyEntityRef(this.prefix, String name, Scope scope)
|
| + : super(name, scope.top);
|
| +
|
| + @override
|
| + expand() {
|
| + if (!wasExpanded) {
|
| + super.reference = scope.top.serializeReference(prefix.reference, name);
|
| + wasExpanded = true;
|
| + }
|
| + }
|
| +}
|
|
|