| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library index.split.store; | 5 library index.split.store; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 import 'dart:io'; | 9 import 'dart:io'; |
| 10 import 'dart:typed_data'; | 10 import 'dart:typed_data'; |
| 11 | 11 |
| 12 import 'package:analysis_server/src/index/store/collection.dart'; |
| 12 import 'package:analyzer/src/generated/element.dart'; | 13 import 'package:analyzer/src/generated/element.dart'; |
| 13 import 'package:analyzer/src/generated/engine.dart'; | 14 import 'package:analyzer/src/generated/engine.dart'; |
| 14 import 'package:analyzer/src/generated/index.dart'; | 15 import 'package:analyzer/src/generated/index.dart'; |
| 15 import 'package:analyzer/src/generated/java_engine.dart'; | 16 import 'package:analyzer/src/generated/java_engine.dart'; |
| 16 import 'package:analyzer/src/generated/source.dart'; | 17 import 'package:analyzer/src/generated/source.dart'; |
| 18 import 'package:analysis_server/src/index/store/codec.dart'; |
| 17 | 19 |
| 18 | 20 |
| 19 /** | 21 /** |
| 20 * A helper that encodes/decodes [AnalysisContext]s from/to integers. | |
| 21 * | |
| 22 * TODO(scheglov) add API to remove [AnalysisContext]s. | |
| 23 */ | |
| 24 class ContextCodec { | |
| 25 /** | |
| 26 * A table mapping contexts to their unique indices. | |
| 27 */ | |
| 28 Map<AnalysisContext, int> _contextToIndex = new HashMap<AnalysisContext, int>( | |
| 29 ); | |
| 30 | |
| 31 /** | |
| 32 * A table mapping indices to the corresponding contexts. | |
| 33 */ | |
| 34 Map<int, AnalysisContext> _indexToContext = new HashMap<int, AnalysisContext>( | |
| 35 ); | |
| 36 | |
| 37 /** | |
| 38 * The next id to assign. | |
| 39 */ | |
| 40 int _nextId = 0; | |
| 41 | |
| 42 /** | |
| 43 * Returns the [AnalysisContext] that corresponds to the given index. | |
| 44 */ | |
| 45 AnalysisContext decode(int index) => _indexToContext[index]; | |
| 46 | |
| 47 /** | |
| 48 * Returns an unique index for the given [AnalysisContext]. | |
| 49 */ | |
| 50 int encode(AnalysisContext context) { | |
| 51 int index = _contextToIndex[context]; | |
| 52 if (index == null) { | |
| 53 index = _nextId++; | |
| 54 _contextToIndex[context] = index; | |
| 55 _indexToContext[index] = context; | |
| 56 } | |
| 57 return index; | |
| 58 } | |
| 59 | |
| 60 /** | |
| 61 * Removes the given [context]. | |
| 62 */ | |
| 63 void remove(AnalysisContext context) { | |
| 64 int id = _contextToIndex.remove(context); | |
| 65 if (id != null) { | |
| 66 _indexToContext.remove(id); | |
| 67 } | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 | |
| 72 /** | |
| 73 * A helper that encodes/decodes [Element]s to/from integers. | |
| 74 */ | |
| 75 class ElementCodec { | |
| 76 /** | |
| 77 * A list that works as a mapping of integers to element encodings (in form of
integer arrays). | |
| 78 */ | |
| 79 List<List<int>> _indexToPath = []; | |
| 80 | |
| 81 /** | |
| 82 * A table mapping element locations (in form of integer arrays) into a single
integer. | |
| 83 */ | |
| 84 IntArrayToIntMap _pathToIndex = new IntArrayToIntMap(10000, 0.75); | |
| 85 | |
| 86 final StringCodec _stringCodec; | |
| 87 | |
| 88 ElementCodec(this._stringCodec); | |
| 89 | |
| 90 /** | |
| 91 * Returns an [Element] that corresponds to the given location. | |
| 92 * | |
| 93 * @param context the [AnalysisContext] to find [Element] in | |
| 94 * @param index an integer corresponding to the [Element] | |
| 95 * @return the [Element] or `null` | |
| 96 */ | |
| 97 Element decode(AnalysisContext context, int index) { | |
| 98 List<int> path = _indexToPath[index]; | |
| 99 List<String> components = _getLocationComponents(path); | |
| 100 ElementLocation location = new ElementLocationImpl.con3(components); | |
| 101 return context.getElement(location); | |
| 102 } | |
| 103 | |
| 104 /** | |
| 105 * Returns a unique integer that corresponds to the given [Element]. | |
| 106 */ | |
| 107 int encode(Element element) { | |
| 108 List<int> path = _getLocationPath(element); | |
| 109 int index = _pathToIndex.get(path, -1); | |
| 110 if (index == -1) { | |
| 111 index = _indexToPath.length; | |
| 112 _pathToIndex.put(path, index); | |
| 113 _indexToPath.add(path); | |
| 114 } | |
| 115 return index; | |
| 116 } | |
| 117 | |
| 118 List<String> _getLocationComponents(List<int> path) { | |
| 119 int length = path.length; | |
| 120 List<String> components = new List<String>(); | |
| 121 for (int i = 0; i < length; i++) { | |
| 122 int componentId = path[i]; | |
| 123 String component = _stringCodec.decode(componentId); | |
| 124 if (i < length - 1 && path[i + 1] < 0) { | |
| 125 component += '@${(-path[i + 1])}'; | |
| 126 i++; | |
| 127 } | |
| 128 components.add(component); | |
| 129 } | |
| 130 return components; | |
| 131 } | |
| 132 | |
| 133 List<int> _getLocationPath(Element element) { | |
| 134 List<String> components = element.location.components; | |
| 135 int length = components.length; | |
| 136 if (_hasLocalOffset(components)) { | |
| 137 List<int> path = new List<int>(); | |
| 138 for (String component in components) { | |
| 139 int atOffset = component.indexOf('@'); | |
| 140 if (atOffset == -1) { | |
| 141 path.add(_stringCodec.encode(component)); | |
| 142 } else { | |
| 143 String preAtString = component.substring(0, atOffset); | |
| 144 String atString = component.substring(atOffset + 1); | |
| 145 path.add(_stringCodec.encode(preAtString)); | |
| 146 path.add(-1 * int.parse(atString)); | |
| 147 } | |
| 148 } | |
| 149 return path; | |
| 150 } else { | |
| 151 List<int> path = new List<int>.filled(length, 0); | |
| 152 for (int i = 0; i < length; i++) { | |
| 153 String component = components[i]; | |
| 154 path[i] = _stringCodec.encode(component); | |
| 155 } | |
| 156 return path; | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 bool _hasLocalOffset(List<String> components) { | |
| 161 for (String component in components) { | |
| 162 if (component.indexOf('@') != -1) { | |
| 163 return true; | |
| 164 } | |
| 165 } | |
| 166 return false; | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 | |
| 171 /** | |
| 172 * A manager for files content. | 22 * A manager for files content. |
| 173 */ | 23 */ |
| 174 abstract class FileManager { | 24 abstract class FileManager { |
| 175 /** | 25 /** |
| 176 * Removes all files. | 26 * Removes all files. |
| 177 */ | 27 */ |
| 178 void clear(); | 28 void clear(); |
| 179 | 29 |
| 180 /** | 30 /** |
| 181 * Deletes the file with the given name. | 31 * Deletes the file with the given name. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 205 final ElementCodec elementCodec; | 55 final ElementCodec elementCodec; |
| 206 | 56 |
| 207 final StringCodec stringCodec; | 57 final StringCodec stringCodec; |
| 208 | 58 |
| 209 final FileManager _fileManager; | 59 final FileManager _fileManager; |
| 210 | 60 |
| 211 int _locationCount = 0; | 61 int _locationCount = 0; |
| 212 | 62 |
| 213 final Logger _logger; | 63 final Logger _logger; |
| 214 | 64 |
| 215 Map<String, int> _nodeLocationCounts = {}; | 65 Map<String, int> _nodeLocationCounts = new HashMap<String, int>(); |
| 216 | 66 |
| 217 final RelationshipCodec _relationshipCodec; | 67 final RelationshipCodec _relationshipCodec; |
| 218 | 68 |
| 219 FileNodeManager(this._fileManager, this._logger, this.stringCodec, | 69 FileNodeManager(this._fileManager, this._logger, this.stringCodec, |
| 220 this.contextCodec, this.elementCodec, this._relationshipCodec); | 70 this.contextCodec, this.elementCodec, this._relationshipCodec); |
| 221 | 71 |
| 222 @override | 72 @override |
| 223 int get locationCount => _locationCount; | 73 int get locationCount => _locationCount; |
| 224 | 74 |
| 225 @override | 75 @override |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 'Version ${_VERSION} expected, but ${version} found.'); | 152 'Version ${_VERSION} expected, but ${version} found.'); |
| 303 } | 153 } |
| 304 } | 154 } |
| 305 // context | 155 // context |
| 306 int contextId = stream.readInt(); | 156 int contextId = stream.readInt(); |
| 307 AnalysisContext context = contextCodec.decode(contextId); | 157 AnalysisContext context = contextCodec.decode(contextId); |
| 308 if (context == null) { | 158 if (context == null) { |
| 309 return null; | 159 return null; |
| 310 } | 160 } |
| 311 // relations | 161 // relations |
| 312 Map<RelationKeyData, List<LocationData>> relations = {}; | 162 Map<RelationKeyData, List<LocationData>> relations = |
| 163 new HashMap<RelationKeyData, List<LocationData>>(); |
| 313 int numRelations = stream.readInt(); | 164 int numRelations = stream.readInt(); |
| 314 for (int i = 0; i < numRelations; i++) { | 165 for (int i = 0; i < numRelations; i++) { |
| 315 RelationKeyData key = _readElementRelationKey(stream); | 166 RelationKeyData key = _readElementRelationKey(stream); |
| 316 int numLocations = stream.readInt(); | 167 int numLocations = stream.readInt(); |
| 317 List<LocationData> locations = new List<LocationData>(); | 168 List<LocationData> locations = new List<LocationData>(); |
| 318 for (int j = 0; j < numLocations; j++) { | 169 for (int j = 0; j < numLocations; j++) { |
| 319 locations.add(_readLocationData(stream)); | 170 locations.add(_readLocationData(stream)); |
| 320 } | 171 } |
| 321 relations[key] = locations; | 172 relations[key] = locations; |
| 322 } | 173 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 List<Location> getRelationships(Element element, Relationship relationship) { | 256 List<Location> getRelationships(Element element, Relationship relationship) { |
| 406 // prepare key | 257 // prepare key |
| 407 RelationKeyData key = new RelationKeyData.forObject(_elementCodec, | 258 RelationKeyData key = new RelationKeyData.forObject(_elementCodec, |
| 408 _relationshipCodec, element, relationship); | 259 _relationshipCodec, element, relationship); |
| 409 // find LocationData(s) | 260 // find LocationData(s) |
| 410 List<LocationData> locationDatas = _relations[key]; | 261 List<LocationData> locationDatas = _relations[key]; |
| 411 if (locationDatas == null) { | 262 if (locationDatas == null) { |
| 412 return Location.EMPTY_ARRAY; | 263 return Location.EMPTY_ARRAY; |
| 413 } | 264 } |
| 414 // convert to Location(s) | 265 // convert to Location(s) |
| 415 List<Location> locations = []; | 266 List<Location> locations = <Location>[]; |
| 416 for (LocationData locationData in locationDatas) { | 267 for (LocationData locationData in locationDatas) { |
| 417 Location location = locationData.getLocation(context, _elementCodec); | 268 Location location = locationData.getLocation(context, _elementCodec); |
| 418 if (location != null) { | 269 if (location != null) { |
| 419 locations.add(location); | 270 locations.add(location); |
| 420 } | 271 } |
| 421 } | 272 } |
| 422 return locations; | 273 return locations; |
| 423 } | 274 } |
| 424 | 275 |
| 425 /** | 276 /** |
| 426 * Records that the given element and location have the given relationship. | 277 * Records that the given element and location have the given relationship. |
| 427 * | 278 * |
| 428 * @param element the element that is related to the location | 279 * @param element the element that is related to the location |
| 429 * @param relationship the [Relationship] between the element and the location | 280 * @param relationship the [Relationship] between the element and the location |
| 430 * @param location the [Location] where relationship happens | 281 * @param location the [Location] where relationship happens |
| 431 */ | 282 */ |
| 432 void recordRelationship(Element element, Relationship relationship, | 283 void recordRelationship(Element element, Relationship relationship, |
| 433 Location location) { | 284 Location location) { |
| 434 RelationKeyData key = new RelationKeyData.forObject(_elementCodec, | 285 RelationKeyData key = new RelationKeyData.forObject(_elementCodec, |
| 435 _relationshipCodec, element, relationship); | 286 _relationshipCodec, element, relationship); |
| 436 // prepare LocationData(s) | 287 // prepare LocationData(s) |
| 437 List<LocationData> locationDatas = _relations[key]; | 288 List<LocationData> locationDatas = _relations[key]; |
| 438 if (locationDatas == null) { | 289 if (locationDatas == null) { |
| 439 locationDatas = []; | 290 locationDatas = <LocationData>[]; |
| 440 _relations[key] = locationDatas; | 291 _relations[key] = locationDatas; |
| 441 } | 292 } |
| 442 // add new LocationData | 293 // add new LocationData |
| 443 locationDatas.add(new LocationData.forObject(_elementCodec, location)); | 294 locationDatas.add(new LocationData.forObject(_elementCodec, location)); |
| 444 } | 295 } |
| 445 } | 296 } |
| 446 | 297 |
| 447 | 298 |
| 448 class IntArrayToIntMap { | |
| 449 // TODO(scheglov) consider using Int32List | |
| 450 final Map<List<int>, int> map = new HashMap<List<int>, int>(equals: | |
| 451 _intArrayEquals, hashCode: _intArrayHashCode); | |
| 452 | |
| 453 IntArrayToIntMap(int initialCapacity, double loadFactor); | |
| 454 | |
| 455 int get(List<int> key, int defaultValue) { | |
| 456 int value = map[key]; | |
| 457 if (value == null) { | |
| 458 return defaultValue; | |
| 459 } | |
| 460 return value; | |
| 461 } | |
| 462 | |
| 463 void put(List<int> key, int value) { | |
| 464 map[key] = value; | |
| 465 } | |
| 466 | |
| 467 static bool _intArrayEquals(List<int> a, List<int> b) { | |
| 468 int length = a.length; | |
| 469 if (length != b.length) { | |
| 470 return false; | |
| 471 } | |
| 472 for (int i = 0; i < length; i++) { | |
| 473 if (a[i] != b[i]) { | |
| 474 return false; | |
| 475 } | |
| 476 } | |
| 477 return true; | |
| 478 } | |
| 479 | |
| 480 static int _intArrayHashCode(List<int> key) { | |
| 481 return key.fold(0, (int result, int item) { | |
| 482 return 31 * result + item; | |
| 483 }); | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 | |
| 488 class IntToIntSetMap { | |
| 489 // TODO(scheglov) consider using Int32List | |
| 490 final Map<int, List<int>> _map = new HashMap<int, List<int>>(); | |
| 491 int _size = 0; | |
| 492 | |
| 493 IntToIntSetMap(int initialCapacity, double loadFactor); | |
| 494 | |
| 495 int get length => _size; | |
| 496 | |
| 497 void add(int key, int value) { | |
| 498 List<int> values = _map[key]; | |
| 499 if (values == null) { | |
| 500 values = new List<int>(); | |
| 501 _map[key] = values; | |
| 502 } | |
| 503 if (values.indexOf(value) == -1) { | |
| 504 values.add(value); | |
| 505 _size++; | |
| 506 } | |
| 507 } | |
| 508 | |
| 509 void clear() { | |
| 510 _map.clear(); | |
| 511 _size = 0; | |
| 512 } | |
| 513 | |
| 514 List<int> get(int key) { | |
| 515 List<int> values = _map[key]; | |
| 516 if (values == null) { | |
| 517 values = <int>[]; | |
| 518 } | |
| 519 return values; | |
| 520 } | |
| 521 } | |
| 522 | |
| 523 | |
| 524 /** | 299 /** |
| 525 * A container with information about a [Location]. | 300 * A container with information about a [Location]. |
| 526 */ | 301 */ |
| 527 class LocationData { | 302 class LocationData { |
| 528 final int elementId; | 303 final int elementId; |
| 529 final int length; | 304 final int length; |
| 530 final int offset; | 305 final int offset; |
| 531 | 306 |
| 532 LocationData.forData(this.elementId, this.offset, this.length); | 307 LocationData.forData(this.elementId, this.offset, this.length); |
| 533 | 308 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 return false; | 415 return false; |
| 641 } | 416 } |
| 642 RelationKeyData other = obj; | 417 RelationKeyData other = obj; |
| 643 return other.elementId == elementId && other.relationshipId == | 418 return other.elementId == elementId && other.relationshipId == |
| 644 relationshipId; | 419 relationshipId; |
| 645 } | 420 } |
| 646 } | 421 } |
| 647 | 422 |
| 648 | 423 |
| 649 /** | 424 /** |
| 650 * A helper that encodes/decodes [Relationship]s to/from integers. | |
| 651 */ | |
| 652 class RelationshipCodec { | |
| 653 final StringCodec _stringCodec; | |
| 654 | |
| 655 RelationshipCodec(this._stringCodec); | |
| 656 | |
| 657 Relationship decode(int idIndex) { | |
| 658 String id = _stringCodec.decode(idIndex); | |
| 659 return Relationship.getRelationship(id); | |
| 660 } | |
| 661 | |
| 662 int encode(Relationship relationship) { | |
| 663 String id = relationship.identifier; | |
| 664 return _stringCodec.encode(id); | |
| 665 } | |
| 666 } | |
| 667 | |
| 668 | |
| 669 /** | |
| 670 * An [IndexStore] which keeps index information in separate nodes for each unit
. | 425 * An [IndexStore] which keeps index information in separate nodes for each unit
. |
| 671 */ | 426 */ |
| 672 class SplitIndexStore implements IndexStore { | 427 class SplitIndexStore implements IndexStore { |
| 673 /** | 428 /** |
| 674 * The [ContextCodec] to encode/decode [AnalysisContext]s. | 429 * The [ContextCodec] to encode/decode [AnalysisContext]s. |
| 675 */ | 430 */ |
| 676 ContextCodec _contextCodec; | 431 ContextCodec _contextCodec; |
| 677 | 432 |
| 678 /** | 433 /** |
| 679 * Information about "universe" elements. | 434 * Information about "universe" elements. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 707 | 462 |
| 708 /** | 463 /** |
| 709 * The [ElementCodec] to encode/decode [Element]s. | 464 * The [ElementCodec] to encode/decode [Element]s. |
| 710 */ | 465 */ |
| 711 ElementCodec _elementCodec; | 466 ElementCodec _elementCodec; |
| 712 | 467 |
| 713 /** | 468 /** |
| 714 * A table mapping element names to the node names that may have relations wit
h elements with | 469 * A table mapping element names to the node names that may have relations wit
h elements with |
| 715 * these names. | 470 * these names. |
| 716 */ | 471 */ |
| 717 IntToIntSetMap _nameToNodeNames = new IntToIntSetMap(10000, 0.75); | 472 IntToIntSetMap _nameToNodeNames = new IntToIntSetMap(); |
| 718 | 473 |
| 719 /** | 474 /** |
| 720 * The [NodeManager] to get/put [IndexNode]s. | 475 * The [NodeManager] to get/put [IndexNode]s. |
| 721 */ | 476 */ |
| 722 final NodeManager _nodeManager; | 477 final NodeManager _nodeManager; |
| 723 | 478 |
| 724 /** | 479 /** |
| 725 * The set of known [Source]s. | 480 * The set of known [Source]s. |
| 726 */ | 481 */ |
| 727 Set<Source> _sources = new HashSet<Source>(); | 482 Set<Source> _sources = new HashSet<Source>(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 libraryElement.definingCompilationUnit; | 516 libraryElement.definingCompilationUnit; |
| 762 if (definingUnitElement == null) { | 517 if (definingUnitElement == null) { |
| 763 return false; | 518 return false; |
| 764 } | 519 } |
| 765 // prepare sources | 520 // prepare sources |
| 766 Source library = definingUnitElement.source; | 521 Source library = definingUnitElement.source; |
| 767 Source unit = unitElement.source; | 522 Source unit = unitElement.source; |
| 768 // special handling for the defining library unit | 523 // special handling for the defining library unit |
| 769 if (unit == library) { | 524 if (unit == library) { |
| 770 // prepare new parts | 525 // prepare new parts |
| 771 Set<Source> newParts = new Set(); | 526 HashSet<Source> newParts = new HashSet<Source>(); |
| 772 for (CompilationUnitElement part in libraryElement.parts) { | 527 for (CompilationUnitElement part in libraryElement.parts) { |
| 773 newParts.add(part.source); | 528 newParts.add(part.source); |
| 774 } | 529 } |
| 775 // prepare old parts | 530 // prepare old parts |
| 776 Map<Source, Set<Source>> libraryToUnits = | 531 Map<Source, Set<Source>> libraryToUnits = |
| 777 _contextToLibraryToUnits[context]; | 532 _contextToLibraryToUnits[context]; |
| 778 if (libraryToUnits == null) { | 533 if (libraryToUnits == null) { |
| 779 libraryToUnits = {}; | 534 libraryToUnits = new HashMap<Source, Set<Source>>(); |
| 780 _contextToLibraryToUnits[context] = libraryToUnits; | 535 _contextToLibraryToUnits[context] = libraryToUnits; |
| 781 } | 536 } |
| 782 Set<Source> oldParts = libraryToUnits[library]; | 537 Set<Source> oldParts = libraryToUnits[library]; |
| 783 // check if some parts are not in the library now | 538 // check if some parts are not in the library now |
| 784 if (oldParts != null) { | 539 if (oldParts != null) { |
| 785 Set<Source> noParts = oldParts.difference(newParts); | 540 Set<Source> noParts = oldParts.difference(newParts); |
| 786 for (Source noPart in noParts) { | 541 for (Source noPart in noParts) { |
| 787 _removeLocations(context, library, noPart); | 542 _removeLocations(context, library, noPart); |
| 788 } | 543 } |
| 789 } | 544 } |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 if (container == null || container.contains(source)) { | 732 if (container == null || container.contains(source)) { |
| 978 removeSource(context, source); | 733 removeSource(context, source); |
| 979 } | 734 } |
| 980 } | 735 } |
| 981 } | 736 } |
| 982 } | 737 } |
| 983 | 738 |
| 984 String _getElementName(Element element) => element.name; | 739 String _getElementName(Element element) => element.name; |
| 985 | 740 |
| 986 List<Location> _getRelationshipsUniverse(Relationship relationship) { | 741 List<Location> _getRelationshipsUniverse(Relationship relationship) { |
| 987 List<Location> locations = []; | 742 List<Location> locations = <Location>[]; |
| 988 _contextNodeRelations.forEach((contextId, contextRelations) { | 743 _contextNodeRelations.forEach((contextId, contextRelations) { |
| 989 AnalysisContext context = _contextCodec.decode(contextId); | 744 AnalysisContext context = _contextCodec.decode(contextId); |
| 990 if (context != null) { | 745 if (context != null) { |
| 991 for (Map<Relationship, List<LocationData>> nodeRelations in | 746 for (Map<Relationship, List<LocationData>> nodeRelations in |
| 992 contextRelations.values) { | 747 contextRelations.values) { |
| 993 List<LocationData> nodeLocations = nodeRelations[relationship]; | 748 List<LocationData> nodeLocations = nodeRelations[relationship]; |
| 994 if (nodeLocations != null) { | 749 if (nodeLocations != null) { |
| 995 for (LocationData locationData in nodeLocations) { | 750 for (LocationData locationData in nodeLocations) { |
| 996 Location location = locationData.getLocation(context, | 751 Location location = locationData.getLocation(context, |
| 997 _elementCodec); | 752 _elementCodec); |
| 998 if (location != null) { | 753 if (location != null) { |
| 999 locations.add(location); | 754 locations.add(location); |
| 1000 } | 755 } |
| 1001 } | 756 } |
| 1002 } | 757 } |
| 1003 } | 758 } |
| 1004 } | 759 } |
| 1005 }); | 760 }); |
| 1006 return locations; | 761 return locations; |
| 1007 } | 762 } |
| 1008 | 763 |
| 1009 void _recordLibraryWithUnit(AnalysisContext context, Source library, | 764 void _recordLibraryWithUnit(AnalysisContext context, Source library, |
| 1010 Source unit) { | 765 Source unit) { |
| 1011 Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context]; | 766 Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context]; |
| 1012 if (libraryToUnits == null) { | 767 if (libraryToUnits == null) { |
| 1013 libraryToUnits = {}; | 768 libraryToUnits = new HashMap<Source, Set<Source>>(); |
| 1014 _contextToLibraryToUnits[context] = libraryToUnits; | 769 _contextToLibraryToUnits[context] = libraryToUnits; |
| 1015 } | 770 } |
| 1016 Set<Source> units = libraryToUnits[library]; | 771 Set<Source> units = libraryToUnits[library]; |
| 1017 if (units == null) { | 772 if (units == null) { |
| 1018 units = new Set(); | 773 units = new HashSet<Source>(); |
| 1019 libraryToUnits[library] = units; | 774 libraryToUnits[library] = units; |
| 1020 } | 775 } |
| 1021 units.add(unit); | 776 units.add(unit); |
| 1022 } | 777 } |
| 1023 | 778 |
| 1024 void _recordNodeNameForElement(Element element) { | 779 void _recordNodeNameForElement(Element element) { |
| 1025 String name = _getElementName(element); | 780 String name = _getElementName(element); |
| 1026 int nameId = _stringCodec.encode(name); | 781 int nameId = _stringCodec.encode(name); |
| 1027 _nameToNodeNames.add(nameId, _currentNodeNameId); | 782 _nameToNodeNames.add(nameId, _currentNodeNameId); |
| 1028 } | 783 } |
| 1029 | 784 |
| 1030 void _recordRelationshipUniverse(Relationship relationship, | 785 void _recordRelationshipUniverse(Relationship relationship, |
| 1031 Location location) { | 786 Location location) { |
| 1032 // in current context | 787 // in current context |
| 1033 Map<int, Map<Relationship, List<LocationData>>> nodeRelations = | 788 Map<int, Map<Relationship, List<LocationData>>> nodeRelations = |
| 1034 _contextNodeRelations[_currentContextId]; | 789 _contextNodeRelations[_currentContextId]; |
| 1035 if (nodeRelations == null) { | 790 if (nodeRelations == null) { |
| 1036 nodeRelations = {}; | 791 nodeRelations = new HashMap<int, Map<Relationship, List<LocationData>>>(); |
| 1037 _contextNodeRelations[_currentContextId] = nodeRelations; | 792 _contextNodeRelations[_currentContextId] = nodeRelations; |
| 1038 } | 793 } |
| 1039 // in current node | 794 // in current node |
| 1040 Map<Relationship, List<LocationData>> relations = | 795 Map<Relationship, List<LocationData>> relations = |
| 1041 nodeRelations[_currentNodeNameId]; | 796 nodeRelations[_currentNodeNameId]; |
| 1042 if (relations == null) { | 797 if (relations == null) { |
| 1043 relations = {}; | 798 relations = new HashMap<Relationship, List<LocationData>>(); |
| 1044 nodeRelations[_currentNodeNameId] = relations; | 799 nodeRelations[_currentNodeNameId] = relations; |
| 1045 } | 800 } |
| 1046 // for the given relationship | 801 // for the given relationship |
| 1047 List<LocationData> locations = relations[relationship]; | 802 List<LocationData> locations = relations[relationship]; |
| 1048 if (locations == null) { | 803 if (locations == null) { |
| 1049 locations = []; | 804 locations = <LocationData>[]; |
| 1050 relations[relationship] = locations; | 805 relations[relationship] = locations; |
| 1051 } | 806 } |
| 1052 // record LocationData | 807 // record LocationData |
| 1053 locations.add(new LocationData.forObject(_elementCodec, location)); | 808 locations.add(new LocationData.forObject(_elementCodec, location)); |
| 1054 } | 809 } |
| 1055 | 810 |
| 1056 void _recordUnitInLibrary(AnalysisContext context, Source library, | 811 void _recordUnitInLibrary(AnalysisContext context, Source library, |
| 1057 Source unit) { | 812 Source unit) { |
| 1058 Map<Source, Set<Source>> unitToLibraries = | 813 Map<Source, Set<Source>> unitToLibraries = |
| 1059 _contextToUnitToLibraries[context]; | 814 _contextToUnitToLibraries[context]; |
| 1060 if (unitToLibraries == null) { | 815 if (unitToLibraries == null) { |
| 1061 unitToLibraries = {}; | 816 unitToLibraries = new HashMap<Source, Set<Source>>(); |
| 1062 _contextToUnitToLibraries[context] = unitToLibraries; | 817 _contextToUnitToLibraries[context] = unitToLibraries; |
| 1063 } | 818 } |
| 1064 Set<Source> libraries = unitToLibraries[unit]; | 819 Set<Source> libraries = unitToLibraries[unit]; |
| 1065 if (libraries == null) { | 820 if (libraries == null) { |
| 1066 libraries = new Set(); | 821 libraries = new HashSet<Source>(); |
| 1067 unitToLibraries[unit] = libraries; | 822 unitToLibraries[unit] = libraries; |
| 1068 } | 823 } |
| 1069 libraries.add(library); | 824 libraries.add(library); |
| 1070 } | 825 } |
| 1071 | 826 |
| 1072 /** | 827 /** |
| 1073 * Removes locations recorded in the given library/unit pair. | 828 * Removes locations recorded in the given library/unit pair. |
| 1074 */ | 829 */ |
| 1075 void _removeLocations(AnalysisContext context, Source library, Source unit) { | 830 void _removeLocations(AnalysisContext context, Source library, Source unit) { |
| 1076 // remove node | 831 // remove node |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1093 */ | 848 */ |
| 1094 AnalysisContext _unwrapContext(AnalysisContext context) { | 849 AnalysisContext _unwrapContext(AnalysisContext context) { |
| 1095 if (context is InstrumentedAnalysisContextImpl) { | 850 if (context is InstrumentedAnalysisContextImpl) { |
| 1096 context = (context as InstrumentedAnalysisContextImpl).basis; | 851 context = (context as InstrumentedAnalysisContextImpl).basis; |
| 1097 } | 852 } |
| 1098 return context; | 853 return context; |
| 1099 } | 854 } |
| 1100 } | 855 } |
| 1101 | 856 |
| 1102 | 857 |
| 1103 /** | |
| 1104 * A helper that encodes/decodes [String]s from/to integers. | |
| 1105 */ | |
| 1106 class StringCodec { | |
| 1107 /** | |
| 1108 * A table mapping names to their unique indices. | |
| 1109 */ | |
| 1110 final Map<String, int> nameToIndex = {}; | |
| 1111 | |
| 1112 /** | |
| 1113 * A table mapping indices to the corresponding strings. | |
| 1114 */ | |
| 1115 List<String> _indexToName = []; | |
| 1116 | |
| 1117 /** | |
| 1118 * Returns the [String] that corresponds to the given index. | |
| 1119 */ | |
| 1120 String decode(int index) => _indexToName[index]; | |
| 1121 | |
| 1122 /** | |
| 1123 * Returns an unique index for the given [String]. | |
| 1124 */ | |
| 1125 int encode(String name) { | |
| 1126 int index = nameToIndex[name]; | |
| 1127 if (index == null) { | |
| 1128 index = _indexToName.length; | |
| 1129 nameToIndex[name] = index; | |
| 1130 _indexToName.add(name); | |
| 1131 } | |
| 1132 return index; | |
| 1133 } | |
| 1134 } | |
| 1135 | |
| 1136 | |
| 1137 class _DataInputStream { | 858 class _DataInputStream { |
| 1138 ByteData _byteData; | 859 ByteData _byteData; |
| 1139 int _byteOffset = 0; | 860 int _byteOffset = 0; |
| 1140 | 861 |
| 1141 _DataInputStream(List<int> bytes) { | 862 _DataInputStream(List<int> bytes) { |
| 1142 ByteBuffer buffer = new Uint8List.fromList(bytes).buffer; | 863 ByteBuffer buffer = new Uint8List.fromList(bytes).buffer; |
| 1143 _byteData = new ByteData.view(buffer); | 864 _byteData = new ByteData.view(buffer); |
| 1144 } | 865 } |
| 1145 | 866 |
| 1146 int readInt() { | 867 int readInt() { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1158 return new Uint8List.fromList(_buffer.takeBytes()); | 879 return new Uint8List.fromList(_buffer.takeBytes()); |
| 1159 } | 880 } |
| 1160 | 881 |
| 1161 void writeInt(int value) { | 882 void writeInt(int value) { |
| 1162 _buffer.addByte((value & 0xFF000000) >> 24); | 883 _buffer.addByte((value & 0xFF000000) >> 24); |
| 1163 _buffer.addByte((value & 0x00FF0000) >> 16); | 884 _buffer.addByte((value & 0x00FF0000) >> 16); |
| 1164 _buffer.addByte((value & 0x0000FF00) >> 8); | 885 _buffer.addByte((value & 0x0000FF00) >> 8); |
| 1165 _buffer.addByte(value & 0xFF); | 886 _buffer.addByte(value & 0xFF); |
| 1166 } | 887 } |
| 1167 } | 888 } |
| OLD | NEW |