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