| 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 services.src.index.store.codec; | 5 library services.src.index.store.codec; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/services/index/index.dart'; | 9 import 'package:analysis_server/src/services/index/index.dart'; |
| 10 import 'package:analysis_server/src/services/index/store/collection.dart'; | 10 import 'package:analysis_server/src/services/index/store/collection.dart'; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 _indexToContext.remove(id); | 61 _indexToContext.remove(id); |
| 62 } | 62 } |
| 63 } | 63 } |
| 64 } | 64 } |
| 65 | 65 |
| 66 | 66 |
| 67 /** | 67 /** |
| 68 * A helper that encodes/decodes [Element]s to/from integers. | 68 * A helper that encodes/decodes [Element]s to/from integers. |
| 69 */ | 69 */ |
| 70 class ElementCodec { | 70 class ElementCodec { |
| 71 static const KIND_DART = 0; | |
| 72 static const KIND_NAME = 1; | |
| 73 static const KIND_UNKNOWN = 2; | |
| 74 | |
| 75 final StringCodec _stringCodec; | 71 final StringCodec _stringCodec; |
| 76 final ElementKindCodec _kindCodec = new ElementKindCodec(); | |
| 77 | 72 |
| 78 /** | 73 /** |
| 79 * A table mapping element encodings to a single integer. | 74 * A table mapping element encodings to a single integer. |
| 80 */ | 75 */ |
| 81 final IntArrayToIntMap _pathToIndex = new IntArrayToIntMap(); | 76 final IntArrayToIntMap _pathToIndex = new IntArrayToIntMap(); |
| 82 | 77 |
| 83 /** | 78 /** |
| 84 * A list that works as a mapping of integers to element encodings. | 79 * A list that works as a mapping of integers to element encodings. |
| 85 */ | 80 */ |
| 86 final List<List<int>> _indexToPath = <List<int>>[]; | 81 final List<List<int>> _indexToPath = <List<int>>[]; |
| 87 | 82 |
| 88 ElementCodec(this._stringCodec); | 83 ElementCodec(this._stringCodec); |
| 89 | 84 |
| 90 /** | 85 /** |
| 91 * Returns an [Element] that corresponds to the given location. | 86 * Returns an [Element] that corresponds to the given location. |
| 92 * | 87 * |
| 93 * @param context the [AnalysisContext] to find [Element] in | 88 * @param context the [AnalysisContext] to find [Element] in |
| 94 * @param index an integer corresponding to the [Element] | 89 * @param index an integer corresponding to the [Element] |
| 95 * @return the [Element] or `null` | 90 * @return the [Element] or `null` |
| 96 */ | 91 */ |
| 97 Element decode(AnalysisContext context, int index) { | 92 Element decode(AnalysisContext context, int index) { |
| 98 List<int> path = _indexToPath[index]; | 93 List<int> path = _indexToPath[index]; |
| 99 int encodingKind = path[0]; | 94 List<String> components = _getLocationComponents(path); |
| 100 // DART | 95 ElementLocation location = new ElementLocationImpl.con3(components); |
| 101 if (encodingKind == KIND_DART) { | 96 Element element = context.getElement(location); |
| 102 String librarySourceEncoding = _stringCodec.decode(path[1]); | 97 return element; |
| 103 String unitSourceEncoding = _stringCodec.decode(path[2]); | |
| 104 int nameOffset = path[3]; | |
| 105 ElementKind kind = _kindCodec.decode(path[4]); | |
| 106 ElementLocation location = new DartElementLocation( | |
| 107 librarySourceEncoding, | |
| 108 unitSourceEncoding, | |
| 109 nameOffset, | |
| 110 kind); | |
| 111 return context.getElement(location); | |
| 112 } | |
| 113 // NAME - never used as a location, so we are never asked to decode it | |
| 114 // TODO(scheglov) support for KIND_HTML ? | |
| 115 return null; | |
| 116 } | 98 } |
| 117 | 99 |
| 118 /** | 100 /** |
| 119 * Returns a unique integer that corresponds to the given [Element]. | 101 * Returns a unique integer that corresponds to the given [Element]. |
| 120 * | 102 * |
| 121 * If [forKey] is `true` then [element] is a part of a key, so it should use | 103 * If [forKey] is `true` then [element] is a part of a key, so it should use |
| 122 * file paths instead of [Element] location URIs. | 104 * file paths instead of [Element] location URIs. |
| 123 */ | 105 */ |
| 124 int encode(Element element, bool forKey) { | 106 int encode(Element element, bool forKey) { |
| 125 List<int> path = _getLocationPath(element, forKey); | 107 List<int> path = _getLocationPath(element, forKey); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 139 List<int> path = _getLocationPathLimited(element); | 121 List<int> path = _getLocationPathLimited(element); |
| 140 int index = _pathToIndex[path]; | 122 int index = _pathToIndex[path]; |
| 141 if (index == null) { | 123 if (index == null) { |
| 142 index = _indexToPath.length; | 124 index = _indexToPath.length; |
| 143 _pathToIndex[path] = index; | 125 _pathToIndex[path] = index; |
| 144 _indexToPath.add(path); | 126 _indexToPath.add(path); |
| 145 } | 127 } |
| 146 return index; | 128 return index; |
| 147 } | 129 } |
| 148 | 130 |
| 131 List<String> _getLocationComponents(List<int> path) { |
| 132 int length = path.length; |
| 133 List<String> components = new List<String>(); |
| 134 for (int i = 0; i < length; i++) { |
| 135 int componentId = path[i]; |
| 136 String component = _stringCodec.decode(componentId); |
| 137 if (i < length - 1 && path[i + 1] < 0) { |
| 138 component += '@${(-path[i + 1])}'; |
| 139 i++; |
| 140 } |
| 141 components.add(component); |
| 142 } |
| 143 return components; |
| 144 } |
| 145 |
| 149 /** | 146 /** |
| 150 * If [usePath] is `true` then [Source] path should be used instead of URI. | 147 * If [usePath] is `true` then [Source] path should be used instead of URI. |
| 151 */ | 148 */ |
| 152 List<int> _getLocationPath(Element element, bool usePath) { | 149 List<int> _getLocationPath(Element element, bool usePath) { |
| 153 LibraryElement library = element.library; | 150 // prepare the location components |
| 154 // DynamicElement, NameElement | 151 List<String> components = element.location.components; |
| 155 if (library == null) { | 152 if (usePath) { |
| 156 int nameId = _stringCodec.encode(element.name); | 153 LibraryElement library = element.library; |
| 157 return <int>[KIND_NAME, nameId]; | 154 if (library != null) { |
| 155 components[0] = library.source.fullName; |
| 156 if (element.enclosingElement is CompilationUnitElement) { |
| 157 components[1] = library.definingCompilationUnit.source.fullName; |
| 158 } |
| 159 } |
| 158 } | 160 } |
| 159 // normal Element | 161 // encode the location |
| 160 ElementLocation location = element.location; | 162 int length = components.length; |
| 161 if (location is DartElementLocation) { | 163 if (_hasLocalOffset(components)) { |
| 162 String librarySourceEncoding; | 164 List<int> path = new List<int>(); |
| 163 String unitSourceEncoding; | 165 for (String component in components) { |
| 164 if (usePath) { | 166 int atOffset = component.indexOf('@'); |
| 165 unitSourceEncoding = library.source.fullName; | 167 if (atOffset == -1) { |
| 166 unitSourceEncoding = element.source.fullName; | 168 path.add(_stringCodec.encode(component)); |
| 167 } else { | 169 } else { |
| 168 librarySourceEncoding = location.librarySourceEncoding; | 170 String preAtString = component.substring(0, atOffset); |
| 169 unitSourceEncoding = location.unitSourceEncoding; | 171 String atString = component.substring(atOffset + 1); |
| 172 path.add(_stringCodec.encode(preAtString)); |
| 173 path.add(-1 * int.parse(atString)); |
| 174 } |
| 170 } | 175 } |
| 171 int libraryId = _stringCodec.encode(librarySourceEncoding); | 176 return path; |
| 172 int unitId = _stringCodec.encode(unitSourceEncoding); | 177 } else { |
| 173 // done | 178 List<int> path = new List<int>.filled(length, 0); |
| 174 int nameOffset = location.nameOffset; | 179 for (int i = 0; i < length; i++) { |
| 175 int kindId = _kindCodec.encode(location.kind); | 180 String component = components[i]; |
| 176 return <int>[KIND_DART, libraryId, unitId, nameOffset, kindId]; | 181 path[i] = _stringCodec.encode(component); |
| 182 } |
| 183 return path; |
| 177 } | 184 } |
| 178 // unknown | |
| 179 return <int>[KIND_UNKNOWN]; | |
| 180 } | 185 } |
| 181 | 186 |
| 182 /** | 187 /** |
| 183 * Returns an approximation of the [element]'s location. | 188 * Returns an approximation of the [element]'s location. |
| 184 */ | 189 */ |
| 185 List<int> _getLocationPathLimited(Element element) { | 190 List<int> _getLocationPathLimited(Element element) { |
| 186 String firstComponent; | 191 String firstComponent; |
| 187 { | 192 { |
| 188 LibraryElement libraryElement = element.library; | 193 LibraryElement libraryElement = element.library; |
| 189 if (libraryElement != null) { | 194 if (libraryElement != null) { |
| 190 firstComponent = libraryElement.source.fullName; | 195 firstComponent = libraryElement.source.fullName; |
| 191 } else { | 196 } else { |
| 192 firstComponent = 'null'; | 197 firstComponent = 'null'; |
| 193 } | 198 } |
| 194 } | 199 } |
| 195 String lastComponent = element.displayName; | 200 String lastComponent = element.displayName; |
| 196 int firstId = _stringCodec.encode(firstComponent); | 201 int firstId = _stringCodec.encode(firstComponent); |
| 197 int lastId = _stringCodec.encode(lastComponent); | 202 int lastId = _stringCodec.encode(lastComponent); |
| 198 return <int>[firstId, lastId]; | 203 return <int>[firstId, lastId]; |
| 199 } | 204 } |
| 200 } | |
| 201 | 205 |
| 202 | 206 static bool _hasLocalOffset(List<String> components) { |
| 203 /** | 207 for (String component in components) { |
| 204 * A helper that encodes/decodes [ElementKind]s to/from integers. | 208 if (component.indexOf('@') != -1) { |
| 205 */ | 209 return true; |
| 206 class ElementKindCodec { | |
| 207 ElementKind decode(int id) { | |
| 208 for (ElementKind kind in ElementKind.values) { | |
| 209 if (kind.ordinal == id) { | |
| 210 return kind; | |
| 211 } | 210 } |
| 212 } | 211 } |
| 213 return null; | 212 return false; |
| 214 } | |
| 215 | |
| 216 int encode(ElementKind kind) { | |
| 217 return kind.ordinal; | |
| 218 } | 213 } |
| 219 } | 214 } |
| 220 | 215 |
| 221 | 216 |
| 222 /** | 217 /** |
| 223 * A helper that encodes/decodes [Relationship]s to/from integers. | 218 * A helper that encodes/decodes [Relationship]s to/from integers. |
| 224 */ | 219 */ |
| 225 class RelationshipCodec { | 220 class RelationshipCodec { |
| 226 final StringCodec _stringCodec; | 221 final StringCodec _stringCodec; |
| 227 | 222 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 int encode(String name) { | 259 int encode(String name) { |
| 265 int index = nameToIndex[name]; | 260 int index = nameToIndex[name]; |
| 266 if (index == null) { | 261 if (index == null) { |
| 267 index = _indexToName.length; | 262 index = _indexToName.length; |
| 268 nameToIndex[name] = index; | 263 nameToIndex[name] = index; |
| 269 _indexToName.add(name); | 264 _indexToName.add(name); |
| 270 } | 265 } |
| 271 return index; | 266 return index; |
| 272 } | 267 } |
| 273 } | 268 } |
| OLD | NEW |