| Index: pkg/analysis_services/lib/src/index/store/split_store.dart
 | 
| diff --git a/pkg/analysis_services/lib/src/index/store/split_store.dart b/pkg/analysis_services/lib/src/index/store/split_store.dart
 | 
| deleted file mode 100644
 | 
| index 5a81f594e2b235c5ddf7e5419142324f47b78113..0000000000000000000000000000000000000000
 | 
| --- a/pkg/analysis_services/lib/src/index/store/split_store.dart
 | 
| +++ /dev/null
 | 
| @@ -1,916 +0,0 @@
 | 
| -// Copyright (c) 2014, 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 services.src.index.store.split_store;
 | 
| -
 | 
| -import 'dart:async';
 | 
| -import 'dart:collection';
 | 
| -import 'dart:io';
 | 
| -import 'dart:typed_data';
 | 
| -
 | 
| -import 'package:analysis_services/index/index.dart';
 | 
| -import 'package:analysis_services/index/index_store.dart';
 | 
| -import 'package:analysis_services/src/index/store/codec.dart';
 | 
| -import 'package:analysis_services/src/index/store/collection.dart';
 | 
| -import 'package:analyzer/src/generated/element.dart';
 | 
| -import 'package:analyzer/src/generated/engine.dart';
 | 
| -import 'package:analyzer/src/generated/java_engine.dart';
 | 
| -import 'package:analyzer/src/generated/source.dart';
 | 
| -
 | 
| -
 | 
| -/**
 | 
| - * A manager for files content.
 | 
| - */
 | 
| -abstract class FileManager {
 | 
| -  /**
 | 
| -   * Removes all files.
 | 
| -   */
 | 
| -  void clear();
 | 
| -
 | 
| -  /**
 | 
| -   * Deletes the file with the given name.
 | 
| -   */
 | 
| -  void delete(String name);
 | 
| -
 | 
| -  /**
 | 
| -   * Read the entire file contents as a list of bytes.
 | 
| -   */
 | 
| -  Future<List<int>> read(String name);
 | 
| -
 | 
| -  /**
 | 
| -   * Write a list of bytes to a file.
 | 
| -   */
 | 
| -  Future write(String name, List<int> bytes);
 | 
| -}
 | 
| -
 | 
| -
 | 
| -/**
 | 
| - * A [FileManager] based [NodeManager].
 | 
| - */
 | 
