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

Side by Side Diff: pkg/analyzer/lib/src/index/store/split_store.dart

Issue 375693002: Move index/search to services. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library engine.src.index.split_store;
6
7 import 'dart:async';
8 import 'dart:collection';
9 import 'dart:io';
10 import 'dart:typed_data';
11
12 import 'package:analyzer/index/index.dart';
13 import 'package:analyzer/index/index_store.dart';
14 import 'package:analyzer/src/generated/element.dart';
15 import 'package:analyzer/src/generated/engine.dart';
16 import 'package:analyzer/src/generated/java_engine.dart';
17 import 'package:analyzer/src/generated/source.dart';
18 import 'package:analyzer/src/index/store/codec.dart';
19 import 'package:analyzer/src/index/store/collection.dart';
20
21
22 /**
23 * A manager for files content.
24 */
25 abstract class FileManager {
26 /**
27 * Removes all files.
28 */
29 void clear();
30
31 /**
32 * Deletes the file with the given name.
33 */
34 void delete(String name);
35
36 /**
37 * Read the entire file contents as a list of bytes.
38 */
39 Future<List<int>> read(String name);
40
41 /**
42 * Write a list of bytes to a file.
43 */
44 Future write(String name, List<int> bytes);
45 }
46
47
48 /**
49 * A [FileManager] based [NodeManager].
50 */
51 class FileNodeManager implements NodeManager {
52 static int _VERSION = 1;
53
54 final FileManager _fileManager;
55 final Logger _logger;
56
57 final ContextCodec contextCodec;
58 final ElementCodec elementCodec;
59 final StringCodec stringCodec;
60 final RelationshipCodec _relationshipCodec;
61
62 int _locationCount = 0;
63
64 Map<String, int> _nodeLocationCounts = new HashMap<String, int>();
65
66 FileNodeManager(this._fileManager, this._logger, this.stringCodec,
67 this.contextCodec, this.elementCodec, this._relationshipCodec);
68
69 @override
70 int get locationCount => _locationCount;
71
72 @override
73 void clear() {
74 _fileManager.clear();
75 }
76
77 @override
78 Future<IndexNode> getNode(String name) {
79 return _fileManager.read(name).then((List<int> bytes) {
80 if (bytes == null) {
81 return null;
82 }
83 _DataInputStream stream = new _DataInputStream(bytes);
84 return _readNode(stream);
85 }).catchError((e, stackTrace) {
86 _logger.logError2('Exception during reading index file ${name}',
87 new CaughtException(e, stackTrace));
88 });
89 }
90
91 @override
92 IndexNode newNode(AnalysisContext context) => new IndexNode(context,
93 elementCodec, _relationshipCodec);
94
95 @override
96 Future putNode(String name, IndexNode node) {
97 // update location count
98 {
99 _locationCount -= _getLocationCount(name);
100 int nodeLocationCount = node.locationCount;
101 _nodeLocationCounts[name] = nodeLocationCount;
102 _locationCount += nodeLocationCount;
103 }
104 // write the node
105 return new Future.microtask(() {
106 _DataOutputStream stream = new _DataOutputStream();
107 _writeNode(node, stream);
108 var bytes = stream.getBytes();
109 return _fileManager.write(name, bytes);
110 }).catchError((e, stackTrace) {
111 _logger.logError2('Exception during reading index file ${name}',
112 new CaughtException(e, stackTrace));
113 });
114 }
115
116 @override
117 void removeNode(String name) {
118 // update location count
119 _locationCount -= _getLocationCount(name);
120 _nodeLocationCounts.remove(name);
121 // remove node
122 _fileManager.delete(name);
123 }
124
125 int _getLocationCount(String name) {
126 int locationCount = _nodeLocationCounts[name];
127 return locationCount != null ? locationCount : 0;
128 }
129
130 RelationKeyData _readElementRelationKey(_DataInputStream stream) {
131 int elementId = stream.readInt();
132 int relationshipId = stream.readInt();
133 return new RelationKeyData.forData(elementId, relationshipId);
134 }
135
136 LocationData _readLocationData(_DataInputStream stream) {
137 int elementId = stream.readInt();
138 int offset = stream.readInt();
139 int length = stream.readInt();
140 return new LocationData.forData(elementId, offset, length);
141 }
142
143 IndexNode _readNode(_DataInputStream stream) {
144 // check version
145 {
146 int version = stream.readInt();
147 if (version != _VERSION) {
148 throw new StateError(
149 'Version ${_VERSION} expected, but ${version} found.');
150 }
151 }
152 // context
153 int contextId = stream.readInt();
154 AnalysisContext context = contextCodec.decode(contextId);
155 if (context == null) {
156 return null;
157 }
158 // relations
159 Map<RelationKeyData, List<LocationData>> relations =
160 new HashMap<RelationKeyData, List<LocationData>>();
161 int numRelations = stream.readInt();
162 for (int i = 0; i < numRelations; i++) {
163 RelationKeyData key = _readElementRelationKey(stream);
164 int numLocations = stream.readInt();
165 List<LocationData> locations = new List<LocationData>();
166 for (int j = 0; j < numLocations; j++) {
167 locations.add(_readLocationData(stream));
168 }
169 relations[key] = locations;
170 }
171 // create IndexNode
172 IndexNode node = new IndexNode(context, elementCodec, _relationshipCodec);
173 node.relations = relations;
174 return node;
175 }
176
177 void _writeElementRelationKey(_DataOutputStream stream, RelationKeyData key) {
178 stream.writeInt(key.elementId);
179 stream.writeInt(key.relationshipId);
180 }
181
182 void _writeNode(IndexNode node, _DataOutputStream stream) {
183 // version
184 stream.writeInt(_VERSION);
185 // context
186 {
187 AnalysisContext context = node.context;
188 int contextId = contextCodec.encode(context);
189 stream.writeInt(contextId);
190 }
191 // relations
192 Map<RelationKeyData, List<LocationData>> relations = node.relations;
193 stream.writeInt(relations.length);
194 relations.forEach((key, locations) {
195 _writeElementRelationKey(stream, key);
196 stream.writeInt(locations.length);
197 for (LocationData location in locations) {
198 stream.writeInt(location.elementId);
199 stream.writeInt(location.offset);
200 stream.writeInt(location.length);
201 }
202 });
203 }
204 }
205
206
207 /**
208 * A single index file in-memory presentation.
209 */
210 class IndexNode {
211 final AnalysisContext context;
212
213 final ElementCodec _elementCodec;
214 final RelationshipCodec _relationshipCodec;
215
216 Map<RelationKeyData, List<LocationData>> _relations =
217 new HashMap<RelationKeyData, List<LocationData>>();
218
219
220 IndexNode(this.context, this._elementCodec, this._relationshipCodec);
221
222 /**
223 * Returns number of locations in this node.
224 */
225 int get locationCount {
226 int locationCount = 0;
227 for (List<LocationData> locations in _relations.values) {
228 locationCount += locations.length;
229 }
230 return locationCount;
231 }
232
233 /**
234 * Returns the recorded relations.
235 */
236 Map<RelationKeyData, List<LocationData>> get relations => _relations;
237
238 /**
239 * Sets relations data.
240 * This method is used during loading data from a storage.
241 */
242 void set relations(Map<RelationKeyData, List<LocationData>> relations) {
243 _relations = relations;
244 }
245
246 /**
247 * Returns the locations of the elements that have the given relationship with
248 * the given element.
249 *
250 * [element] - the the element that has the relationship with the locations to
251 * be returned.
252 * [relationship] - the [Relationship] between the given [element] and the
253 * locations to be returned
254 */
255 List<Location> getRelationships(Element element, Relationship relationship) {
256 // prepare key
257 RelationKeyData key = new RelationKeyData.forObject(_elementCodec,
258 _relationshipCodec, element, relationship);
259 // find LocationData(s)
260 List<LocationData> locationDatas = _relations[key];
261 if (locationDatas == null) {
262 return Location.EMPTY_ARRAY;
263 }
264 // convert to Location(s)
265 List<Location> locations = <Location>[];
266 for (LocationData locationData in locationDatas) {
267 Location location = locationData.getLocation(context, _elementCodec);
268 if (location != null) {
269 locations.add(location);
270 }
271 }
272 return locations;
273 }
274
275 /**
276 * Records that the given [element] and [location] have the given [relationshi p].
277 *
278 * [element] - the [Element] that is related to the location.
279 * [relationship] - the [Relationship] between [element] and [location].
280 * [location] - the [Location] where relationship happens.
281 */
282 void recordRelationship(Element element, Relationship relationship,
283 Location location) {
284 RelationKeyData key = new RelationKeyData.forObject(_elementCodec,
285 _relationshipCodec, element, relationship);
286 // prepare LocationData(s)
287 List<LocationData> locationDatas = _relations[key];
288 if (locationDatas == null) {
289 locationDatas = <LocationData>[];
290 _relations[key] = locationDatas;
291 }
292 // add new LocationData
293 locationDatas.add(new LocationData.forObject(_elementCodec, location));
294 }
295 }
296
297
298 /**
299 * A container with information about a [Location].
300 */
301 class LocationData {
302 final int elementId;
303 final int offset;
304 final int length;
305
306 LocationData.forData(this.elementId, this.offset, this.length);
307
308 LocationData.forObject(ElementCodec elementCodec, Location location)
309 : elementId = elementCodec.encode(location.element),
310 offset = location.offset,
311 length = location.length;
312
313 @override
314 int get hashCode {
315 return 31 * (31 * elementId + offset) + length;
316 }
317
318 @override
319 bool operator ==(Object obj) {
320 if (obj is! LocationData) {
321 return false;
322 }
323 LocationData other = obj;
324 return other.elementId == elementId && other.offset == offset &&
325 other.length == length;
326 }
327
328 /**
329 * Returns a {@link Location} that is represented by this {@link LocationData} .
330 */
331 Location getLocation(AnalysisContext context, ElementCodec elementCodec) {
332 Element element = elementCodec.decode(context, elementId);
333 if (element == null) {
334 return null;
335 }
336 return new Location(element, offset, length);
337 }
338 }
339
340
341 /**
342 * A manager for [IndexNode]s.
343 */
344 abstract class NodeManager {
345 /**
346 * The shared {@link ContextCodec} instance.
347 */
348 ContextCodec get contextCodec;
349
350 /**
351 * The shared {@link ElementCodec} instance.
352 */
353 ElementCodec get elementCodec;
354
355 /**
356 * A number of locations in all nodes.
357 */
358 int get locationCount;
359
360 /**
361 * The shared {@link StringCodec} instance.
362 */
363 StringCodec get stringCodec;
364
365 /**
366 * Removes all nodes.
367 */
368 void clear();
369
370 /**
371 * Returns the {@link IndexNode} with the given name, {@code null} if not foun d.
372 */
373 Future<IndexNode> getNode(String name);
374
375 /**
376 * Returns a new {@link IndexNode}.
377 */
378 IndexNode newNode(AnalysisContext context);
379
380 /**
381 * Associates the given {@link IndexNode} with the given name.
382 */
383 void putNode(String name, IndexNode node);
384
385 /**
386 * Removes the {@link IndexNode} with the given name.
387 */
388 void removeNode(String name);
389 }
390
391
392 /**
393 * An [Element] to [Location] relation key.
394 */
395 class RelationKeyData {
396 final int elementId;
397 final int relationshipId;
398
399 RelationKeyData.forData(this.elementId, this.relationshipId);
400
401 RelationKeyData.forObject(ElementCodec elementCodec,
402 RelationshipCodec relationshipCodec, Element element, Relationship relatio nship)
403 : elementId = elementCodec.encode(element),
404 relationshipId = relationshipCodec.encode(relationship);
405
406 @override
407 int get hashCode {
408 return 31 * elementId + relationshipId;
409 }
410
411 @override
412 bool operator ==(Object obj) {
413 if (obj is! RelationKeyData) {
414 return false;
415 }
416 RelationKeyData other = obj;
417 return other.elementId == elementId && other.relationshipId ==
418 relationshipId;
419 }
420 }
421
422
423 /**
424 * An [IndexStore] which keeps index information in separate nodes for each unit .
425 */
426 class SplitIndexStore implements IndexStore {
427 /**
428 * The [ContextCodec] to encode/decode [AnalysisContext]s.
429 */
430 ContextCodec _contextCodec;
431
432 /**
433 * Information about "universe" elements.
434 * We need to keep them together to avoid loading of all index nodes.
435 *
436 * Order of keys: contextId, nodeId, Relationship.
437 */
438 Map<int, Map<int, Map<Relationship, List<LocationData>>>>
439 _contextNodeRelations = new HashMap<int, Map<int, Map<Relationship,
440 List<LocationData>>>>();
441
442 /**
443 * The mapping of library [Source] to the [Source]s of part units.
444 */
445 Map<AnalysisContext, Map<Source, Set<Source>>> _contextToLibraryToUnits =
446 new HashMap<AnalysisContext, Map<Source, Set<Source>>>();
447
448 /**
449 * The mapping of unit [Source] to the [Source]s of libraries it is used in.
450 */
451 Map<AnalysisContext, Map<Source, Set<Source>>> _contextToUnitToLibraries =
452 new HashMap<AnalysisContext, Map<Source, Set<Source>>>();
453
454 int _currentContextId = 0;
455
456 IndexNode _currentNode;
457
458 String _currentNodeName;
459
460 int _currentNodeNameId = 0;
461
462 /**
463 * The [ElementCodec] to encode/decode [Element]s.
464 */
465 ElementCodec _elementCodec;
466
467 /**
468 * A table mapping element names to the node names that may have relations wit h elements with
469 * these names.
470 */
471 IntToIntSetMap _nameToNodeNames = new IntToIntSetMap();
472
473 /**
474 * The [NodeManager] to get/put [IndexNode]s.
475 */
476 final NodeManager _nodeManager;
477
478 /**
479 * The set of known [Source]s.
480 */
481 Set<Source> _sources = new HashSet<Source>();
482
483 /**
484 * The [StringCodec] to encode/decode [String]s.
485 */
486 StringCodec _stringCodec;
487
488 SplitIndexStore(this._nodeManager) {
489 this._contextCodec = _nodeManager.contextCodec;
490 this._elementCodec = _nodeManager.elementCodec;
491 this._stringCodec = _nodeManager.stringCodec;
492 }
493
494 @override
495 String get statistics =>
496 '[${_nodeManager.locationCount} locations, ${_sources.length} sources, ${_ nameToNodeNames.length} names]';
497
498 @override
499 bool aboutToIndexDart(AnalysisContext context,
500 CompilationUnitElement unitElement) {
501 context = _unwrapContext(context);
502 // may be already disposed in other thread
503 if (context.isDisposed) {
504 return false;
505 }
506 // validate unit
507 if (unitElement == null) {
508 return false;
509 }
510 LibraryElement libraryElement = unitElement.library;
511 if (libraryElement == null) {
512 return false;
513 }
514 CompilationUnitElement definingUnitElement =
515 libraryElement.definingCompilationUnit;
516 if (definingUnitElement == null) {
517 return false;
518 }
519 // prepare sources
520 Source library = definingUnitElement.source;
521 Source unit = unitElement.source;
522 // special handling for the defining library unit
523 if (unit == library) {
524 // prepare new parts
525 HashSet<Source> newParts = new HashSet<Source>();
526 for (CompilationUnitElement part in libraryElement.parts) {
527 newParts.add(part.source);
528 }
529 // prepare old parts
530 Map<Source, Set<Source>> libraryToUnits =
531 _contextToLibraryToUnits[context];
532 if (libraryToUnits == null) {
533 libraryToUnits = new HashMap<Source, Set<Source>>();
534 _contextToLibraryToUnits[context] = libraryToUnits;
535 }
536 Set<Source> oldParts = libraryToUnits[library];
537 // check if some parts are not in the library now
538 if (oldParts != null) {
539 Set<Source> noParts = oldParts.difference(newParts);
540 for (Source noPart in noParts) {
541 _removeLocations(context, library, noPart);
542 }
543 }
544 // remember new parts
545 libraryToUnits[library] = newParts;
546 }
547 // remember library/unit relations
548 _recordUnitInLibrary(context, library, unit);
549 _recordLibraryWithUnit(context, library, unit);
550 _sources.add(library);
551 _sources.add(unit);
552 // prepare node
553 String libraryName = library.fullName;
554 String unitName = unit.fullName;
555 int libraryNameIndex = _stringCodec.encode(libraryName);
556 int unitNameIndex = _stringCodec.encode(unitName);
557 _currentNodeName = '${libraryNameIndex}_${unitNameIndex}.index';
558 _currentNodeNameId = _stringCodec.encode(_currentNodeName);
559 _currentNode = _nodeManager.newNode(context);
560 _currentContextId = _contextCodec.encode(context);
561 // remove Universe information for the current node
562 for (Map<int, dynamic> nodeRelations in _contextNodeRelations.values) {
563 nodeRelations.remove(_currentNodeNameId);
564 }
565 // done
566 return true;
567 }
568
569 @override
570 bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement) {
571 context = _unwrapContext(context);
572 // may be already disposed in other thread
573 if (context.isDisposed) {
574 return false;
575 }
576 // remove locations
577 Source source = htmlElement.source;
578 _removeLocations(context, null, source);
579 // remember library/unit relations
580 _recordUnitInLibrary(context, null, source);
581 // prepare node
582 String sourceName = source.fullName;
583 int sourceNameIndex = _stringCodec.encode(sourceName);
584 _currentNodeName = '${sourceNameIndex}.index';
585 _currentNodeNameId = _stringCodec.encode(_currentNodeName);
586 _currentNode = _nodeManager.newNode(context);
587 return true;
588 }
589
590 @override
591 void clear() {
592 _contextNodeRelations.clear();
593 _nodeManager.clear();
594 _nameToNodeNames.clear();
595 }
596
597 @override
598 void doneIndex() {
599 if (_currentNode != null) {
600 _nodeManager.putNode(_currentNodeName, _currentNode);
601 _currentNodeName = null;
602 _currentNodeNameId = -1;
603 _currentNode = null;
604 _currentContextId = -1;
605 }
606 }
607
608 Future<List<Location>> getRelationships(Element element,
609 Relationship relationship) {
610 // special support for UniverseElement
611 if (identical(element, UniverseElement.INSTANCE)) {
612 List<Location> locations = _getRelationshipsUniverse(relationship);
613 return new Future.value(locations);
614 }
615 // prepare node names
616 String name = _getElementName(element);
617 int nameId = _stringCodec.encode(name);
618 List<int> nodeNameIds = _nameToNodeNames.get(nameId);
619 // prepare Future(s) for reading each IndexNode
620 List<Future<List<Location>>> nodeFutures = <Future<List<Location>>>[];
621 for (int nodeNameId in nodeNameIds) {
622 String nodeName = _stringCodec.decode(nodeNameId);
623 Future<IndexNode> nodeFuture = _nodeManager.getNode(nodeName);
624 Future<List<Location>> locationsFuture = nodeFuture.then((node) {
625 if (node == null) {
626 // TODO(scheglov) remove node
627 return Location.EMPTY_ARRAY;
628 }
629 return node.getRelationships(element, relationship);
630 });
631 nodeFutures.add(locationsFuture);
632 }
633 // return Future that merges separate IndexNode Location(s)
634 return Future.wait(nodeFutures).then((List<List<Location>> locationsList) {
635 List<Location> allLocations = <Location>[];
636 for (List<Location> locations in locationsList) {
637 allLocations.addAll(locations);
638 }
639 return allLocations;
640 });
641 }
642
643 @override
644 void recordRelationship(Element element, Relationship relationship,
645 Location location) {
646 if (element == null || location == null) {
647 return;
648 }
649 // special support for UniverseElement
650 if (identical(element, UniverseElement.INSTANCE)) {
651 _recordRelationshipUniverse(relationship, location);
652 return;
653 }
654 // other elements
655 _recordNodeNameForElement(element);
656 _currentNode.recordRelationship(element, relationship, location);
657 }
658
659 @override
660 void removeContext(AnalysisContext context) {
661 context = _unwrapContext(context);
662 if (context == null) {
663 return;
664 }
665 // remove sources
666 removeSources(context, null);
667 // remove context information
668 _contextToLibraryToUnits.remove(context);
669 _contextToUnitToLibraries.remove(context);
670 _contextNodeRelations.remove(_contextCodec.encode(context));
671 // remove context from codec
672 _contextCodec.remove(context);
673 }
674
675 @override
676 void removeSource(AnalysisContext context, Source source) {
677 context = _unwrapContext(context);
678 if (context == null) {
679 return;
680 }
681 // remove nodes for unit/library pairs
682 Map<Source, Set<Source>> unitToLibraries =
683 _contextToUnitToLibraries[context];
684 if (unitToLibraries != null) {
685 Set<Source> libraries = unitToLibraries.remove(source);
686 if (libraries != null) {
687 for (Source library in libraries) {
688 _removeLocations(context, library, source);
689 }
690 }
691 }
692 // remove nodes for library/unit pairs
693 Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
694 if (libraryToUnits != null) {
695 Set<Source> units = libraryToUnits.remove(source);
696 if (units != null) {
697 for (Source unit in units) {
698 _removeLocations(context, source, unit);
699 }
700 }
701 }
702 }
703
704 @override
705 void removeSources(AnalysisContext context, SourceContainer container) {
706 context = _unwrapContext(context);
707 if (context == null) {
708 return;
709 }
710 // remove nodes for unit/library pairs
711 Map<Source, Set<Source>> unitToLibraries =
712 _contextToUnitToLibraries[context];
713 if (unitToLibraries != null) {
714 List<Source> units = new List<Source>.from(unitToLibraries.keys);
715 for (Source source in units) {
716 if (container == null || container.contains(source)) {
717 removeSource(context, source);
718 }
719 }
720 }
721 // remove nodes for library/unit pairs
722 Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
723 if (libraryToUnits != null) {
724 List<Source> libraries = new List<Source>.from(libraryToUnits.keys);
725 for (Source source in libraries) {
726 if (container == null || container.contains(source)) {
727 removeSource(context, source);
728 }
729 }
730 }
731 }
732
733 String _getElementName(Element element) => element.name;
734
735 List<Location> _getRelationshipsUniverse(Relationship relationship) {
736 List<Location> locations = <Location>[];
737 _contextNodeRelations.forEach((contextId, contextRelations) {
738 AnalysisContext context = _contextCodec.decode(contextId);
739 if (context != null) {
740 for (Map<Relationship, List<LocationData>> nodeRelations in
741 contextRelations.values) {
742 List<LocationData> nodeLocations = nodeRelations[relationship];
743 if (nodeLocations != null) {
744 for (LocationData locationData in nodeLocations) {
745 Location location = locationData.getLocation(context,
746 _elementCodec);
747 if (location != null) {
748 locations.add(location);
749 }
750 }
751 }
752 }
753 }
754 });
755 return locations;
756 }
757
758 void _recordLibraryWithUnit(AnalysisContext context, Source library,
759 Source unit) {
760 Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
761 if (libraryToUnits == null) {
762 libraryToUnits = new HashMap<Source, Set<Source>>();
763 _contextToLibraryToUnits[context] = libraryToUnits;
764 }
765 Set<Source> units = libraryToUnits[library];
766 if (units == null) {
767 units = new HashSet<Source>();
768 libraryToUnits[library] = units;
769 }
770 units.add(unit);
771 }
772
773 void _recordNodeNameForElement(Element element) {
774 String name = _getElementName(element);
775 int nameId = _stringCodec.encode(name);
776 _nameToNodeNames.add(nameId, _currentNodeNameId);
777 }
778
779 void _recordRelationshipUniverse(Relationship relationship,
780 Location location) {
781 // in current context
782 Map<int, Map<Relationship, List<LocationData>>> nodeRelations =
783 _contextNodeRelations[_currentContextId];
784 if (nodeRelations == null) {
785 nodeRelations = new HashMap<int, Map<Relationship, List<LocationData>>>();
786 _contextNodeRelations[_currentContextId] = nodeRelations;
787 }
788 // in current node
789 Map<Relationship, List<LocationData>> relations =
790 nodeRelations[_currentNodeNameId];
791 if (relations == null) {
792 relations = new HashMap<Relationship, List<LocationData>>();
793 nodeRelations[_currentNodeNameId] = relations;
794 }
795 // for the given relationship
796 List<LocationData> locations = relations[relationship];
797 if (locations == null) {
798 locations = <LocationData>[];
799 relations[relationship] = locations;
800 }
801 // record LocationData
802 locations.add(new LocationData.forObject(_elementCodec, location));
803 }
804
805 void _recordUnitInLibrary(AnalysisContext context, Source library,
806 Source unit) {
807 Map<Source, Set<Source>> unitToLibraries =
808 _contextToUnitToLibraries[context];
809 if (unitToLibraries == null) {
810 unitToLibraries = new HashMap<Source, Set<Source>>();
811 _contextToUnitToLibraries[context] = unitToLibraries;
812 }
813 Set<Source> libraries = unitToLibraries[unit];
814 if (libraries == null) {
815 libraries = new HashSet<Source>();
816 unitToLibraries[unit] = libraries;
817 }
818 libraries.add(library);
819 }
820
821 /**
822 * Removes locations recorded in the given library/unit pair.
823 */
824 void _removeLocations(AnalysisContext context, Source library, Source unit) {
825 // remove node
826 String libraryName = library != null ? library.fullName : null;
827 String unitName = unit.fullName;
828 int libraryNameIndex = _stringCodec.encode(libraryName);
829 int unitNameIndex = _stringCodec.encode(unitName);
830 String nodeName = '${libraryNameIndex}_${unitNameIndex}.index';
831 int nodeNameId = _stringCodec.encode(nodeName);
832 _nodeManager.removeNode(nodeName);
833 // remove source
834 _sources.remove(library);
835 _sources.remove(unit);
836 // remove universe relations
837 {
838 int contextId = _contextCodec.encode(context);
839 Map<int, Object> nodeRelations = _contextNodeRelations[contextId];
840 if (nodeRelations != null) {
841 nodeRelations.remove(nodeNameId);
842 }
843 }
844 }
845
846 /**
847 * When logging is on, [AnalysisEngine] actually creates
848 * [InstrumentedAnalysisContextImpl], which wraps [AnalysisContextImpl] used t o create
849 * actual [Element]s. So, in index we have to unwrap [InstrumentedAnalysisCont extImpl]
850 * when perform any operation.
851 */
852 AnalysisContext _unwrapContext(AnalysisContext context) {
853 if (context is InstrumentedAnalysisContextImpl) {
854 context = (context as InstrumentedAnalysisContextImpl).basis;
855 }
856 return context;
857 }
858 }
859
860
861 class _DataInputStream {
862 ByteData _byteData;
863 int _byteOffset = 0;
864
865 _DataInputStream(List<int> bytes) {
866 ByteBuffer buffer = new Uint8List.fromList(bytes).buffer;
867 _byteData = new ByteData.view(buffer);
868 }
869
870 int readInt() {
871 int result = _byteData.getInt32(_byteOffset);
872 _byteOffset += 4;
873 return result;
874 }
875 }
876
877
878 class _DataOutputStream {
879 BytesBuilder _buffer = new BytesBuilder();
880
881 Uint8List getBytes() {
882 return new Uint8List.fromList(_buffer.takeBytes());
883 }
884
885 void writeInt(int value) {
886 _buffer.addByte((value & 0xFF000000) >> 24);
887 _buffer.addByte((value & 0x00FF0000) >> 16);
888 _buffer.addByte((value & 0x0000FF00) >> 8);
889 _buffer.addByte(value & 0xFF);
890 }
891 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/index/store/separate_file_manager.dart ('k') | pkg/analyzer/lib/src/search/search_engine.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698