| 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'; |
| 11 import 'package:analyzer/src/generated/element.dart'; | 11 import 'package:analyzer/src/generated/element.dart'; |
| 12 import 'package:analyzer/src/generated/engine.dart'; | 12 import 'package:analyzer/src/generated/engine.dart'; |
| 13 import 'package:analyzer/src/generated/source.dart'; |
| 13 | 14 |
| 14 | 15 |
| 15 /** | 16 /** |
| 16 * A helper that encodes/decodes [AnalysisContext]s from/to integers. | 17 * A helper that encodes/decodes [AnalysisContext]s from/to integers. |
| 17 */ | 18 */ |
| 18 class ContextCodec { | 19 class ContextCodec { |
| 19 /** | 20 /** |
| 20 * A table mapping contexts to their unique indices. | 21 * A table mapping contexts to their unique indices. |
| 21 */ | 22 */ |
| 22 Map<AnalysisContext, int> _contextToIndex = | 23 Map<AnalysisContext, int> _contextToIndex = |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 Element decode(AnalysisContext context, int index) { | 92 Element decode(AnalysisContext context, int index) { |
| 92 List<int> path = _indexToPath[index]; | 93 List<int> path = _indexToPath[index]; |
| 93 List<String> components = _getLocationComponents(path); | 94 List<String> components = _getLocationComponents(path); |
| 94 ElementLocation location = new ElementLocationImpl.con3(components); | 95 ElementLocation location = new ElementLocationImpl.con3(components); |
| 95 Element element = context.getElement(location); | 96 Element element = context.getElement(location); |
| 96 return element; | 97 return element; |
| 97 } | 98 } |
| 98 | 99 |
| 99 /** | 100 /** |
| 100 * Returns a unique integer that corresponds to the given [Element]. | 101 * Returns a unique integer that corresponds to the given [Element]. |
| 102 * |
| 103 * If [forKey] is `true` then [element] is a part of a key, so it should use |
| 104 * file paths instead of [Element] location URIs. |
| 101 */ | 105 */ |
| 102 int encode(Element element) { | 106 int encode(Element element, bool forKey) { |
| 103 List<int> path = _getLocationPath(element); | 107 List<int> path = _getLocationPath(element, forKey); |
| 104 int index = _pathToIndex[path]; | 108 int index = _pathToIndex[path]; |
| 105 if (index == null) { | 109 if (index == null) { |
| 106 index = _indexToPath.length; | 110 index = _indexToPath.length; |
| 107 _pathToIndex[path] = index; | 111 _pathToIndex[path] = index; |
| 108 _indexToPath.add(path); | 112 _indexToPath.add(path); |
| 109 } | 113 } |
| 110 return index; | 114 return index; |
| 111 } | 115 } |
| 112 | 116 |
| 113 /** | 117 /** |
| 114 * Returns an integer that corresponds to an approximated location of the give
n {@link Element}. | 118 * Returns an integer that corresponds to an approximated location of [element
]. |
| 115 */ | 119 */ |
| 116 int encodeHash(Element element) { | 120 int encodeHash(Element element) { |
| 117 List<int> path = _getLocationPathLimited(element); | 121 List<int> path = _getLocationPathLimited(element); |
| 118 int index = _pathToIndex[path]; | 122 int index = _pathToIndex[path]; |
| 119 if (index == null) { | 123 if (index == null) { |
| 120 index = _indexToPath.length; | 124 index = _indexToPath.length; |
| 121 _pathToIndex[path] = index; | 125 _pathToIndex[path] = index; |
| 122 _indexToPath.add(path); | 126 _indexToPath.add(path); |
| 123 } | 127 } |
| 124 return index; | 128 return index; |
| 125 } | 129 } |
| 126 | 130 |
| 127 List<String> _getLocationComponents(List<int> path) { | 131 List<String> _getLocationComponents(List<int> path) { |
| 128 int length = path.length; | 132 int length = path.length; |
| 129 List<String> components = new List<String>(); | 133 List<String> components = new List<String>(); |
| 130 for (int i = 0; i < length; i++) { | 134 for (int i = 0; i < length; i++) { |
| 131 int componentId = path[i]; | 135 int componentId = path[i]; |
| 132 String component = _stringCodec.decode(componentId); | 136 String component = _stringCodec.decode(componentId); |
| 133 if (i < length - 1 && path[i + 1] < 0) { | 137 if (i < length - 1 && path[i + 1] < 0) { |
| 134 component += '@${(-path[i + 1])}'; | 138 component += '@${(-path[i + 1])}'; |
| 135 i++; | 139 i++; |
| 136 } | 140 } |
| 137 components.add(component); | 141 components.add(component); |
| 138 } | 142 } |
| 139 return components; | 143 return components; |
| 140 } | 144 } |
| 141 | 145 |
| 142 List<int> _getLocationPath(Element element) { | 146 /** |
| 147 * If [usePath] is `true` then [Source] path should be used instead of URI. |
| 148 */ |
| 149 List<int> _getLocationPath(Element element, bool usePath) { |
| 150 // prepare the location components |
| 143 List<String> components = element.location.components; | 151 List<String> components = element.location.components; |
| 152 if (usePath) { |
| 153 LibraryElement library = element.library; |
| 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 } |
| 160 } |
| 161 // encode the location |
| 144 int length = components.length; | 162 int length = components.length; |
| 145 if (_hasLocalOffset(components)) { | 163 if (_hasLocalOffset(components)) { |
| 146 List<int> path = new List<int>(); | 164 List<int> path = new List<int>(); |
| 147 for (String component in components) { | 165 for (String component in components) { |
| 148 int atOffset = component.indexOf('@'); | 166 int atOffset = component.indexOf('@'); |
| 149 if (atOffset == -1) { | 167 if (atOffset == -1) { |
| 150 path.add(_stringCodec.encode(component)); | 168 path.add(_stringCodec.encode(component)); |
| 151 } else { | 169 } else { |
| 152 String preAtString = component.substring(0, atOffset); | 170 String preAtString = component.substring(0, atOffset); |
| 153 String atString = component.substring(atOffset + 1); | 171 String atString = component.substring(atOffset + 1); |
| 154 path.add(_stringCodec.encode(preAtString)); | 172 path.add(_stringCodec.encode(preAtString)); |
| 155 path.add(-1 * int.parse(atString)); | 173 path.add(-1 * int.parse(atString)); |
| 156 } | 174 } |
| 157 } | 175 } |
| 158 return path; | 176 return path; |
| 159 } else { | 177 } else { |
| 160 List<int> path = new List<int>.filled(length, 0); | 178 List<int> path = new List<int>.filled(length, 0); |
| 161 for (int i = 0; i < length; i++) { | 179 for (int i = 0; i < length; i++) { |
| 162 String component = components[i]; | 180 String component = components[i]; |
| 163 path[i] = _stringCodec.encode(component); | 181 path[i] = _stringCodec.encode(component); |
| 164 } | 182 } |
| 165 return path; | 183 return path; |
| 166 } | 184 } |
| 167 } | 185 } |
| 168 | 186 |
| 169 /** | 187 /** |
| 170 * Returns an approximation of the given {@link Element}'s location. | 188 * Returns an approximation of the [element]'s location. |
| 171 */ | 189 */ |
| 172 List<int> _getLocationPathLimited(Element element) { | 190 List<int> _getLocationPathLimited(Element element) { |
| 173 List<String> components = element.location.components; | 191 String firstComponent; |
| 174 int length = components.length; | 192 { |
| 175 String firstComponent = components[0]; | 193 LibraryElement libraryElement = element.library; |
| 176 String lastComponent = components[length - 1]; | 194 if (libraryElement != null) { |
| 177 lastComponent = _substringBeforeAt(lastComponent); | 195 firstComponent = libraryElement.source.fullName; |
| 196 } else { |
| 197 firstComponent = 'null'; |
| 198 } |
| 199 } |
| 200 String lastComponent = element.displayName; |
| 178 int firstId = _stringCodec.encode(firstComponent); | 201 int firstId = _stringCodec.encode(firstComponent); |
| 179 int lastId = _stringCodec.encode(lastComponent); | 202 int lastId = _stringCodec.encode(lastComponent); |
| 180 return <int>[firstId, lastId]; | 203 return <int>[firstId, lastId]; |
| 181 } | 204 } |
| 182 | 205 |
| 183 bool _hasLocalOffset(List<String> components) { | 206 static String _getComponentUnit(Element element) { |
| 207 LibraryElement libraryElement = element.library; |
| 208 if (libraryElement == null) { |
| 209 return 'null'; |
| 210 } |
| 211 return libraryElement.definingCompilationUnit.source.fullName; |
| 212 } |
| 213 |
| 214 static bool _hasLocalOffset(List<String> components) { |
| 184 for (String component in components) { | 215 for (String component in components) { |
| 185 if (component.indexOf('@') != -1) { | 216 if (component.indexOf('@') != -1) { |
| 186 return true; | 217 return true; |
| 187 } | 218 } |
| 188 } | 219 } |
| 189 return false; | 220 return false; |
| 190 } | 221 } |
| 191 | 222 |
| 192 String _substringBeforeAt(String str) { | 223 static String _substringBeforeAt(String str) { |
| 193 int atOffset = str.indexOf('@'); | 224 int atOffset = str.indexOf('@'); |
| 194 if (atOffset != -1) { | 225 if (atOffset != -1) { |
| 195 str = str.substring(0, atOffset); | 226 str = str.substring(0, atOffset); |
| 196 } | 227 } |
| 197 return str; | 228 return str; |
| 198 } | 229 } |
| 199 } | 230 } |
| 200 | 231 |
| 201 | 232 |
| 202 /** | 233 /** |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 int encode(String name) { | 275 int encode(String name) { |
| 245 int index = nameToIndex[name]; | 276 int index = nameToIndex[name]; |
| 246 if (index == null) { | 277 if (index == null) { |
| 247 index = _indexToName.length; | 278 index = _indexToName.length; |
| 248 nameToIndex[name] = index; | 279 nameToIndex[name] = index; |
| 249 _indexToName.add(name); | 280 _indexToName.add(name); |
| 250 } | 281 } |
| 251 return index; | 282 return index; |
| 252 } | 283 } |
| 253 } | 284 } |
| OLD | NEW |