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

Side by Side Diff: pkg/analysis_server/lib/src/services/index/store/codec.dart

Issue 1075773002: Use file/offset/kind triplet as elements id. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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
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';
11 import 'package:analyzer/src/generated/element.dart'; 10 import 'package:analyzer/src/generated/element.dart';
12 import 'package:analyzer/src/generated/engine.dart'; 11 import 'package:analyzer/src/generated/engine.dart';
13 import 'package:analyzer/src/generated/source.dart'; 12 import 'package:analyzer/src/generated/source.dart';
14 import 'package:analyzer/src/generated/utilities_general.dart'; 13 import 'package:analyzer/src/generated/utilities_general.dart';
15 14
16 /** 15 /**
17 * A helper that encodes/decodes [AnalysisContext]s from/to integers. 16 * A helper that encodes/decodes [AnalysisContext]s from/to integers.
18 */ 17 */
19 class ContextCodec { 18 class ContextCodec {
20 /** 19 /**
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 if (id != null) { 59 if (id != null) {
61 _indexToContext.remove(id); 60 _indexToContext.remove(id);
62 } 61 }
63 } 62 }
64 } 63 }
65 64
66 /** 65 /**
67 * A helper that encodes/decodes [Element]s to/from integers. 66 * A helper that encodes/decodes [Element]s to/from integers.
68 */ 67 */
69 class ElementCodec { 68 class ElementCodec {
69 static const int NAMED_FILE_ID = -1;
70 static const int NAMED_KIND_ID = -1;
71 static const int _CONSTRUCTOR_KIND_BASE = -100;
72
70 final StringCodec _stringCodec; 73 final StringCodec _stringCodec;
71 74
72 /**
73 * A table mapping element encodings to a single integer.
74 */
75 final IntArrayToIntMap _pathToIndex = new IntArrayToIntMap();
76
77 /**
78 * A list that works as a mapping of integers to element encodings.
79 */
80 final List<List<int>> _indexToPath = <List<int>>[];
81
82 ElementCodec(this._stringCodec); 75 ElementCodec(this._stringCodec);
83 76
84 /** 77 /**
85 * Returns an [Element] that corresponds to the given location. 78 * Returns an [Element] that corresponds to the given identifiers.
86 *
87 * @param context the [AnalysisContext] to find [Element] in
88 * @param index an integer corresponding to the [Element]
89 * @return the [Element] or `null`
90 */ 79 */
91 Element decode(AnalysisContext context, int index) { 80 Element decode(AnalysisContext context, int fileId, int offset, int kindId) {
92 List<int> path = _indexToPath[index]; 81 String filePath = _stringCodec.decode(fileId);
93 List<String> components = _getLocationComponents(path); 82 List<Source> unitSources = context.getSourcesWithFullName(filePath);
94 ElementLocation location = new ElementLocationImpl.con3(components); 83 for (Source unitSource in unitSources) {
95 return context.getElement(location); 84 List<Source> libSources = context.getLibrariesContaining(unitSource);
85 for (Source libSource in libSources) {
86 LibraryElement libraryElement = context.getLibraryElement(libSource);
Brian Wilkerson 2015/04/09 14:06:25 We need to handle the case where 'getLibraryElemen
scheglov 2015/04/09 15:11:57 Done.
87 if (kindId == ElementKind.LIBRARY.ordinal) {
88 return libraryElement;
89 } else if (kindId == ElementKind.COMPILATION_UNIT.ordinal) {
90 for (CompilationUnitElement unit in libraryElement.units) {
91 if (unit.source.fullName == filePath) {
92 return unit;
93 }
94 }
95 return null;
96 } else {
97 Element element = libraryElement.getElementAt(offset);
98 if (element == null) {
99 return null;
100 }
101 if (element is ClassElement && kindId <= _CONSTRUCTOR_KIND_BASE) {
102 int constructorIndex = -1 * (kindId - _CONSTRUCTOR_KIND_BASE);
103 return element.constructors[constructorIndex];
104 }
105 if (element is PropertyInducingElement) {
106 if (kindId == ElementKind.GETTER.ordinal) {
107 return element.getter;
108 }
109 if (kindId == ElementKind.SETTER.ordinal) {
110 return element.setter;
111 }
112 }
113 return element;
114 }
115 }
116 }
117 return null;
96 } 118 }
97 119
98 /** 120 /**
99 * Returns a unique integer that corresponds to the given [Element]. 121 * Returns the 1-st component of the [element] id.
Brian Wilkerson 2015/04/09 14:06:25 "1-st" --> "first"
scheglov 2015/04/09 15:11:57 Done.
100 *
101 * If [forKey] is `true` then [element] is a part of a key, so it should use
102 * file paths instead of [Element] location URIs.
103 */ 122 */
104 int encode(Element element, bool forKey) { 123 int encode1(Element element) {
Brian Wilkerson 2015/04/09 14:06:25 Perhaps more meaningful names, such as "encodeFile
scheglov 2015/04/09 15:11:57 The names are intentionally opaque. Also it's basi
Brian Wilkerson 2015/04/09 15:26:30 I didn't suggest it for clients, I suggested it fo
scheglov 2015/04/09 15:51:08 I will add comments for these methods.
105 if (element is NameElement) { 124 Source source = element.source;
106 String name = element.name; 125 if (source == null) {
107 int nameId = _stringCodec.encode(name); 126 return NAMED_FILE_ID;
108 return _encodePath(<int>[nameId]);
109 } 127 }
110 // check the location has a cached id 128 String filePath = source.fullName;
111 ElementLocationImpl location = element.location; 129 return _stringCodec.encode(filePath);
112 if (!identical(location.indexOwner, this)) {
113 location.indexKeyId = null;
114 location.indexLocationId = null;
115 }
116 if (forKey) {
117 int id = location.indexKeyId;
118 if (id != null) {
119 return id;
120 }
121 } else {
122 int id = location.indexLocationId;
123 if (id != null) {
124 return id;
125 }
126 }
127 // prepare an id
128 List<int> path = _getLocationPath(element, location, forKey);
129 int index = _encodePath(path);
130 // put the id into the location
131 if (forKey) {
132 location.indexOwner = this;
133 location.indexKeyId = index;
134 } else {
135 location.indexOwner = this;
136 location.indexLocationId = index;
137 }
138 // done
139 return index;
140 } 130 }
141 131
142 /** 132 /**
133 * Returns the 2-nd component of the [element] id.
Brian Wilkerson 2015/04/09 14:06:25 "2-nd" --> "second"
scheglov 2015/04/09 15:11:57 Done.
134 */
135 int encode2(Element element) {
136 if (element is NameElement) {
137 String name = element.name;
138 return _stringCodec.encode(name);
139 }
140 if (element is ConstructorElement) {
141 return element.enclosingElement.nameOffset;
142 }
143 return element.nameOffset;
144 }
145
146 /**
147 * Returns the 3-rd component of the [element] id.
Brian Wilkerson 2015/04/09 14:06:25 "3-rd" --> "third"
scheglov 2015/04/09 15:11:57 Done.
148 */
149 int encode3(Element element) {
150 if (element is NameElement) {
151 return NAMED_KIND_ID;
152 }
153 if (element is ConstructorElement) {
154 ClassElement classElement = element.enclosingElement;
155 int constructorIndex = classElement.constructors.indexOf(element);
156 return _CONSTRUCTOR_KIND_BASE - constructorIndex;
157 }
158 return element.kind.ordinal;
159 }
160
161 /**
143 * Returns an integer that corresponds to the name of [element]. 162 * Returns an integer that corresponds to the name of [element].
144 */ 163 */
145 int encodeHash(Element element) { 164 int encodeHash(Element element) {
146 String elementName = element.displayName; 165 String elementName = element.displayName;
147 int elementNameId = _stringCodec.encode(elementName); 166 int elementNameId = _stringCodec.encode(elementName);
148 LibraryElement libraryElement = element.library; 167 LibraryElement libraryElement = element.library;
149 if (libraryElement != null) { 168 if (libraryElement != null) {
150 String libraryPath = libraryElement.source.fullName; 169 String libraryPath = libraryElement.source.fullName;
151 int libraryPathId = _stringCodec.encode(libraryPath); 170 int libraryPathId = _stringCodec.encode(libraryPath);
152 return JenkinsSmiHash.combine(libraryPathId, elementNameId); 171 return JenkinsSmiHash.combine(libraryPathId, elementNameId);
153 } else { 172 } else {
154 return elementNameId; 173 return elementNameId;
155 } 174 }
156 } 175 }
157
158 /**
159 * Returns a list with the location components of the element with the
160 * given encoded ID.
161 */
162 List<String> inspect_decodePath(int id) {
163 List<int> path = _indexToPath[id];
164 return _getLocationComponents(path);
165 }
166
167 /**
168 * Returns a map of element IDs to their locations for elements with
169 * the [requiredName].
170 */
171 Map<int, List<String>> inspect_getElements(String requiredName) {
172 Map<int, List<String>> result = <int, List<String>>{};
173 for (int i = 0; i < _indexToPath.length; i++) {
174 List<int> path = _indexToPath[i];
175 int nameIndex = path[path.length - 1];
176 if (nameIndex >= 0) {
177 String name = _stringCodec.decode(nameIndex);
178 if (name == requiredName) {
179 result[i] = path.map(_stringCodec.decode).toList();
180 }
181 }
182 }
183 return result;
184 }
185
186 int _encodePath(List<int> path) {
187 int index = _pathToIndex[path];
188 if (index == null) {
189 index = _indexToPath.length;
190 _pathToIndex[path] = index;
191 _indexToPath.add(path);
192 }
193 return index;
194 }
195
196 List<String> _getLocationComponents(List<int> path) {
197 int length = path.length;
198 List<String> components = new List<String>();
199 for (int i = 0; i < length; i++) {
200 int componentId = path[i];
201 String component = _stringCodec.decode(componentId);
202 if (i < length - 1 && path[i + 1] < 0) {
203 component += '@${(-path[i + 1])}';
204 i++;
205 }
206 components.add(component);
207 }
208 return components;
209 }
210
211 /**
212 * If [usePath] is `true` then [Source] path should be used instead of URI.
213 */
214 List<int> _getLocationPath(
215 Element element, ElementLocation location, bool usePath) {
216 // prepare the location components
217 List<String> components = location.components;
218 if (usePath) {
219 LibraryElement library = element.library;
220 if (library != null) {
221 components = components.toList();
222 components[0] = library.source.fullName;
223 for (Element e = element; e != null; e = e.enclosingElement) {
224 if (e is CompilationUnitElement) {
225 components[1] = e.source.fullName;
226 break;
227 }
228 }
229 }
230 }
231 // encode the location
232 int length = components.length;
233 if (_hasLocalOffset(components)) {
234 List<int> path = new List<int>();
235 for (String component in components) {
236 int atOffset = component.indexOf('@');
237 if (atOffset == -1) {
238 path.add(_stringCodec.encode(component));
239 } else {
240 String preAtString = component.substring(0, atOffset);
241 String atString = component.substring(atOffset + 1);
242 path.add(_stringCodec.encode(preAtString));
243 path.add(-1 * int.parse(atString));
244 }
245 }
246 return path;
247 } else {
248 List<int> path = new List<int>.filled(length, 0);
249 for (int i = 0; i < length; i++) {
250 String component = components[i];
251 path[i] = _stringCodec.encode(component);
252 }
253 return path;
254 }
255 }
256
257 static bool _hasLocalOffset(List<String> components) {
258 for (String component in components) {
259 if (component.indexOf('@') != -1) {
260 return true;
261 }
262 }
263 return false;
264 }
265 } 176 }
266 177
267 /** 178 /**
268 * A helper that encodes/decodes [Relationship]s to/from integers. 179 * A helper that encodes/decodes [Relationship]s to/from integers.
269 */ 180 */
270 class RelationshipCodec { 181 class RelationshipCodec {
271 final StringCodec _stringCodec; 182 final StringCodec _stringCodec;
272 183
273 RelationshipCodec(this._stringCodec); 184 RelationshipCodec(this._stringCodec);
274 185
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 int encode(String name) { 219 int encode(String name) {
309 int index = nameToIndex[name]; 220 int index = nameToIndex[name];
310 if (index == null) { 221 if (index == null) {
311 index = _indexToName.length; 222 index = _indexToName.length;
312 nameToIndex[name] = index; 223 nameToIndex[name] = index;
313 _indexToName.add(name); 224 _indexToName.add(name);
314 } 225 }
315 return index; 226 return index;
316 } 227 }
317 } 228 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698