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

Side by Side Diff: dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/index/file/SplitIndexStoreImpl.java

Issue 371913004: Version 1.5.6 (Closed) Base URL: http://dart.googlecode.com/svn/branches/1.5/
Patch Set: Created 6 years, 5 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2014, the Dart project authors.
3 *
4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u se this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Unless required by applicable law or agreed to in writing, software distribut ed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K IND, either express
11 * or implied. See the License for the specific language governing permissions a nd limitations under
12 * the License.
13 */
14
15 package com.google.dart.engine.internal.index.file;
16
17 import com.google.common.collect.Lists;
18 import com.google.common.collect.Maps;
19 import com.google.common.collect.Sets;
20 import com.google.dart.engine.AnalysisEngine;
21 import com.google.dart.engine.context.AnalysisContext;
22 import com.google.dart.engine.element.CompilationUnitElement;
23 import com.google.dart.engine.element.Element;
24 import com.google.dart.engine.element.ElementKind;
25 import com.google.dart.engine.element.HtmlElement;
26 import com.google.dart.engine.element.LibraryElement;
27 import com.google.dart.engine.index.IndexStore;
28 import com.google.dart.engine.index.Location;
29 import com.google.dart.engine.index.Relationship;
30 import com.google.dart.engine.index.UniverseElement;
31 import com.google.dart.engine.internal.context.AnalysisContextImpl;
32 import com.google.dart.engine.internal.context.InstrumentedAnalysisContextImpl;
33 import com.google.dart.engine.source.Source;
34 import com.google.dart.engine.source.SourceContainer;
35
36 import org.apache.commons.lang3.ArrayUtils;
37
38 import java.util.Collections;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Map.Entry;
42 import java.util.Set;
43
44 /**
45 * An {@link IndexStore} which keeps index information in separate nodes for eac h unit.
46 *
47 * @coverage dart.engine.index
48 */
49 public class SplitIndexStoreImpl implements IndexStore {
50 /**
51 * The {@link NodeManager} to get/put {@link IndexNode}s.
52 */
53 private final NodeManager nodeManager;
54
55 /**
56 * The {@link ContextCodec} to encode/decode {@link AnalysisContext}s.
57 */
58 private final ContextCodec contextCodec;
59
60 /**
61 * The {@link ElementCodec} to encode/decode {@link Element}s.
62 */
63 private final ElementCodec elementCodec;
64
65 /**
66 * The {@link StringCodec} to encode/decode {@link String}s.
67 */
68 private final StringCodec stringCodec;
69
70 /**
71 * A table mapping element names to the node names that may have relations wit h elements with
72 * these names.
73 */
74 private final IntToIntSetMap nameToNodeNames = new IntToIntSetMap(10000, 0.75f );
75
76 /**
77 * Information about "universe" elements. We need to keep them together to avo id loading of all
78 * index nodes.
79 * <p>
80 * Order of keys: contextId, nodeId, Relationship.
81 */
82 private final Map<Integer, Map<Integer, Map<Relationship, List<LocationData>>> > contextNodeRelations = Maps.newHashMap();
83
84 /**
85 * The mapping of library {@link Source} to the {@link Source}s of part units.
86 */
87 final Map<AnalysisContext, Map<Source, Set<Source>>> contextToLibraryToUnits = Maps.newHashMap();
88
89 /**
90 * The mapping of unit {@link Source} to the {@link Source}s of libraries it i s used in.
91 */
92 final Map<AnalysisContext, Map<Source, Set<Source>>> contextToUnitToLibraries = Maps.newHashMap();
93
94 /**
95 * The set of known {@link Source}s.
96 */
97 private final Set<Source> sources = Sets.newHashSet();
98
99 private int currentContextId;
100 private String currentNodeName;
101 private int currentNodeNameId;
102 private IndexNode currentNode;
103
104 public SplitIndexStoreImpl(NodeManager nodeManager) {
105 this.nodeManager = nodeManager;
106 this.contextCodec = nodeManager.getContextCodec();
107 this.elementCodec = nodeManager.getElementCodec();
108 this.stringCodec = nodeManager.getStringCodec();
109 }
110
111 @Override
112 public boolean aboutToIndexDart(AnalysisContext context, CompilationUnitElemen t unitElement) {
113 context = unwrapContext(context);
114 // may be already disposed in other thread
115 if (context.isDisposed()) {
116 return false;
117 }
118 // validate unit
119 if (unitElement == null) {
120 return false;
121 }
122 LibraryElement libraryElement = unitElement.getLibrary();
123 if (libraryElement == null) {
124 return false;
125 }
126 CompilationUnitElement definingUnitElement = libraryElement.getDefiningCompi lationUnit();
127 if (definingUnitElement == null) {
128 return false;
129 }
130 // prepare sources
131 Source library = definingUnitElement.getSource();
132 Source unit = unitElement.getSource();
133 // special handling for the defining library unit
134 if (unit.equals(library)) {
135 // prepare new parts
136 Set<Source> newParts = Sets.newHashSet();
137 for (CompilationUnitElement part : libraryElement.getParts()) {
138 newParts.add(part.getSource());
139 }
140 // prepare old parts
141 Map<Source, Set<Source>> libraryToUnits = contextToLibraryToUnits.get(cont ext);
142 if (libraryToUnits == null) {
143 libraryToUnits = Maps.newHashMap();
144 contextToLibraryToUnits.put(context, libraryToUnits);
145 }
146 Set<Source> oldParts = libraryToUnits.get(library);
147 // check if some parts are not in the library now
148 if (oldParts != null) {
149 Set<Source> noParts = Sets.difference(oldParts, newParts);
150 for (Source noPart : noParts) {
151 removeLocations(context, library, noPart);
152 }
153 }
154 // remember new parts
155 libraryToUnits.put(library, newParts);
156 }
157 // remember library/unit relations
158 recordUnitInLibrary(context, library, unit);
159 recordLibraryWithUnit(context, library, unit);
160 sources.add(library);
161 sources.add(unit);
162 // prepare node
163 String libraryName = library.getFullName();
164 String unitName = unit.getFullName();
165 int libraryNameIndex = stringCodec.encode(libraryName);
166 int unitNameIndex = stringCodec.encode(unitName);
167 currentNodeName = libraryNameIndex + "_" + unitNameIndex + ".index";
168 currentNodeNameId = stringCodec.encode(currentNodeName);
169 currentNode = nodeManager.newNode(context);
170 currentContextId = contextCodec.encode(context);
171 // remove Universe information for the current node
172 for (Map<Integer, ?> nodeRelations : contextNodeRelations.values()) {
173 nodeRelations.remove(currentNodeNameId);
174 }
175 // done
176 return true;
177 }
178
179 @Override
180 public boolean aboutToIndexHtml(AnalysisContext context, HtmlElement htmlEleme nt) {
181 context = unwrapContext(context);
182 // may be already disposed in other thread
183 if (context.isDisposed()) {
184 return false;
185 }
186 // remove locations
187 Source source = htmlElement.getSource();
188 removeLocations(context, null, source);
189 // remember library/unit relations
190 recordUnitInLibrary(context, null, source);
191 // prepare node
192 String sourceName = source.getFullName();
193 int sourceNameIndex = stringCodec.encode(sourceName);
194 currentNodeName = sourceNameIndex + ".index";
195 currentNodeNameId = stringCodec.encode(currentNodeName);
196 currentNode = nodeManager.newNode(context);
197 return true;
198 }
199
200 @Override
201 public void clear() {
202 nodeManager.clear();
203 nameToNodeNames.clear();
204 }
205
206 @Override
207 public void doneIndex() {
208 if (currentNode != null) {
209 nodeManager.putNode(currentNodeName, currentNode);
210 currentNodeName = null;
211 currentNodeNameId = -1;
212 currentNode = null;
213 currentContextId = -1;
214 }
215 }
216
217 @Override
218 public Location[] getRelationships(Element element, Relationship relationship) {
219 // special support for UniverseElement
220 if (element == UniverseElement.INSTANCE) {
221 return getRelationshipsUniverse(relationship);
222 }
223 // prepare node names
224 String name = getElementName(element);
225 int nameId = stringCodec.encode(name);
226 int[] nodeNameIds = nameToNodeNames.get(nameId);
227 // check each node
228 List<Location> locations = Lists.newArrayList();
229 for (int i = 0; i < nodeNameIds.length; i++) {
230 int nodeNameId = nodeNameIds[i];
231 String nodeName = stringCodec.decode(nodeNameId);
232 IndexNode node = nodeManager.getNode(nodeName);
233 if (node != null) {
234 Collections.addAll(locations, node.getRelationships(element, relationshi p));
235 } else {
236 nodeNameIds = ArrayUtils.removeElement(nodeNameIds, nodeNameId);
237 i--;
238 }
239 }
240 // done
241 return locations.toArray(new Location[locations.size()]);
242 }
243
244 @Override
245 public String getStatistics() {
246 return "[" + nodeManager.getLocationCount() + " locations, " + sources.size( ) + " sources, "
247 + nameToNodeNames.size() + " names]";
248 }
249
250 @Override
251 public void recordRelationship(Element element, Relationship relationship, Loc ation location) {
252 if (element == null || element.getKind() == ElementKind.ERROR) {
253 return;
254 }
255 if (location == null) {
256 return;
257 }
258 // special support for UniverseElement
259 if (element == UniverseElement.INSTANCE) {
260 recordRelationshipUniverse(relationship, location);
261 return;
262 }
263 // other elements
264 recordNodeNameForElement(element);
265 currentNode.recordRelationship(element, relationship, location);
266 }
267
268 @Override
269 public void removeContext(AnalysisContext context) {
270 context = unwrapContext(context);
271 if (context == null) {
272 return;
273 }
274 // remove sources
275 removeSources(context, null);
276 // remove context information
277 contextToLibraryToUnits.remove(context);
278 contextToUnitToLibraries.remove(context);
279 contextNodeRelations.remove(contextCodec.encode(context));
280 // remove context from codec
281 contextCodec.removeContext(context);
282 }
283
284 @Override
285 public void removeSource(AnalysisContext context, Source source) {
286 context = unwrapContext(context);
287 if (context == null) {
288 return;
289 }
290 // remove nodes for unit/library pairs
291 Map<Source, Set<Source>> unitToLibraries = contextToUnitToLibraries.get(cont ext);
292 if (unitToLibraries != null) {
293 Set<Source> libraries = unitToLibraries.remove(source);
294 if (libraries != null) {
295 for (Source library : libraries) {
296 removeLocations(context, library, source);
297 }
298 }
299 }
300 // remove nodes for library/unit pairs
301 Map<Source, Set<Source>> libraryToUnits = contextToLibraryToUnits.get(contex t);
302 if (libraryToUnits != null) {
303 Set<Source> units = libraryToUnits.remove(source);
304 if (units != null) {
305 for (Source unit : units) {
306 removeLocations(context, source, unit);
307 }
308 }
309 }
310 }
311
312 @Override
313 public void removeSources(AnalysisContext context, SourceContainer container) {
314 context = unwrapContext(context);
315 if (context == null) {
316 return;
317 }
318 // remove nodes for unit/library pairs
319 Map<Source, Set<Source>> unitToLibraries = contextToUnitToLibraries.get(cont ext);
320 if (unitToLibraries != null) {
321 List<Source> units = Lists.newArrayList(unitToLibraries.keySet());
322 for (Source source : units) {
323 if (container == null || container.contains(source)) {
324 removeSource(context, source);
325 }
326 }
327 }
328 // remove nodes for library/unit pairs
329 Map<Source, Set<Source>> libraryToUnits = contextToLibraryToUnits.get(contex t);
330 if (libraryToUnits != null) {
331 List<Source> libraries = Lists.newArrayList(libraryToUnits.keySet());
332 for (Source source : libraries) {
333 if (container == null || container.contains(source)) {
334 removeSource(context, source);
335 }
336 }
337 }
338 }
339
340 private String getElementName(Element element) {
341 return element.getName();
342 }
343
344 private Location[] getRelationshipsUniverse(Relationship relationship) {
345 List<Location> locations = Lists.newArrayList();
346 for (Entry<Integer, Map<Integer, Map<Relationship, List<LocationData>>>> con textEntry : contextNodeRelations.entrySet()) {
347 int contextId = contextEntry.getKey();
348 AnalysisContext context = contextCodec.decode(contextId);
349 if (context != null) {
350 for (Map<Relationship, List<LocationData>> nodeRelations : contextEntry. getValue().values()) {
351 List<LocationData> nodeLocations = nodeRelations.get(relationship);
352 if (nodeLocations != null) {
353 for (LocationData locationData : nodeLocations) {
354 Location location = locationData.getLocation(context, elementCodec );
355 if (location != null) {
356 locations.add(location);
357 }
358 }
359 }
360 }
361 }
362 }
363 return locations.toArray(new Location[locations.size()]);
364 }
365
366 private void recordLibraryWithUnit(AnalysisContext context, Source library, So urce unit) {
367 Map<Source, Set<Source>> libraryToUnits = contextToLibraryToUnits.get(contex t);
368 if (libraryToUnits == null) {
369 libraryToUnits = Maps.newHashMap();
370 contextToLibraryToUnits.put(context, libraryToUnits);
371 }
372 Set<Source> units = libraryToUnits.get(library);
373 if (units == null) {
374 units = Sets.newHashSet();
375 libraryToUnits.put(library, units);
376 }
377 units.add(unit);
378 }
379
380 private void recordNodeNameForElement(Element element) {
381 String name = getElementName(element);
382 int nameId = stringCodec.encode(name);
383 nameToNodeNames.add(nameId, currentNodeNameId);
384 }
385
386 private void recordRelationshipUniverse(Relationship relationship, Location lo cation) {
387 // in current context
388 Map<Integer, Map<Relationship, List<LocationData>>> nodeRelations = contextN odeRelations.get(currentContextId);
389 if (nodeRelations == null) {
390 nodeRelations = Maps.newHashMap();
391 contextNodeRelations.put(currentContextId, nodeRelations);
392 }
393 // in current node
394 Map<Relationship, List<LocationData>> relations = nodeRelations.get(currentN odeNameId);
395 if (relations == null) {
396 relations = Maps.newHashMap();
397 nodeRelations.put(currentNodeNameId, relations);
398 }
399 // for the given relationship
400 List<LocationData> locations = relations.get(relationship);
401 if (locations == null) {
402 locations = Lists.newArrayList();
403 relations.put(relationship, locations);
404 }
405 // record LocationData
406 locations.add(new LocationData(elementCodec, location));
407 }
408
409 private void recordUnitInLibrary(AnalysisContext context, Source library, Sour ce unit) {
410 Map<Source, Set<Source>> unitToLibraries = contextToUnitToLibraries.get(cont ext);
411 if (unitToLibraries == null) {
412 unitToLibraries = Maps.newHashMap();
413 contextToUnitToLibraries.put(context, unitToLibraries);
414 }
415 Set<Source> libraries = unitToLibraries.get(unit);
416 if (libraries == null) {
417 libraries = Sets.newHashSet();
418 unitToLibraries.put(unit, libraries);
419 }
420 libraries.add(library);
421 }
422
423 /**
424 * Removes locations recorded in the given library/unit pair.
425 */
426 private void removeLocations(AnalysisContext context, Source library, Source u nit) {
427 // remove node
428 String libraryName = library != null ? library.getFullName() : null;
429 String unitName = unit.getFullName();
430 int libraryNameIndex = stringCodec.encode(libraryName);
431 int unitNameIndex = stringCodec.encode(unitName);
432 String nodeName = libraryNameIndex + "_" + unitNameIndex + ".index";
433 nodeManager.removeNode(nodeName);
434 // remove source
435 sources.remove(library);
436 sources.remove(unit);
437 }
438
439 /**
440 * When logging is on, {@link AnalysisEngine} actually creates
441 * {@link InstrumentedAnalysisContextImpl}, which wraps {@link AnalysisContext Impl} used to create
442 * actual {@link Element}s. So, in index we have to unwrap {@link Instrumented AnalysisContextImpl}
443 * when perform any operation.
444 */
445 private AnalysisContext unwrapContext(AnalysisContext context) {
446 if (context instanceof InstrumentedAnalysisContextImpl) {
447 context = ((InstrumentedAnalysisContextImpl) context).getBasis();
448 }
449 return context;
450 }
451 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698