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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/index/file/SplitIndexStoreImpl.java
===================================================================
--- dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/index/file/SplitIndexStoreImpl.java (revision 0)
+++ dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/index/file/SplitIndexStoreImpl.java (revision 0)
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2014, the Dart project authors.
+ *
+ * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.dart.engine.internal.index.file;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.dart.engine.AnalysisEngine;
+import com.google.dart.engine.context.AnalysisContext;
+import com.google.dart.engine.element.CompilationUnitElement;
+import com.google.dart.engine.element.Element;
+import com.google.dart.engine.element.ElementKind;
+import com.google.dart.engine.element.HtmlElement;
+import com.google.dart.engine.element.LibraryElement;
+import com.google.dart.engine.index.IndexStore;
+import com.google.dart.engine.index.Location;
+import com.google.dart.engine.index.Relationship;
+import com.google.dart.engine.index.UniverseElement;
+import com.google.dart.engine.internal.context.AnalysisContextImpl;
+import com.google.dart.engine.internal.context.InstrumentedAnalysisContextImpl;
+import com.google.dart.engine.source.Source;
+import com.google.dart.engine.source.SourceContainer;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * An {@link IndexStore} which keeps index information in separate nodes for each unit.
+ *
+ * @coverage dart.engine.index
+ */
+public class SplitIndexStoreImpl implements IndexStore {
+ /**
+ * The {@link NodeManager} to get/put {@link IndexNode}s.
+ */
+ private final NodeManager nodeManager;
+
+ /**
+ * The {@link ContextCodec} to encode/decode {@link AnalysisContext}s.
+ */
+ private final ContextCodec contextCodec;
+
+ /**
+ * The {@link ElementCodec} to encode/decode {@link Element}s.
+ */
+ private final ElementCodec elementCodec;
+
+ /**
+ * The {@link StringCodec} to encode/decode {@link String}s.
+ */
+ private final StringCodec stringCodec;
+
+ /**
+ * A table mapping element names to the node names that may have relations with elements with
+ * these names.
+ */
+ private final IntToIntSetMap nameToNodeNames = new IntToIntSetMap(10000, 0.75f);
+
+ /**
+ * Information about "universe" elements. We need to keep them together to avoid loading of all
+ * index nodes.
+ * <p>
+ * Order of keys: contextId, nodeId, Relationship.
+ */
+ private final Map<Integer, Map<Integer, Map<Relationship, List<LocationData>>>> contextNodeRelations = Maps.newHashMap();
+
+ /**
+ * The mapping of library {@link Source} to the {@link Source}s of part units.
+ */
+ final Map<AnalysisContext, Map<Source, Set<Source>>> contextToLibraryToUnits = Maps.newHashMap();
+
+ /**
+ * The mapping of unit {@link Source} to the {@link Source}s of libraries it is used in.
+ */
+ final Map<AnalysisContext, Map<Source, Set<Source>>> contextToUnitToLibraries = Maps.newHashMap();
+
+ /**
+ * The set of known {@link Source}s.
+ */
+ private final Set<Source> sources = Sets.newHashSet();
+
+ private int currentContextId;
+ private String currentNodeName;
+ private int currentNodeNameId;
+ private IndexNode currentNode;
+
+ public SplitIndexStoreImpl(NodeManager nodeManager) {
+ this.nodeManager = nodeManager;
+ this.contextCodec = nodeManager.getContextCodec();
+ this.elementCodec = nodeManager.getElementCodec();
+ this.stringCodec = nodeManager.getStringCodec();
+ }
+
+ @Override
+ public boolean aboutToIndexDart(AnalysisContext context, CompilationUnitElement unitElement) {
+ context = unwrapContext(context);
+ // may be already disposed in other thread
+ if (context.isDisposed()) {
+ return false;
+ }
+ // validate unit
+ if (unitElement == null) {
+ return false;
+ }
+ LibraryElement libraryElement = unitElement.getLibrary();
+ if (libraryElement == null) {
+ return false;
+ }
+ CompilationUnitElement definingUnitElement = libraryElement.getDefiningCompilationUnit();
+ if (definingUnitElement == null) {
+ return false;
+ }
+ // prepare sources
+ Source library = definingUnitElement.getSource();
+ Source unit = unitElement.getSource();
+ // special handling for the defining library unit
+ if (unit.equals(library)) {
+ // prepare new parts
+ Set<Source> newParts = Sets.newHashSet();
+ for (CompilationUnitElement part : libraryElement.getParts()) {
+ newParts.add(part.getSource());
+ }
+ // prepare old parts
+ Map<Source, Set<Source>> libraryToUnits = contextToLibraryToUnits.get(context);
+ if (libraryToUnits == null) {
+ libraryToUnits = Maps.newHashMap();
+ contextToLibraryToUnits.put(context, libraryToUnits);
+ }
+ Set<Source> oldParts = libraryToUnits.get(library);
+ // check if some parts are not in the library now
+ if (oldParts != null) {
+ Set<Source> noParts = Sets.difference(oldParts, newParts);
+ for (Source noPart : noParts) {
+ removeLocations(context, library, noPart);
+ }
+ }
+ // remember new parts
+ libraryToUnits.put(library, newParts);
+ }
+ // remember library/unit relations
+ recordUnitInLibrary(context, library, unit);
+ recordLibraryWithUnit(context, library, unit);
+ sources.add(library);
+ sources.add(unit);
+ // prepare node
+ String libraryName = library.getFullName();
+ String unitName = unit.getFullName();
+ int libraryNameIndex = stringCodec.encode(libraryName);
+ int unitNameIndex = stringCodec.encode(unitName);
+ currentNodeName = libraryNameIndex + "_" + unitNameIndex + ".index";
+ currentNodeNameId = stringCodec.encode(currentNodeName);
+ currentNode = nodeManager.newNode(context);
+ currentContextId = contextCodec.encode(context);
+ // remove Universe information for the current node
+ for (Map<Integer, ?> nodeRelations : contextNodeRelations.values()) {
+ nodeRelations.remove(currentNodeNameId);
+ }
+ // done
+ return true;
+ }
+
+ @Override
+ public boolean aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement) {
+ context = unwrapContext(context);
+ // may be already disposed in other thread
+ if (context.isDisposed()) {
+ return false;
+ }
+ // remove locations
+ Source source = htmlElement.getSource();
+ removeLocations(context, null, source);
+ // remember library/unit relations
+ recordUnitInLibrary(context, null, source);
+ // prepare node
+ String sourceName = source.getFullName();
+ int sourceNameIndex = stringCodec.encode(sourceName);
+ currentNodeName = sourceNameIndex + ".index";
+ currentNodeNameId = stringCodec.encode(currentNodeName);
+ currentNode = nodeManager.newNode(context);
+ return true;
+ }
+
+ @Override
+ public void clear() {
+ nodeManager.clear();
+ nameToNodeNames.clear();
+ }
+
+ @Override
+ public void doneIndex() {
+ if (currentNode != null) {
+ nodeManager.putNode(currentNodeName, currentNode);
+ currentNodeName = null;
+ currentNodeNameId = -1;
+ currentNode = null;
+ currentContextId = -1;
+ }
+ }
+
+ @Override
+ public Location[] getRelationships(Element element, Relationship relationship) {
+ // special support for UniverseElement
+ if (element == UniverseElement.INSTANCE) {
+ return getRelationshipsUniverse(relationship);
+ }
+ // prepare node names
+ String name = getElementName(element);
+ int nameId = stringCodec.encode(name);
+ int[] nodeNameIds = nameToNodeNames.get(nameId);
+ // check each node
+ List<Location> locations = Lists.newArrayList();
+ for (int i = 0; i < nodeNameIds.length; i++) {
+ int nodeNameId = nodeNameIds[i];
+ String nodeName = stringCodec.decode(nodeNameId);
+ IndexNode node = nodeManager.getNode(nodeName);
+ if (node != null) {
+ Collections.addAll(locations, node.getRelationships(element, relationship));
+ } else {
+ nodeNameIds = ArrayUtils.removeElement(nodeNameIds, nodeNameId);
+ i--;
+ }
+ }
+ // done
+ return locations.toArray(new Location[locations.size()]);
+ }
+
+ @Override
+ public String getStatistics() {
+ return "[" + nodeManager.getLocationCount() + " locations, " + sources.size() + " sources, "
+ + nameToNodeNames.size() + " names]";
+ }
+
+ @Override
+ public void recordRelationship(Element element, Relationship relationship, Location location) {
+ if (element == null || element.getKind() == ElementKind.ERROR) {
+ return;
+ }
+ if (location == null) {
+ return;
+ }
+ // special support for UniverseElement
+ if (element == UniverseElement.INSTANCE) {
+ recordRelationshipUniverse(relationship, location);
+ return;
+ }
+ // other elements
+ recordNodeNameForElement(element);
+ currentNode.recordRelationship(element, relationship, location);
+ }
+
+ @Override
+ public void removeContext(AnalysisContext context) {
+ context = unwrapContext(context);
+ if (context == null) {
+ return;
+ }
+ // remove sources
+ removeSources(context, null);
+ // remove context information
+ contextToLibraryToUnits.remove(context);
+ contextToUnitToLibraries.remove(context);
+ contextNodeRelations.remove(contextCodec.encode(context));
+ // remove context from codec
+ contextCodec.removeContext(context);
+ }
+
+ @Override
+ public void removeSource(AnalysisContext context, Source source) {
+ context = unwrapContext(context);
+ if (context == null) {
+ return;
+ }
+ // remove nodes for unit/library pairs
+ Map<Source, Set<Source>> unitToLibraries = contextToUnitToLibraries.get(context);
+ if (unitToLibraries != null) {
+ Set<Source> libraries = unitToLibraries.remove(source);
+ if (libraries != null) {
+ for (Source library : libraries) {
+ removeLocations(context, library, source);
+ }
+ }
+ }
+ // remove nodes for library/unit pairs
+ Map<Source, Set<Source>> libraryToUnits = contextToLibraryToUnits.get(context);
+ if (libraryToUnits != null) {
+ Set<Source> units = libraryToUnits.remove(source);
+ if (units != null) {
+ for (Source unit : units) {
+ removeLocations(context, source, unit);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void removeSources(AnalysisContext context, SourceContainer container) {
+ context = unwrapContext(context);
+ if (context == null) {
+ return;
+ }
+ // remove nodes for unit/library pairs
+ Map<Source, Set<Source>> unitToLibraries = contextToUnitToLibraries.get(context);
+ if (unitToLibraries != null) {
+ List<Source> units = Lists.newArrayList(unitToLibraries.keySet());
+ for (Source source : units) {
+ if (container == null || container.contains(source)) {
+ removeSource(context, source);
+ }
+ }
+ }
+ // remove nodes for library/unit pairs
+ Map<Source, Set<Source>> libraryToUnits = contextToLibraryToUnits.get(context);
+ if (libraryToUnits != null) {
+ List<Source> libraries = Lists.newArrayList(libraryToUnits.keySet());
+ for (Source source : libraries) {
+ if (container == null || container.contains(source)) {
+ removeSource(context, source);
+ }
+ }
+ }
+ }
+
+ private String getElementName(Element element) {
+ return element.getName();
+ }
+
+ private Location[] getRelationshipsUniverse(Relationship relationship) {
+ List<Location> locations = Lists.newArrayList();
+ for (Entry<Integer, Map<Integer, Map<Relationship, List<LocationData>>>> contextEntry : contextNodeRelations.entrySet()) {
+ int contextId = contextEntry.getKey();
+ AnalysisContext context = contextCodec.decode(contextId);
+ if (context != null) {
+ for (Map<Relationship, List<LocationData>> nodeRelations : contextEntry.getValue().values()) {
+ List<LocationData> nodeLocations = nodeRelations.get(relationship);
+ if (nodeLocations != null) {
+ for (LocationData locationData : nodeLocations) {
+ Location location = locationData.getLocation(context, elementCodec);
+ if (location != null) {
+ locations.add(location);
+ }
+ }
+ }
+ }
+ }
+ }
+ return locations.toArray(new Location[locations.size()]);
+ }
+
+ private void recordLibraryWithUnit(AnalysisContext context, Source library, Source unit) {
+ Map<Source, Set<Source>> libraryToUnits = contextToLibraryToUnits.get(context);
+ if (libraryToUnits == null) {
+ libraryToUnits = Maps.newHashMap();
+ contextToLibraryToUnits.put(context, libraryToUnits);
+ }
+ Set<Source> units = libraryToUnits.get(library);
+ if (units == null) {
+ units = Sets.newHashSet();
+ libraryToUnits.put(library, units);
+ }
+ units.add(unit);
+ }
+
+ private void recordNodeNameForElement(Element element) {
+ String name = getElementName(element);
+ int nameId = stringCodec.encode(name);
+ nameToNodeNames.add(nameId, currentNodeNameId);
+ }
+
+ private void recordRelationshipUniverse(Relationship relationship, Location location) {
+ // in current context
+ Map<Integer, Map<Relationship, List<LocationData>>> nodeRelations = contextNodeRelations.get(currentContextId);
+ if (nodeRelations == null) {
+ nodeRelations = Maps.newHashMap();
+ contextNodeRelations.put(currentContextId, nodeRelations);
+ }
+ // in current node
+ Map<Relationship, List<LocationData>> relations = nodeRelations.get(currentNodeNameId);
+ if (relations == null) {
+ relations = Maps.newHashMap();
+ nodeRelations.put(currentNodeNameId, relations);
+ }
+ // for the given relationship
+ List<LocationData> locations = relations.get(relationship);
+ if (locations == null) {
+ locations = Lists.newArrayList();
+ relations.put(relationship, locations);
+ }
+ // record LocationData
+ locations.add(new LocationData(elementCodec, location));
+ }
+
+ private void recordUnitInLibrary(AnalysisContext context, Source library, Source unit) {
+ Map<Source, Set<Source>> unitToLibraries = contextToUnitToLibraries.get(context);
+ if (unitToLibraries == null) {
+ unitToLibraries = Maps.newHashMap();
+ contextToUnitToLibraries.put(context, unitToLibraries);
+ }
+ Set<Source> libraries = unitToLibraries.get(unit);
+ if (libraries == null) {
+ libraries = Sets.newHashSet();
+ unitToLibraries.put(unit, libraries);
+ }
+ libraries.add(library);
+ }
+
+ /**
+ * Removes locations recorded in the given library/unit pair.
+ */
+ private void removeLocations(AnalysisContext context, Source library, Source unit) {
+ // remove node
+ String libraryName = library != null ? library.getFullName() : null;
+ String unitName = unit.getFullName();
+ int libraryNameIndex = stringCodec.encode(libraryName);
+ int unitNameIndex = stringCodec.encode(unitName);
+ String nodeName = libraryNameIndex + "_" + unitNameIndex + ".index";
+ nodeManager.removeNode(nodeName);
+ // remove source
+ sources.remove(library);
+ sources.remove(unit);
+ }
+
+ /**
+ * When logging is on, {@link AnalysisEngine} actually creates
+ * {@link InstrumentedAnalysisContextImpl}, which wraps {@link AnalysisContextImpl} used to create
+ * actual {@link Element}s. So, in index we have to unwrap {@link InstrumentedAnalysisContextImpl}
+ * when perform any operation.
+ */
+ private AnalysisContext unwrapContext(AnalysisContext context) {
+ if (context instanceof InstrumentedAnalysisContextImpl) {
+ context = ((InstrumentedAnalysisContextImpl) context).getBasis();
+ }
+ return context;
+ }
+}
Property changes on: dart/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/index/file/SplitIndexStoreImpl.java
___________________________________________________________________
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698