| -class FileNodeManager implements NodeManager {
 | 
| -  static int _VERSION = 1;
 | 
| -
 | 
| -  final FileManager _fileManager;
 | 
| -  final Logger _logger;
 | 
| -
 | 
| -  final ContextCodec contextCodec;
 | 
| -  final ElementCodec elementCodec;
 | 
| -  final StringCodec stringCodec;
 | 
| -  final RelationshipCodec _relationshipCodec;
 | 
| -
 | 
| -  int _locationCount = 0;
 | 
| -
 | 
| -  Map<String, int> _nodeLocationCounts = new HashMap<String, int>();
 | 
| -
 | 
| -  FileNodeManager(this._fileManager, this._logger, this.stringCodec,
 | 
| -      this.contextCodec, this.elementCodec, this._relationshipCodec);
 | 
| -
 | 
| -  @override
 | 
| -  int get locationCount => _locationCount;
 | 
| -
 | 
| -  @override
 | 
| -  void clear() {
 | 
| -    _fileManager.clear();
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  Future<IndexNode> getNode(String name) {
 | 
| -    return _fileManager.read(name).then((List<int> bytes) {
 | 
| -      if (bytes == null) {
 | 
| -        return null;
 | 
| -      }
 | 
| -      _DataInputStream stream = new _DataInputStream(bytes);
 | 
| -      return _readNode(stream);
 | 
| -    }).catchError((e, stackTrace) {
 | 
| -      _logger.logError2(
 | 
| -          'Exception during reading index file ${name}',
 | 
| -          new CaughtException(e, stackTrace));
 | 
| -    });
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  IndexNode newNode(AnalysisContext context) =>
 | 
| -      new IndexNode(context, elementCodec, _relationshipCodec);
 | 
| -
 | 
| -  @override
 | 
| -  Future putNode(String name, IndexNode node) {
 | 
| -    // update location count
 | 
| -    {
 | 
| -      _locationCount -= _getLocationCount(name);
 | 
| -      int nodeLocationCount = node.locationCount;
 | 
| -      _nodeLocationCounts[name] = nodeLocationCount;
 | 
| -      _locationCount += nodeLocationCount;
 | 
| -    }
 | 
| -    // write the node
 | 
| -    return new Future.microtask(() {
 | 
| -      _DataOutputStream stream = new _DataOutputStream();
 | 
| -      _writeNode(node, stream);
 | 
| -      var bytes = stream.getBytes();
 | 
| -      return _fileManager.write(name, bytes);
 | 
| -    }).catchError((e, stackTrace) {
 | 
| -      _logger.logError2(
 | 
| -          'Exception during reading index file ${name}',
 | 
| -          new CaughtException(e, stackTrace));
 | 
| -    });
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  void removeNode(String name) {
 | 
| -    // update location count
 | 
| -    _locationCount -= _getLocationCount(name);
 | 
| -    _nodeLocationCounts.remove(name);
 | 
| -    // remove node
 | 
| -    _fileManager.delete(name);
 | 
| -  }
 | 
| -
 | 
| -  int _getLocationCount(String name) {
 | 
| -    int locationCount = _nodeLocationCounts[name];
 | 
| -    return locationCount != null ? locationCount : 0;
 | 
| -  }
 | 
| -
 | 
| -  RelationKeyData _readElementRelationKey(_DataInputStream stream) {
 | 
| -    int elementId = stream.readInt();
 | 
| -    int relationshipId = stream.readInt();
 | 
| -    return new RelationKeyData.forData(elementId, relationshipId);
 | 
| -  }
 | 
| -
 | 
| -  LocationData _readLocationData(_DataInputStream stream) {
 | 
| -    int elementId = stream.readInt();
 | 
| -    int offset = stream.readInt();
 | 
| -    int length = stream.readInt();
 | 
| -    int flags = stream.readInt();
 | 
| -    return new LocationData.forData(elementId, offset, length, flags);
 | 
| -  }
 | 
| -
 | 
| -  IndexNode _readNode(_DataInputStream stream) {
 | 
| -    // check version
 | 
| -    {
 | 
| -      int version = stream.readInt();
 | 
| -      if (version != _VERSION) {
 | 
| -        throw new StateError(
 | 
| -            'Version ${_VERSION} expected, but ${version} found.');
 | 
| -      }
 | 
| -    }
 | 
| -    // context
 | 
| -    int contextId = stream.readInt();
 | 
| -    AnalysisContext context = contextCodec.decode(contextId);
 | 
| -    if (context == null) {
 | 
| -      return null;
 | 
| -    }
 | 
| -    // relations
 | 
| -    Map<RelationKeyData, List<LocationData>> relations =
 | 
| -        new HashMap<RelationKeyData, List<LocationData>>();
 | 
| -    int numRelations = stream.readInt();
 | 
| -    for (int i = 0; i < numRelations; i++) {
 | 
| -      RelationKeyData key = _readElementRelationKey(stream);
 | 
| -      int numLocations = stream.readInt();
 | 
| -      List<LocationData> locations = new List<LocationData>();
 | 
| -      for (int j = 0; j < numLocations; j++) {
 | 
| -        locations.add(_readLocationData(stream));
 | 
| -      }
 | 
| -      relations[key] = locations;
 | 
| -    }
 | 
| -    // create IndexNode
 | 
| -    IndexNode node = new IndexNode(context, elementCodec, _relationshipCodec);
 | 
| -    node.relations = relations;
 | 
| -    return node;
 | 
| -  }
 | 
| -
 | 
| -  void _writeElementRelationKey(_DataOutputStream stream, RelationKeyData key) {
 | 
| -    stream.writeInt(key.elementId);
 | 
| -    stream.writeInt(key.relationshipId);
 | 
| -  }
 | 
| -
 | 
| -  void _writeNode(IndexNode node, _DataOutputStream stream) {
 | 
| -    // version
 | 
| -    stream.writeInt(_VERSION);
 | 
| -    // context
 | 
| -    {
 | 
| -      AnalysisContext context = node.context;
 | 
| -      int contextId = contextCodec.encode(context);
 | 
| -      stream.writeInt(contextId);
 | 
| -    }
 | 
| -    // relations
 | 
| -    Map<RelationKeyData, List<LocationData>> relations = node.relations;
 | 
| -    stream.writeInt(relations.length);
 | 
| -    relations.forEach((key, locations) {
 | 
| -      _writeElementRelationKey(stream, key);
 | 
| -      stream.writeInt(locations.length);
 | 
| -      for (LocationData location in locations) {
 | 
| -        stream.writeInt(location.elementId);
 | 
| -        stream.writeInt(location.offset);
 | 
| -        stream.writeInt(location.length);
 | 
| -        stream.writeInt(location.flags);
 | 
| -      }
 | 
| -    });
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -/**
 | 
| - * A single index file in-memory presentation.
 | 
| - */
 | 
| -class IndexNode {
 | 
| -  final AnalysisContext context;
 | 
| -
 | 
| -  final ElementCodec _elementCodec;
 | 
| -  final RelationshipCodec _relationshipCodec;
 | 
| -
 | 
| -  Map<RelationKeyData, List<LocationData>> _relations =
 | 
| -      new HashMap<RelationKeyData, List<LocationData>>();
 | 
| -
 | 
| -
 | 
| -  IndexNode(this.context, this._elementCodec, this._relationshipCodec);
 | 
| -
 | 
| -  /**
 | 
| -   * Returns number of locations in this node.
 | 
| -   */
 | 
| -  int get locationCount {
 | 
| -    int locationCount = 0;
 | 
| -    for (List<LocationData> locations in _relations.values) {
 | 
| -      locationCount += locations.length;
 | 
| -    }
 | 
| -    return locationCount;
 | 
| -  }
 | 
| -
 | 
| -  /**
 | 
| -   * Returns the recorded relations.
 | 
| -   */
 | 
| -  Map<RelationKeyData, List<LocationData>> get relations => _relations;
 | 
| -
 | 
| -  /**
 | 
| -   * Sets relations data.
 | 
| -   * This method is used during loading data from a storage.
 | 
| -   */
 | 
| -  void set relations(Map<RelationKeyData, List<LocationData>> relations) {
 | 
| -    _relations = relations;
 | 
| -  }
 | 
| -
 | 
| -  /**
 | 
| -   * Returns the locations of the elements that have the given relationship with
 | 
| -   * the given element.
 | 
| -   *
 | 
| -   * [element] - the the element that has the relationship with the locations to
 | 
| -   *    be returned.
 | 
| -   * [relationship] - the [Relationship] between the given [element] and the
 | 
| -   *    locations to be returned
 | 
| -   */
 | 
| -  List<Location> getRelationships(Element element, Relationship relationship) {
 | 
| -    // prepare key
 | 
| -    RelationKeyData key =
 | 
| -        new RelationKeyData.forObject(
 | 
| -            _elementCodec,
 | 
| -            _relationshipCodec,
 | 
| -            element,
 | 
| -            relationship);
 | 
| -    // find LocationData(s)
 | 
| -    List<LocationData> locationDatas = _relations[key];
 | 
| -    if (locationDatas == null) {
 | 
| -      return Location.EMPTY_ARRAY;
 | 
| -    }
 | 
| -    // convert to Location(s)
 | 
| -    List<Location> locations = <Location>[];
 | 
| -    for (LocationData locationData in locationDatas) {
 | 
| -      Location location = locationData.getLocation(context, _elementCodec);
 | 
| -      if (location != null) {
 | 
| -        locations.add(location);
 | 
| -      }
 | 
| -    }
 | 
| -    return locations;
 | 
| -  }
 | 
| -
 | 
| -  /**
 | 
| -   * Records that the given [element] and [location] have the given [relationship].
 | 
| -   *
 | 
| -   * [element] - the [Element] that is related to the location.
 | 
| -   * [relationship] - the [Relationship] between [element] and [location].
 | 
| -   * [location] - the [Location] where relationship happens.
 | 
| -   */
 | 
| -  void recordRelationship(Element element, Relationship relationship,
 | 
| -      Location location) {
 | 
| -    RelationKeyData key =
 | 
| -        new RelationKeyData.forObject(
 | 
| -            _elementCodec,
 | 
| -            _relationshipCodec,
 | 
| -            element,
 | 
| -            relationship);
 | 
| -    // prepare LocationData(s)
 | 
| -    List<LocationData> locationDatas = _relations[key];
 | 
| -    if (locationDatas == null) {
 | 
| -      locationDatas = <LocationData>[];
 | 
| -      _relations[key] = locationDatas;
 | 
| -    }
 | 
| -    // add new LocationData
 | 
| -    locationDatas.add(new LocationData.forObject(_elementCodec, location));
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -/**
 | 
| - * A container with information about a [Location].
 | 
| - */
 | 
| -class LocationData {
 | 
| -  static const int _FLAG_QUALIFIED = 1 << 0;
 | 
| -  static const int _FLAG_RESOLVED = 1 << 1;
 | 
| -
 | 
| -  final int elementId;
 | 
| -  final int offset;
 | 
| -  final int length;
 | 
| -  final int flags;
 | 
| -
 | 
| -  LocationData.forData(this.elementId, this.offset, this.length, this.flags);
 | 
| -
 | 
| -  LocationData.forObject(ElementCodec elementCodec, Location location)
 | 
| -      : elementId = elementCodec.encode(location.element),
 | 
| -        offset = location.offset,
 | 
| -        length = location.length,
 | 
| -        flags = (location.isQualified ? _FLAG_QUALIFIED : 0) |
 | 
| -          (location.isResolved ? _FLAG_RESOLVED : 0);
 | 
| -
 | 
| -  @override
 | 
| -  int get hashCode {
 | 
| -    return 31 * (31 * elementId + offset) + length;
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  bool operator ==(Object obj) {
 | 
| -    if (obj is! LocationData) {
 | 
| -      return false;
 | 
| -    }
 | 
| -    LocationData other = obj;
 | 
| -    return other.elementId == elementId &&
 | 
| -        other.offset == offset &&
 | 
| -        other.length == length &&
 | 
| -        other.flags == flags;
 | 
| -  }
 | 
| -
 | 
| -  /**
 | 
| -   * Returns a {@link Location} that is represented by this {@link LocationData}.
 | 
| -   */
 | 
| -  Location getLocation(AnalysisContext context, ElementCodec elementCodec) {
 | 
| -    Element element = elementCodec.decode(context, elementId);
 | 
| -    if (element == null) {
 | 
| -      return null;
 | 
| -    }
 | 
| -    bool isQualified = (flags & _FLAG_QUALIFIED) != 0;
 | 
| -    bool isResovled = (flags & _FLAG_RESOLVED) != 0;
 | 
| -    return new Location(
 | 
| -        element,
 | 
| -        offset,
 | 
| -        length,
 | 
| -        isQualified: isQualified,
 | 
| -        isResolved: isResovled);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -/**
 | 
| - * A manager for [IndexNode]s.
 | 
| - */
 | 
| -abstract class NodeManager {
 | 
| -  /**
 | 
| -   * The shared {@link ContextCodec} instance.
 | 
| -   */
 | 
| -  ContextCodec get contextCodec;
 | 
| -
 | 
| -  /**
 | 
| -   * The shared {@link ElementCodec} instance.
 | 
| -   */
 | 
| -  ElementCodec get elementCodec;
 | 
| -
 | 
| -  /**
 | 
| -   * A number of locations in all nodes.
 | 
| -   */
 | 
| -  int get locationCount;
 | 
| -
 | 
| -  /**
 | 
| -   * The shared {@link StringCodec} instance.
 | 
| -   */
 | 
| -  StringCodec get stringCodec;
 | 
| -
 | 
| -  /**
 | 
| -   * Removes all nodes.
 | 
| -   */
 | 
| -  void clear();
 | 
| -
 | 
| -  /**
 | 
| -   * Returns the {@link IndexNode} with the given name, {@code null} if not found.
 | 
| -   */
 | 
| -  Future<IndexNode> getNode(String name);
 | 
| -
 | 
| -  /**
 | 
| -   * Returns a new {@link IndexNode}.
 | 
| -   */
 | 
| -  IndexNode newNode(AnalysisContext context);
 | 
| -
 | 
| -  /**
 | 
| -   * Associates the given {@link IndexNode} with the given name.
 | 
| -   */
 | 
| -  void putNode(String name, IndexNode node);
 | 
| -
 | 
| -  /**
 | 
| -   * Removes the {@link IndexNode} with the given name.
 | 
| -   */
 | 
| -  void removeNode(String name);
 | 
| -}
 | 
| -
 | 
| -
 | 
| -/**
 | 
| - * An [Element] to [Location] relation key.
 | 
| - */
 | 
| -class RelationKeyData {
 | 
| -  final int elementId;
 | 
| -  final int relationshipId;
 | 
| -
 | 
| -  RelationKeyData.forData(this.elementId, this.relationshipId);
 | 
| -
 | 
| -  RelationKeyData.forObject(ElementCodec elementCodec,
 | 
| -      RelationshipCodec relationshipCodec, Element element, Relationship relationship)
 | 
| -      : elementId = elementCodec.encode(element),
 | 
| -        relationshipId = relationshipCodec.encode(relationship);
 | 
| -
 | 
| -  @override
 | 
| -  int get hashCode {
 | 
| -    return 31 * elementId + relationshipId;
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  bool operator ==(Object obj) {
 | 
| -    if (obj is! RelationKeyData) {
 | 
| -      return false;
 | 
| -    }
 | 
| -    RelationKeyData other = obj;
 | 
| -    return other.elementId == elementId &&
 | 
| -        other.relationshipId == relationshipId;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -/**
 | 
| - * An [IndexStore] which keeps index information in separate nodes for each unit.
 | 
| - */
 | 
| -class SplitIndexStore implements IndexStore {
 | 
| -  /**
 | 
| -   * The [ContextCodec] to encode/decode [AnalysisContext]s.
 | 
| -   */
 | 
| -  ContextCodec _contextCodec;
 | 
| -
 | 
| -  /**
 | 
| -   * Information about "universe" elements.
 | 
| -   * We need to keep them together to avoid loading of all index nodes.
 | 
| -   *
 | 
| -   * Order of keys: contextId, nodeId, Relationship.
 | 
| -   */
 | 
| -  Map<int, Map<int, Map<Relationship, List<LocationData>>>>
 | 
| -      _contextNodeRelations =
 | 
| -      new HashMap<int, Map<int, Map<Relationship, List<LocationData>>>>();
 | 
| -
 | 
| -  /**
 | 
| -   * The mapping of library [Source] to the [Source]s of part units.
 | 
| -   */
 | 
| -  Map<AnalysisContext, Map<Source, Set<Source>>> _contextToLibraryToUnits =
 | 
| -      new HashMap<AnalysisContext, Map<Source, Set<Source>>>();
 | 
| -
 | 
| -  /**
 | 
| -   * The mapping of unit [Source] to the [Source]s of libraries it is used in.
 | 
| -   */
 | 
| -  Map<AnalysisContext, Map<Source, Set<Source>>> _contextToUnitToLibraries =
 | 
| -      new HashMap<AnalysisContext, Map<Source, Set<Source>>>();
 | 
| -
 | 
| -  int _currentContextId = 0;
 | 
| -
 | 
| -  IndexNode _currentNode;
 | 
| -
 | 
| -  String _currentNodeName;
 | 
| -
 | 
| -  int _currentNodeNameId = 0;
 | 
| -
 | 
| -  /**
 | 
| -   * The [ElementCodec] to encode/decode [Element]s.
 | 
| -   */
 | 
| -  ElementCodec _elementCodec;
 | 
| -
 | 
| -  /**
 | 
| -   * A table mapping element names to the node names that may have relations with elements with
 | 
| -   * these names.
 | 
| -   */
 | 
| -  IntToIntSetMap _nameToNodeNames = new IntToIntSetMap();
 | 
| -
 | 
| -  /**
 | 
| -   * The [NodeManager] to get/put [IndexNode]s.
 | 
| -   */
 | 
| -  final NodeManager _nodeManager;
 | 
| -
 | 
| -  /**
 | 
| -   * The set of known [Source]s.
 | 
| -   */
 | 
| -  Set<Source> _sources = new HashSet<Source>();
 | 
| -
 | 
| -  /**
 | 
| -   * The [StringCodec] to encode/decode [String]s.
 | 
| -   */
 | 
| -  StringCodec _stringCodec;
 | 
| -
 | 
| -  SplitIndexStore(this._nodeManager) {
 | 
| -    this._contextCodec = _nodeManager.contextCodec;
 | 
| -    this._elementCodec = _nodeManager.elementCodec;
 | 
| -    this._stringCodec = _nodeManager.stringCodec;
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  String get statistics =>
 | 
| -      '[${_nodeManager.locationCount} locations, ${_sources.length} sources, ${_nameToNodeNames.length} names]';
 | 
| -
 | 
| -  @override
 | 
| -  bool aboutToIndexDart(AnalysisContext context,
 | 
| -      CompilationUnitElement unitElement) {
 | 
| -    context = _unwrapContext(context);
 | 
| -    // may be already disposed in other thread
 | 
| -    if (context.isDisposed) {
 | 
| -      return false;
 | 
| -    }
 | 
| -    // validate unit
 | 
| -    if (unitElement == null) {
 | 
| -      return false;
 | 
| -    }
 | 
| -    LibraryElement libraryElement = unitElement.library;
 | 
| -    if (libraryElement == null) {
 | 
| -      return false;
 | 
| -    }
 | 
| -    CompilationUnitElement definingUnitElement =
 | 
| -        libraryElement.definingCompilationUnit;
 | 
| -    if (definingUnitElement == null) {
 | 
| -      return false;
 | 
| -    }
 | 
| -    // prepare sources
 | 
| -    Source library = definingUnitElement.source;
 | 
| -    Source unit = unitElement.source;
 | 
| -    // special handling for the defining library unit
 | 
| -    if (unit == library) {
 | 
| -      // prepare new parts
 | 
| -      HashSet<Source> newParts = new HashSet<Source>();
 | 
| -      for (CompilationUnitElement part in libraryElement.parts) {
 | 
| -        newParts.add(part.source);
 | 
| -      }
 | 
| -      // prepare old parts
 | 
| -      Map<Source, Set<Source>> libraryToUnits =
 | 
| -          _contextToLibraryToUnits[context];
 | 
| -      if (libraryToUnits == null) {
 | 
| -        libraryToUnits = new HashMap<Source, Set<Source>>();
 | 
| -        _contextToLibraryToUnits[context] = libraryToUnits;
 | 
| -      }
 | 
| -      Set<Source> oldParts = libraryToUnits[library];
 | 
| -      // check if some parts are not in the library now
 | 
| -      if (oldParts != null) {
 | 
| -        Set<Source> noParts = oldParts.difference(newParts);
 | 
| -        for (Source noPart in noParts) {
 | 
| -          _removeLocations(context, library, noPart);
 | 
| -        }
 | 
| -      }
 | 
| -      // remember new parts
 | 
| -      libraryToUnits[library] = newParts;
 | 
| -    }
 | 
| -    // remember library/unit relations
 | 
| -    _recordUnitInLibrary(context, library, unit);
 | 
| -    _recordLibraryWithUnit(context, library, unit);
 | 
| -    _sources.add(library);
 | 
| -    _sources.add(unit);
 | 
| -    // prepare node
 | 
| -    String libraryName = library.fullName;
 | 
| -    String unitName = unit.fullName;
 | 
| -    int libraryNameIndex = _stringCodec.encode(libraryName);
 | 
| -    int unitNameIndex = _stringCodec.encode(unitName);
 | 
| -    _currentNodeName = '${libraryNameIndex}_${unitNameIndex}.index';
 | 
| -    _currentNodeNameId = _stringCodec.encode(_currentNodeName);
 | 
| -    _currentNode = _nodeManager.newNode(context);
 | 
| -    _currentContextId = _contextCodec.encode(context);
 | 
| -    // remove Universe information for the current node
 | 
| -    for (Map<int, dynamic> nodeRelations in _contextNodeRelations.values) {
 | 
| -      nodeRelations.remove(_currentNodeNameId);
 | 
| -    }
 | 
| -    // done
 | 
| -    return true;
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement) {
 | 
| -    context = _unwrapContext(context);
 | 
| -    // may be already disposed in other thread
 | 
| -    if (context.isDisposed) {
 | 
| -      return false;
 | 
| -    }
 | 
| -    // remove locations
 | 
| -    Source source = htmlElement.source;
 | 
| -    _removeLocations(context, null, source);
 | 
| -    // remember library/unit relations
 | 
| -    _recordUnitInLibrary(context, null, source);
 | 
| -    // prepare node
 | 
| -    String sourceName = source.fullName;
 | 
| -    int sourceNameIndex = _stringCodec.encode(sourceName);
 | 
| -    _currentNodeName = '${sourceNameIndex}.index';
 | 
| -    _currentNodeNameId = _stringCodec.encode(_currentNodeName);
 | 
| -    _currentNode = _nodeManager.newNode(context);
 | 
| -    return true;
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  void clear() {
 | 
| -    _contextNodeRelations.clear();
 | 
| -    _nodeManager.clear();
 | 
| -    _nameToNodeNames.clear();
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  void doneIndex() {
 | 
| -    if (_currentNode != null) {
 | 
| -      _nodeManager.putNode(_currentNodeName, _currentNode);
 | 
| -      _currentNodeName = null;
 | 
| -      _currentNodeNameId = -1;
 | 
| -      _currentNode = null;
 | 
| -      _currentContextId = -1;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  Future<List<Location>> getRelationships(Element element,
 | 
| -      Relationship relationship) {
 | 
| -    // special support for UniverseElement
 | 
| -    if (identical(element, UniverseElement.INSTANCE)) {
 | 
| -      List<Location> locations = _getRelationshipsUniverse(relationship);
 | 
| -      return new Future.value(locations);
 | 
| -    }
 | 
| -    // prepare node names
 | 
| -    int nameId = _elementCodec.encodeHash(element);
 | 
| -    List<int> nodeNameIds = _nameToNodeNames.get(nameId);
 | 
| -    // prepare Future(s) for reading each IndexNode
 | 
| -    List<Future<List<Location>>> nodeFutures = <Future<List<Location>>>[];
 | 
| -    for (int nodeNameId in nodeNameIds) {
 | 
| -      String nodeName = _stringCodec.decode(nodeNameId);
 | 
| -      Future<IndexNode> nodeFuture = _nodeManager.getNode(nodeName);
 | 
| -      Future<List<Location>> locationsFuture = nodeFuture.then((node) {
 | 
| -        if (node == null) {
 | 
| -          // TODO(scheglov) remove node
 | 
| -          return Location.EMPTY_ARRAY;
 | 
| -        }
 | 
| -        return node.getRelationships(element, relationship);
 | 
| -      });
 | 
| -      nodeFutures.add(locationsFuture);
 | 
| -    }
 | 
| -    // return Future that merges separate IndexNode Location(s)
 | 
| -    return Future.wait(nodeFutures).then((List<List<Location>> locationsList) {
 | 
| -      List<Location> allLocations = <Location>[];
 | 
| -      for (List<Location> locations in locationsList) {
 | 
| -        allLocations.addAll(locations);
 | 
| -      }
 | 
| -      return allLocations;
 | 
| -    });
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  void recordRelationship(Element element, Relationship relationship,
 | 
| -      Location location) {
 | 
| -    if (element == null || location == null) {
 | 
| -      return;
 | 
| -    }
 | 
| -    // special support for UniverseElement
 | 
| -    if (identical(element, UniverseElement.INSTANCE)) {
 | 
| -      _recordRelationshipUniverse(relationship, location);
 | 
| -      return;
 | 
| -    }
 | 
| -    // other elements
 | 
| -    _recordNodeNameForElement(element);
 | 
| -    _currentNode.recordRelationship(element, relationship, location);
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  void removeContext(AnalysisContext context) {
 | 
| -    context = _unwrapContext(context);
 | 
| -    if (context == null) {
 | 
| -      return;
 | 
| -    }
 | 
| -    // remove sources
 | 
| -    removeSources(context, null);
 | 
| -    // remove context information
 | 
| -    _contextToLibraryToUnits.remove(context);
 | 
| -    _contextToUnitToLibraries.remove(context);
 | 
| -    _contextNodeRelations.remove(_contextCodec.encode(context));
 | 
| -    // remove context from codec
 | 
| -    _contextCodec.remove(context);
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  void removeSource(AnalysisContext context, Source source) {
 | 
| -    context = _unwrapContext(context);
 | 
| -    if (context == null) {
 | 
| -      return;
 | 
| -    }
 | 
| -    // remove nodes for unit/library pairs
 | 
| -    Map<Source, Set<Source>> unitToLibraries =
 | 
| -        _contextToUnitToLibraries[context];
 | 
| -    if (unitToLibraries != null) {
 | 
| -      Set<Source> libraries = unitToLibraries.remove(source);
 | 
| -      if (libraries != null) {
 | 
| -        for (Source library in libraries) {
 | 
| -          _removeLocations(context, library, source);
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -    // remove nodes for library/unit pairs
 | 
| -    Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
 | 
| -    if (libraryToUnits != null) {
 | 
| -      Set<Source> units = libraryToUnits.remove(source);
 | 
| -      if (units != null) {
 | 
| -        for (Source unit in units) {
 | 
| -          _removeLocations(context, source, unit);
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  @override
 | 
| -  void removeSources(AnalysisContext context, SourceContainer container) {
 | 
| -    context = _unwrapContext(context);
 | 
| -    if (context == null) {
 | 
| -      return;
 | 
| -    }
 | 
| -    // remove nodes for unit/library pairs
 | 
| -    Map<Source, Set<Source>> unitToLibraries =
 | 
| -        _contextToUnitToLibraries[context];
 | 
| -    if (unitToLibraries != null) {
 | 
| -      List<Source> units = new List<Source>.from(unitToLibraries.keys);
 | 
| -      for (Source source in units) {
 | 
| -        if (container == null || container.contains(source)) {
 | 
| -          removeSource(context, source);
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -    // remove nodes for library/unit pairs
 | 
| -    Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
 | 
| -    if (libraryToUnits != null) {
 | 
| -      List<Source> libraries = new List<Source>.from(libraryToUnits.keys);
 | 
| -      for (Source source in libraries) {
 | 
| -        if (container == null || container.contains(source)) {
 | 
| -          removeSource(context, source);
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  String _getElementName(Element element) => element.name;
 | 
| -
 | 
| -  List<Location> _getRelationshipsUniverse(Relationship relationship) {
 | 
| -    List<Location> locations = <Location>[];
 | 
| -    _contextNodeRelations.forEach((contextId, contextRelations) {
 | 
| -      AnalysisContext context = _contextCodec.decode(contextId);
 | 
| -      if (context != null) {
 | 
| -        for (Map<Relationship, List<LocationData>> nodeRelations in
 | 
| -            contextRelations.values) {
 | 
| -          List<LocationData> nodeLocations = nodeRelations[relationship];
 | 
| -          if (nodeLocations != null) {
 | 
| -            for (LocationData locationData in nodeLocations) {
 | 
| -              Location location =
 | 
| -                  locationData.getLocation(context, _elementCodec);
 | 
| -              if (location != null) {
 | 
| -                locations.add(location);
 | 
| -              }
 | 
| -            }
 | 
| -          }
 | 
| -        }
 | 
| -      }
 | 
| -    });
 | 
| -    return locations;
 | 
| -  }
 | 
| -
 | 
| -  void _recordLibraryWithUnit(AnalysisContext context, Source library,
 | 
| -      Source unit) {
 | 
| -    Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
 | 
| -    if (libraryToUnits == null) {
 | 
| -      libraryToUnits = new HashMap<Source, Set<Source>>();
 | 
| -      _contextToLibraryToUnits[context] = libraryToUnits;
 | 
| -    }
 | 
| -    Set<Source> units = libraryToUnits[library];
 | 
| -    if (units == null) {
 | 
| -      units = new HashSet<Source>();
 | 
| -      libraryToUnits[library] = units;
 | 
| -    }
 | 
| -    units.add(unit);
 | 
| -  }
 | 
| -
 | 
| -  void _recordNodeNameForElement(Element element) {
 | 
| -    int nameId = _elementCodec.encodeHash(element);
 | 
| -    _nameToNodeNames.add(nameId, _currentNodeNameId);
 | 
| -  }
 | 
| -
 | 
| -  void _recordRelationshipUniverse(Relationship relationship,
 | 
| -      Location location) {
 | 
| -    // in current context
 | 
| -    Map<int, Map<Relationship, List<LocationData>>> nodeRelations =
 | 
| -        _contextNodeRelations[_currentContextId];
 | 
| -    if (nodeRelations == null) {
 | 
| -      nodeRelations = new HashMap<int, Map<Relationship, List<LocationData>>>();
 | 
| -      _contextNodeRelations[_currentContextId] = nodeRelations;
 | 
| -    }
 | 
| -    // in current node
 | 
| -    Map<Relationship, List<LocationData>> relations =
 | 
| -        nodeRelations[_currentNodeNameId];
 | 
| -    if (relations == null) {
 | 
| -      relations = new HashMap<Relationship, List<LocationData>>();
 | 
| -      nodeRelations[_currentNodeNameId] = relations;
 | 
| -    }
 | 
| -    // for the given relationship
 | 
| -    List<LocationData> locations = relations[relationship];
 | 
| -    if (locations == null) {
 | 
| -      locations = <LocationData>[];
 | 
| -      relations[relationship] = locations;
 | 
| -    }
 | 
| -    // record LocationData
 | 
| -    locations.add(new LocationData.forObject(_elementCodec, location));
 | 
| -  }
 | 
| -
 | 
| -  void _recordUnitInLibrary(AnalysisContext context, Source library,
 | 
| -      Source unit) {
 | 
| -    Map<Source, Set<Source>> unitToLibraries =
 | 
| -        _contextToUnitToLibraries[context];
 | 
| -    if (unitToLibraries == null) {
 | 
| -      unitToLibraries = new HashMap<Source, Set<Source>>();
 | 
| -      _contextToUnitToLibraries[context] = unitToLibraries;
 | 
| -    }
 | 
| -    Set<Source> libraries = unitToLibraries[unit];
 | 
| -    if (libraries == null) {
 | 
| -      libraries = new HashSet<Source>();
 | 
| -      unitToLibraries[unit] = libraries;
 | 
| -    }
 | 
| -    libraries.add(library);
 | 
| -  }
 | 
| -
 | 
| -  /**
 | 
| -   * Removes locations recorded in the given library/unit pair.
 | 
| -   */
 | 
| -  void _removeLocations(AnalysisContext context, Source library, Source unit) {
 | 
| -    // remove node
 | 
| -    String libraryName = library != null ? library.fullName : null;
 | 
| -    String unitName = unit.fullName;
 | 
| -    int libraryNameIndex = _stringCodec.encode(libraryName);
 | 
| -    int unitNameIndex = _stringCodec.encode(unitName);
 | 
| -    String nodeName = '${libraryNameIndex}_${unitNameIndex}.index';
 | 
| -    int nodeNameId = _stringCodec.encode(nodeName);
 | 
| -    _nodeManager.removeNode(nodeName);
 | 
| -    // remove source
 | 
| -    _sources.remove(library);
 | 
| -    _sources.remove(unit);
 | 
| -    // remove universe relations
 | 
| -    {
 | 
| -      int contextId = _contextCodec.encode(context);
 | 
| -      Map<int, Object> nodeRelations = _contextNodeRelations[contextId];
 | 
| -      if (nodeRelations != null) {
 | 
| -        nodeRelations.remove(nodeNameId);
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /**
 | 
| -   * When logging is on, [AnalysisEngine] actually creates
 | 
| -   * [InstrumentedAnalysisContextImpl], which wraps [AnalysisContextImpl] used to create
 | 
| -   * actual [Element]s. So, in index we have to unwrap [InstrumentedAnalysisContextImpl]
 | 
| -   * when perform any operation.
 | 
| -   */
 | 
| -  AnalysisContext _unwrapContext(AnalysisContext context) {
 | 
| -    if (context is InstrumentedAnalysisContextImpl) {
 | 
| -      context = (context as InstrumentedAnalysisContextImpl).basis;
 | 
| -    }
 | 
| -    return context;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -class _DataInputStream {
 | 
| -  ByteData _byteData;
 | 
| -  int _byteOffset = 0;
 | 
| -
 | 
| -  _DataInputStream(List<int> bytes) {
 | 
| -    ByteBuffer buffer = new Uint8List.fromList(bytes).buffer;
 | 
| -    _byteData = new ByteData.view(buffer);
 | 
| -  }
 | 
| -
 | 
| -  int readInt() {
 | 
| -    int result = _byteData.getInt32(_byteOffset);
 | 
| -    _byteOffset += 4;
 | 
| -    return result;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -class _DataOutputStream {
 | 
| -  BytesBuilder _buffer = new BytesBuilder();
 | 
| -
 | 
| -  Uint8List getBytes() {
 | 
| -    return new Uint8List.fromList(_buffer.takeBytes());
 | 
| -  }
 | 
| -
 | 
| -  void writeInt(int value) {
 | 
| -    _buffer.addByte((value & 0xFF000000) >> 24);
 | 
| -    _buffer.addByte((value & 0x00FF0000) >> 16);
 | 
| -    _buffer.addByte((value & 0x0000FF00) >> 8);
 | 
| -    _buffer.addByte(value & 0xFF);
 | 
| -  }
 | 
| -}
 | 
| 
 |