javac ast indices uses MapReduceIndex

This commit is contained in:
Dmitry Batkovich
2016-12-02 17:01:07 +03:00
parent 3e927e977f
commit 67fdc4e1cf
10 changed files with 505 additions and 482 deletions

View File

@@ -24,6 +24,8 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.containers.Queue;
import com.intellij.util.indexing.StorageException;
import com.intellij.util.indexing.ValueContainer;
import gnu.trove.THashSet;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
@@ -31,27 +33,25 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator;
import org.jetbrains.jps.backwardRefs.CompilerBackwardReferenceIndex;
import org.jetbrains.jps.backwardRefs.LightRef;
import org.jetbrains.jps.backwardRefs.index.CompilerIndices;
import java.io.File;
import java.io.IOException;
import java.util.*;
import static java.util.stream.Collectors.*;
import static java.util.stream.Collectors.toList;
class CompilerReferenceReader {
private final static Logger LOG = Logger.getInstance(CompilerReferenceReader.class);
private final CompilerBackwardReferenceIndex myIndex;
private final Object myHierarchyLock = new Object(); //access to hierarchy & definition maps
private final Object myReferenceLock = new Object(); //access to reference & file enumerator maps
private CompilerReferenceReader(File buildDir) throws IOException {
myIndex = new CompilerBackwardReferenceIndex(buildDir);
}
@Nullable
TIntHashSet findReferentFileIds(@NotNull LightRef ref, boolean checkBaseClassAmbiguity) {
TIntHashSet findReferentFileIds(@NotNull LightRef ref, boolean checkBaseClassAmbiguity) throws StorageException {
LightRef.LightClassHierarchyElementDef hierarchyElement = ref instanceof LightRef.LightClassHierarchyElementDef ?
(LightRef.LightClassHierarchyElementDef)ref :
((LightRef.LightMember)ref).getOwner();
@@ -76,38 +76,22 @@ class CompilerReferenceReader {
@NotNull GlobalSearchScope searchScope,
@NotNull GlobalSearchScope dirtyScope,
@NotNull FileType fileType,
@NotNull CompilerHierarchySearchType searchType) {
Collection<CompilerBackwardReferenceIndex.LightDefinition> candidates;
synchronized (myHierarchyLock) {
candidates = myIndex.getBackwardHierarchyMap().get(searchElement);
}
if (candidates == null) return Collections.emptyMap();
@NotNull CompilerHierarchySearchType searchType) throws StorageException {
GlobalSearchScope effectiveSearchScope = GlobalSearchScope.notScope(dirtyScope).intersectWith(searchScope);
LanguageLightRefAdapter adapter = CompilerReferenceServiceImpl.findAdapterForFileType(fileType);
LOG.assertTrue(adapter != null, "adapter is null for file type: " + fileType);
Class<? extends LightRef> requiredLightRefClass = searchType.getRequiredClass(adapter);
Map<VirtualFile, Object[]> candidatesPerFile;
synchronized (myReferenceLock) {
candidatesPerFile = candidates
.stream()
.filter(def -> requiredLightRefClass.isInstance(def.getRef()))
.map(definition -> {
final VirtualFile file = findFile(definition.getFileId());
if (file != null && effectiveSearchScope.contains(file)) {
return new Object() {
final VirtualFile containingFile = file;
final LightRef def = definition.getRef();
};
}
else {
return null;
}
})
.filter(Objects::nonNull)
.collect(groupingBy(x -> x.containingFile, mapping(x -> x.def, collectingAndThen(toList(), l -> searchType.convertToIds(l, myIndex.getByteSeqEum())))));
}
Map<VirtualFile, Object[]> candidatesPerFile = new HashMap<>();
myIndex.get(CompilerIndices.BACK_HIERARCHY).getData(searchElement).forEach((fileId, defs) -> {
final List<LightRef> requiredCandidates = defs.stream().filter(requiredLightRefClass::isInstance).collect(toList());
if (requiredCandidates.isEmpty()) return true;
final VirtualFile file = findFile(fileId);
if (file != null && effectiveSearchScope.contains(file)) {
candidatesPerFile.put(file, searchType.convertToIds(defs, myIndex.getByteSeqEum()));
}
return true;
});
return candidatesPerFile.isEmpty() ? Collections.emptyMap() : candidatesPerFile;
}
@@ -133,19 +117,18 @@ class CompilerReferenceReader {
}
}
private void addUsages(LightRef usage, TIntHashSet sink) {
final Collection<Integer> usageFiles;
synchronized (myReferenceLock) {
usageFiles = myIndex.getBackwardReferenceMap().get(usage);
if (usageFiles != null) {
for (int fileId : usageFiles) {
final VirtualFile file = findFile(fileId);
private void addUsages(LightRef usage, TIntHashSet sink) throws StorageException {
myIndex.get(CompilerIndices.BACK_USAGES).getData(usage).forEach(
new ValueContainer.ContainerAction<Void>() {
@Override
public boolean perform(int id, Void value) {
final VirtualFile file = findFile(id);
if (file != null) {
sink.add(((VirtualFileWithId)file).getId());
}
return true;
}
}
}
});
}
private VirtualFile findFile(int id) {
@@ -160,38 +143,55 @@ class CompilerReferenceReader {
}
@Nullable("return null if the class hierarchy contains ambiguous qualified names")
private LightRef.NamedLightRef[] getWholeHierarchy(LightRef.LightClassHierarchyElementDef hierarchyElement, boolean checkBaseClassAmbiguity) {
private LightRef.NamedLightRef[] getWholeHierarchy(LightRef.LightClassHierarchyElementDef hierarchyElement, boolean checkBaseClassAmbiguity)
throws StorageException {
Set<LightRef.NamedLightRef> result = new THashSet<>();
Queue<LightRef.NamedLightRef> q = new Queue<>(10);
q.addLast(hierarchyElement);
synchronized (myHierarchyLock) {
while (!q.isEmpty()) {
LightRef.NamedLightRef curClass = q.pullFirst();
if (result.add(curClass)) {
if (checkBaseClassAmbiguity || curClass != hierarchyElement) {
final Collection<Integer> definitionFiles = myIndex.getBackwardClassDefinitionMap().get(curClass);
if (definitionFiles == null) {
//diagnostic
String baseHierarchyElement = getNameEnumerator().getName(hierarchyElement.getName());
String curHierarchyElement = getNameEnumerator().getName(curClass.getName());
LOG.error("Can't get definition files for :" + curHierarchyElement + " base class: " + baseHierarchyElement);
}
if (definitionFiles.size() != 1) {
return null;
}
while (!q.isEmpty()) {
LightRef.NamedLightRef curClass = q.pullFirst();
if (result.add(curClass)) {
if (checkBaseClassAmbiguity || curClass != hierarchyElement) {
DefCount count = getDefinitionCount(curClass);
if (count == DefCount.NONE) {
//diagnostic
String baseHierarchyElement = getNameEnumerator().getName(hierarchyElement.getName());
String curHierarchyElement = getNameEnumerator().getName(curClass.getName());
LOG.error("Can't get definition files for :" + curHierarchyElement + " base class: " + baseHierarchyElement);
}
final Collection<CompilerBackwardReferenceIndex.LightDefinition> subClassDefs = myIndex.getBackwardHierarchyMap().get(curClass);
if (subClassDefs != null) {
for (CompilerBackwardReferenceIndex.LightDefinition subclass : subClassDefs) {
final LightRef ref = subclass.getRef();
if (ref instanceof LightRef.LightClassHierarchyElementDef) {
q.addLast((LightRef.LightClassHierarchyElementDef) ref);
}
}
if (count != DefCount.ONE) {
return null;
}
}
myIndex.get(CompilerIndices.BACK_HIERARCHY).getData(curClass).forEach((id, children) -> {
for (LightRef child : children) {
q.addLast((LightRef.LightClassHierarchyElementDef) child);
}
return true;
});
}
}
return result.toArray(new LightRef.NamedLightRef[result.size()]);
}
private enum DefCount { NONE, ONE, MANY}
@NotNull
private DefCount getDefinitionCount(LightRef def) throws StorageException {
DefCount[] result = new DefCount[]{DefCount.NONE};
myIndex.get(CompilerIndices.BACK_CLASS_DEF).getData(def).forEach(new ValueContainer.ContainerAction<Void>() {
@Override
public boolean perform(int id, Void value) {
if (result[0] == DefCount.NONE) {
result[0] = DefCount.ONE;
return true;
}
if (result[0] == DefCount.ONE) {
result[0] = DefCount.MANY;
return true;
}
return false;
}
});
return result[0];
}
}

View File

@@ -46,6 +46,7 @@ import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.indexing.StorageException;
import gnu.trove.THashSet;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
@@ -266,7 +267,12 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
myReadDataLock.lock();
try {
if (myReader == null) return null;
return myReader.getDirectInheritors(searchElement, useScope, myDirtyModulesHolder.getDirtyScope(), searchFileType, searchType);
try {
return myReader.getDirectInheritors(searchElement, useScope, myDirtyModulesHolder.getDirtyScope(), searchFileType, searchType);
}
catch (StorageException e) {
throw new RuntimeException(e);
}
} finally {
myReadDataLock.unlock();
}
@@ -291,10 +297,15 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
if (myReader == null) return null;
TIntHashSet referentFileIds = new TIntHashSet();
for (LightRef ref : compilerElementInfo.searchElements) {
final TIntHashSet referents = myReader.findReferentFileIds(ref, compilerElementInfo.place == ElementPlace.SRC);
if (referents == null) return null;
referentFileIds.addAll(referents.toArray());
}
try {
final TIntHashSet referents = myReader.findReferentFileIds(ref, compilerElementInfo.place == ElementPlace.SRC);
if (referents == null) return null;
referentFileIds.addAll(referents.toArray());
}
catch (StorageException e) {
throw new RuntimeException(e);
}
}
return referentFileIds;
} finally {

View File

@@ -15,47 +15,65 @@
*/
package org.jetbrains.jps.backwardRefs;
import com.intellij.openapi.util.Factory;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.jps.backwardRefs.index.CompiledFileData;
import org.jetbrains.jps.javac.ast.api.JavacDef;
import org.jetbrains.jps.javac.ast.api.JavacRef;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.*;
public class BackwardReferenceIndexUtil {
static void registerFile(String filePath,
Set<? extends JavacRef> refs,
List<JavacDef> defs,
BackwardReferenceIndexWriter writer) {
final BackwardReferenceIndexWriter writer) {
final int fileId = writer.enumeratePath(filePath);
int funExprId = 0;
final List<LightRef> definitions = new ArrayList<LightRef>(defs.size());
final Map<LightRef, Void> definitions = new HashMap<LightRef, Void>(defs.size());
final Map<LightRef, Collection<LightRef>> backwardHierarchyMap = new HashMap<LightRef, Collection<LightRef>>();
for (JavacDef def : defs) {
if (def instanceof JavacDef.JavacClassDef) {
JavacRef.JavacClass sym = (JavacRef.JavacClass)def.getDefinedElement();
final LightRef.JavaLightClassRef aClass = writer.asClassUsage(sym);
definitions.add(aClass);
definitions.put(aClass, null);
final JavacRef[] superClasses = ((JavacDef.JavacClassDef)def).getSuperClasses();
final LightRef.JavaLightClassRef[] lightSuperClasses = new LightRef.JavaLightClassRef[superClasses.length];
for (int i = 0; i < superClasses.length; i++) {
JavacRef superClass = superClasses[i];
lightSuperClasses[i] = writer.asClassUsage(superClass);
}
for (JavacRef superClass : superClasses) {
LightRef.JavaLightClassRef superClassRef = writer.asClassUsage(superClass);
writer.writeHierarchy(fileId, aClass, lightSuperClasses);
Collection<LightRef> children = backwardHierarchyMap.get(superClassRef);
if (children == null) {
backwardHierarchyMap.put(superClassRef, children = new SmartList<LightRef>());
}
children.add(aClass);
}
}
else if (def instanceof JavacDef.JavacFunExprDef) {
final LightRef.JavaLightClassRef functionalType = writer.asClassUsage(def.getDefinedElement());
int id = funExprId++;
LightRef.JavaLightFunExprDef result = new LightRef.JavaLightFunExprDef(id);
definitions.add(result);
writer.writeHierarchy(fileId, result, functionalType);
definitions.put(result, null);
ContainerUtil.getOrCreate(backwardHierarchyMap, functionalType, new Factory<Collection<LightRef>>() {
@Override
public Collection<LightRef> create() {
return new SmartList<LightRef>();
}
}).add(result);
}
}
writer.writeClassDefinitions(fileId, definitions);
writer.writeReferences(fileId, refs);
Map<LightRef, Void> convertedRefs = new HashMap<LightRef, Void>(refs.size());
for (JavacRef ref : refs) {
LightRef key = writer.enumerateNames(ref);
if (key != null) {
convertedRefs.put(key, null);
}
}
writer.writeData(fileId, new CompiledFileData(backwardHierarchyMap, convertedRefs, definitions));
}
}

View File

@@ -15,14 +15,12 @@
*/
package org.jetbrains.jps.backwardRefs;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.util.Function;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.InvertedIndex;
import com.sun.tools.javac.code.Flags;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.backwardRefs.index.CompiledFileData;
import org.jetbrains.jps.builders.java.JavaBuilderUtil;
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.incremental.CompileContext;
@@ -34,7 +32,6 @@ import org.jetbrains.jps.model.java.compiler.JavaCompilers;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Set;
import static com.sun.tools.javac.code.Flags.PRIVATE;
@@ -44,24 +41,9 @@ public class BackwardReferenceIndexWriter {
private static volatile BackwardReferenceIndexWriter ourInstance;
private final CompilerBackwardReferenceIndex myIndex;
private final boolean myRebuild;
private final LowMemoryWatcher myMemWatcher;
private final Object myCloseLock = new Object();
private boolean myClosed;
private BackwardReferenceIndexWriter(CompilerBackwardReferenceIndex index, boolean rebuild) {
private BackwardReferenceIndexWriter(CompilerBackwardReferenceIndex index) {
myIndex = index;
myRebuild = rebuild;
myMemWatcher = LowMemoryWatcher.register(new Runnable() {
@Override
public void run() {
synchronized (myCloseLock) {
if (!myClosed) {
myIndex.flush();
}
}
}
});
}
public static void closeIfNeed() {
@@ -96,7 +78,7 @@ public class BackwardReferenceIndexWriter {
}
if (CompilerBackwardReferenceIndex.exist(buildDir) || isRebuild) {
ourInstance = new BackwardReferenceIndexWriter(new CompilerBackwardReferenceIndex(buildDir), isRebuild);
ourInstance = new BackwardReferenceIndexWriter(new CompilerBackwardReferenceIndex(buildDir));
}
} else {
CompilerBackwardReferenceIndex.removeIndexFiles(buildDir);
@@ -111,99 +93,15 @@ public class BackwardReferenceIndexWriter {
return new LightRef.JavaLightClassRef(id(aClass, myIndex.getByteSeqEum()));
}
synchronized void processDeletedFiles(Collection<String> paths) {
for (String path : paths) {
final int deletedFileId = enumeratePath(new File(path).getPath());
//remove from reference maps
final Collection<LightRef> refs = myIndex.getReferenceMap().get(deletedFileId);
if (refs != null) {
for (LightRef ref : refs) {
myIndex.getBackwardReferenceMap().removeFrom(ref, deletedFileId);
}
}
myIndex.getReferenceMap().remove(deletedFileId);
//remove from definition & hierarchy maps
final Collection<LightRef> definedClasses = myIndex.getClassDefinitionMap().get(deletedFileId);
removeClassesFromHierarchy(deletedFileId, definedClasses);
myIndex.getClassDefinitionMap().remove(deletedFileId);
void processDeletedFiles(Collection<String> files) {
for (String file : files) {
writeData(enumeratePath(file), null);
}
}
synchronized void writeClassDefinitions(int fileId, Collection<LightRef> classes) {
if (myRebuild) {
directlyWriteClassDefinitions(fileId, classes);
} else {
updateClassDefinitions(fileId, classes);
}
}
private void updateClassDefinitions(int fileId, Collection<LightRef> classes) {
final Collection<LightRef> oldDefs = myIndex.getClassDefinitionMap().get(fileId);
final Collection<LightRef> oldDefsCopy = oldDefs == null ? null : new THashSet<LightRef>(oldDefs);
myIndex.getClassDefinitionMap().replace(fileId, classes);
for (LightRef aClass : classes) {
if (oldDefsCopy == null || !oldDefsCopy.remove(aClass)) {
myIndex.getBackwardClassDefinitionMap().put(aClass, fileId);
}
}
removeClassesFromHierarchy(fileId, oldDefsCopy);
}
private void directlyWriteClassDefinitions(int fileId, Collection<LightRef> classes) {
myIndex.getClassDefinitionMap().put(fileId, classes);
for (LightRef aClass : classes) {
myIndex.getBackwardClassDefinitionMap().put(aClass, fileId);
}
}
synchronized void writeReferences(int fileId, Collection<? extends JavacRef> refs) {
final ByteArrayEnumerator byteSeqEum = myIndex.getByteSeqEum();
final Set<LightRef> usages = ContainerUtil.map2SetNotNull(refs, new Function<JavacRef, LightRef>() {
@Override
public LightRef fun(JavacRef ref) {
return enumerateNames(ref, byteSeqEum);
}
});
if (myRebuild) {
for (LightRef usage : usages) {
myIndex.getBackwardReferenceMap().put(usage, fileId);
myIndex.getReferenceMap().put(fileId, usage);
}
}
else {
updateReferenceIndicesIncrementally(fileId, usages);
}
}
private void updateReferenceIndicesIncrementally(int fileId, Collection<LightRef> usages) {
final Collection<LightRef> rawOldUsages = myIndex.getReferenceMap().get(fileId);
Collection<LightRef> oldUsages = rawOldUsages == null ? null : new THashSet<LightRef>(rawOldUsages);
for (LightRef usage : usages) {
if (oldUsages == null || !oldUsages.remove(usage)) {
myIndex.getBackwardReferenceMap().put(usage, fileId);
myIndex.getReferenceMap().put(fileId, usage);
}
}
if (oldUsages != null && !oldUsages.isEmpty()) {
myIndex.getReferenceMap().removeAll(fileId, oldUsages);
for (LightRef usage : oldUsages) {
myIndex.getBackwardReferenceMap().removeFrom(usage, fileId);
}
}
}
synchronized void writeHierarchy(int fileId, LightRef aClass, LightRef.JavaLightClassRef... supers) {
CompilerBackwardReferenceIndex.LightDefinition def = new CompilerBackwardReferenceIndex.LightDefinition(aClass, fileId);
if (myRebuild) {
directlyWriteHierarchyIndices(def, supers);
}
else {
updateHierarchyIndicesIncrementally(def, supers);
void writeData(int id, CompiledFileData d) {
for (InvertedIndex<?, ?, CompiledFileData> index : myIndex.getIndices()) {
index.update(id, d).compute();
}
}
@@ -217,73 +115,12 @@ public class BackwardReferenceIndexWriter {
}
private void close() {
synchronized (myCloseLock) {
myClosed = true;
myMemWatcher.stop();
myIndex.close();
}
}
private void directlyWriteHierarchyIndices(CompilerBackwardReferenceIndex.LightDefinition classId, LightRef.JavaLightClassRef[] superIds) {
for (LightRef.JavaLightClassRef superId : superIds) {
myIndex.getBackwardHierarchyMap().put(superId, classId);
myIndex.getHierarchyMap().put(classId, superId);
}
}
private void updateHierarchyIndicesIncrementally(final CompilerBackwardReferenceIndex.LightDefinition classId, LightRef.JavaLightClassRef[] superIds) {
final Collection<LightRef> rawOldSupers = myIndex.getHierarchyMap().get(classId);
Set<LightRef> oldSuperClasses;
if (rawOldSupers == null) {
oldSuperClasses = null;
}
else {
if (superIds.length == rawOldSupers.size()) {
boolean needUpdate = false;
for (LightRef.JavaLightClassRef id : superIds) {
if (!rawOldSupers.contains(id)) {
needUpdate = true;
break;
}
}
if (!needUpdate) return;
}
oldSuperClasses = new THashSet<LightRef>(rawOldSupers);
}
for (LightRef.JavaLightClassRef superId: superIds) {
if (oldSuperClasses == null || !oldSuperClasses.remove(superId)) {
myIndex.getBackwardHierarchyMap().put(superId, classId);
myIndex.getHierarchyMap().put(classId, superId);
}
}
if (oldSuperClasses != null && !oldSuperClasses.isEmpty()) {
myIndex.getHierarchyMap().removeAll(classId, oldSuperClasses);
for (LightRef anOldClass : oldSuperClasses) {
myIndex.getBackwardHierarchyMap().removeFrom(anOldClass, classId);
}
}
}
private void removeClassesFromHierarchy(int deletedFileId, Collection<LightRef> definedClasses) {
if (definedClasses != null) {
for (LightRef aClass : definedClasses) {
myIndex.getBackwardClassDefinitionMap().removeFrom(aClass, deletedFileId);
final CompilerBackwardReferenceIndex.LightDefinition def =
new CompilerBackwardReferenceIndex.LightDefinition(aClass, deletedFileId);
final Collection<LightRef> superClasses = myIndex.getHierarchyMap().get(def);
if (superClasses != null) {
for (LightRef superClass : superClasses) {
myIndex.getBackwardHierarchyMap().removeFrom(superClass, def);
}
}
myIndex.getHierarchyMap().remove(def);
}
}
myIndex.close();
}
@Nullable
private static LightRef enumerateNames(JavacRef ref, ByteArrayEnumerator byteArrayEnumerator) {
LightRef enumerateNames(JavacRef ref) {
ByteArrayEnumerator byteArrayEnumerator = myIndex.getByteSeqEum();
if (ref instanceof JavacRef.JavacClass) {
if (!isPrivate(ref) && !((JavacRef.JavacClass)ref).isAnonymous()) {
return new LightRef.JavaLightClassRef(id(ref, byteArrayEnumerator));

View File

@@ -15,50 +15,53 @@
*/
package org.jetbrains.jps.backwardRefs;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.indexing.*;
import com.intellij.util.indexing.impl.*;
import com.intellij.util.io.*;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.java.dependencyView.CloseableMaplet;
import org.jetbrains.jps.builders.java.dependencyView.CollectionFactory;
import org.jetbrains.jps.builders.java.dependencyView.IntObjectPersistentMultiMaplet;
import org.jetbrains.jps.builders.java.dependencyView.ObjectObjectPersistentMultiMaplet;
import org.jetbrains.jps.backwardRefs.index.CompiledFileData;
import org.jetbrains.jps.backwardRefs.index.CompilerIndices;
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.*;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class CompilerBackwardReferenceIndex {
private static final int VERSION = 0;
private final static String FILE_ENUM_TAB = "file.path.enum.tab";
private final static String INCOMPLETE_FILES_TAB = "incomplete.files.tab";
private final static String USAGES_TAB = "refs.tab";
private final static String BACK_USAGES_TAB = "back.refs.tab";
private final static String HIERARCHY_TAB = "hierarchy.tab";
private final static String BACK_HIERARCHY_TAB = "back.hierarchy.tab";
private final static String CLASS_DEF_TAB = "class.def.tab";
private final static String BACK_CLASS_DEF_TAB = "back.class.def.tab";
public static final String VERSION_FILE = ".version";
private final IntObjectPersistentMultiMaplet<LightRef> myReferenceMap;
private final ObjectObjectPersistentMultiMaplet<LightDefinition, LightRef> myHierarchyMap;
private final ObjectObjectPersistentMultiMaplet<LightRef, Integer> myBackwardReferenceMap;
private final ObjectObjectPersistentMultiMaplet<LightRef, LightDefinition> myBackwardHierarchyMap;
private final ObjectObjectPersistentMultiMaplet<LightRef, Integer> myBackwardClassDefinitionMap;
private final IntObjectPersistentMultiMaplet<LightRef> myClassDefinitionMap;
private final static String NAME_ENUM_TAB = "name.tab";
private static final String VERSION_FILE = ".version";
private final Map<ID<?, ?>, InvertedIndex<?, ?, CompiledFileData>> myIndices;
private final ByteArrayEnumerator myNameEnumerator;
private final PersistentStringEnumerator myFilePathEnumerator;
private final File myIndicesDir;
private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() {
@Override
public void run() {
synchronized (myNameEnumerator) {
if (!myNameEnumerator.isClosed()) {
myNameEnumerator.force();
}
}
synchronized (myFilePathEnumerator) {
if (!myFilePathEnumerator.isClosed()) {
myFilePathEnumerator.force();
}
}
}
});
private volatile boolean myRebuildRequired;
public CompilerBackwardReferenceIndex(File buildDir) {
myIndicesDir = getIndexDir(buildDir);
@@ -67,7 +70,7 @@ public class CompilerBackwardReferenceIndex {
}
try {
if (versionDiffers(buildDir)) {
FileUtil.writeToFile(new File(myIndicesDir, VERSION_FILE), String.valueOf(VERSION));
FileUtil.writeToFile(new File(myIndicesDir, VERSION_FILE), String.valueOf(CompilerIndices.VERSION));
}
myFilePathEnumerator = new PersistentStringEnumerator(new File(myIndicesDir, FILE_ENUM_TAB)) {
@Override
@@ -76,68 +79,13 @@ public class CompilerBackwardReferenceIndex {
}
};
final KeyDescriptor<LightRef> lightUsageDescriptor = new LightRefDescriptor();
final KeyDescriptor<LightDefinition> defDescriptor = LightDefinition.createDescriptor(lightUsageDescriptor);
myIndices = new HashMap<ID<?, ?>, InvertedIndex<?, ?, CompiledFileData>>();
for (IndexExtension<LightRef, ?, CompiledFileData> indexExtension : CompilerIndices.getIndices()) {
//noinspection unchecked
myIndices.put(indexExtension.getName(), new CompilerMapReduceIndex(indexExtension, myIndicesDir));
}
myBackwardReferenceMap = new ObjectObjectPersistentMultiMaplet<LightRef, Integer>(new File(myIndicesDir, BACK_USAGES_TAB),
lightUsageDescriptor,
EnumeratorIntegerDescriptor.INSTANCE,
new CollectionFactory<Integer>() {
@Override
public Collection<Integer> create() {
return new THashSet<Integer>();
}
});
myBackwardHierarchyMap = new ObjectObjectPersistentMultiMaplet<LightRef, LightDefinition>(new File(myIndicesDir, BACK_HIERARCHY_TAB),
lightUsageDescriptor,
defDescriptor,
new CollectionFactory<LightDefinition>() {
@Override
public Collection<LightDefinition> create() {
return new THashSet<LightDefinition>();
}
});
myReferenceMap = new IntObjectPersistentMultiMaplet<LightRef>(new File(myIndicesDir, USAGES_TAB),
EnumeratorIntegerDescriptor.INSTANCE,
lightUsageDescriptor, new CollectionFactory<LightRef>() {
@Override
public Collection<LightRef> create() {
return new THashSet<LightRef>();
}
});
myHierarchyMap = new ObjectObjectPersistentMultiMaplet<LightDefinition, LightRef>(new File(myIndicesDir, HIERARCHY_TAB),
defDescriptor,
lightUsageDescriptor,
new CollectionFactory<LightRef>() {
@Override
public Collection<LightRef> create() {
return new THashSet<LightRef>();
}
});
myClassDefinitionMap = new IntObjectPersistentMultiMaplet<LightRef>(new File(myIndicesDir, CLASS_DEF_TAB),
EnumeratorIntegerDescriptor.INSTANCE,
lightUsageDescriptor,
new CollectionFactory<LightRef>() {
@Override
public Collection<LightRef> create() {
return new THashSet<LightRef>();
}
});
myBackwardClassDefinitionMap = new ObjectObjectPersistentMultiMaplet<LightRef, Integer>(new File(myIndicesDir, BACK_CLASS_DEF_TAB),
lightUsageDescriptor,
EnumeratorIntegerDescriptor.INSTANCE,
new CollectionFactory<Integer>() {
@Override
public Collection<Integer> create() {
return new THashSet<Integer>();
}
});
myNameEnumerator = new ByteArrayEnumerator(new File(myIndicesDir, INCOMPLETE_FILES_TAB));
myNameEnumerator = new ByteArrayEnumerator(new File(myIndicesDir, NAME_ENUM_TAB));
}
catch (IOException e) {
removeIndexFiles(myIndicesDir);
@@ -145,34 +93,13 @@ public class CompilerBackwardReferenceIndex {
}
}
@NotNull
public ObjectObjectPersistentMultiMaplet<LightRef, Integer> getBackwardReferenceMap() {
return myBackwardReferenceMap;
Collection<InvertedIndex<?, ?, CompiledFileData>> getIndices() {
return myIndices.values();
}
@NotNull
public ObjectObjectPersistentMultiMaplet<LightRef, LightDefinition> getBackwardHierarchyMap() {
return myBackwardHierarchyMap;
}
@NotNull
public IntObjectPersistentMultiMaplet<LightRef> getReferenceMap() {
return myReferenceMap;
}
@NotNull
public ObjectObjectPersistentMultiMaplet<LightDefinition, LightRef> getHierarchyMap() {
return myHierarchyMap;
}
@NotNull
public ObjectObjectPersistentMultiMaplet<LightRef, Integer> getBackwardClassDefinitionMap() {
return myBackwardClassDefinitionMap;
}
@NotNull
public IntObjectPersistentMultiMaplet<LightRef> getClassDefinitionMap() {
return myClassDefinitionMap;
public <K, V> InvertedIndex<K, V, CompiledFileData> get(ID<K, V> key) {
//noinspection unchecked
return (InvertedIndex<K, V, CompiledFileData>)myIndices.get(key);
}
@NotNull
@@ -186,32 +113,22 @@ public class CompilerBackwardReferenceIndex {
}
public void close() {
myLowMemoryWatcher.stop();
final CommonProcessors.FindFirstProcessor<BuildDataCorruptedException> exceptionProc =
new CommonProcessors.FindFirstProcessor<BuildDataCorruptedException>();
close(myFilePathEnumerator, exceptionProc);
close(myBackwardHierarchyMap, exceptionProc);
close(myBackwardReferenceMap, exceptionProc);
close(myBackwardClassDefinitionMap, exceptionProc);
close(myHierarchyMap, exceptionProc);
close(myReferenceMap, exceptionProc);
close(myClassDefinitionMap, exceptionProc);
close(myNameEnumerator, exceptionProc);
for (InvertedIndex<?, ?, CompiledFileData> index : myIndices.values()) {
close(index, exceptionProc);
}
final BuildDataCorruptedException exception = exceptionProc.getFoundValue();
if (exception != null) {
removeIndexFiles(myIndicesDir);
throw exception;
}
}
void flush() {
myBackwardHierarchyMap.flush(false);
myBackwardReferenceMap.flush(false);
myBackwardClassDefinitionMap.flush(false);
myHierarchyMap.flush(false);
myReferenceMap.flush(false);
myClassDefinitionMap.flush(false);
myNameEnumerator.force();
myFilePathEnumerator.force();
if (myRebuildRequired) {
removeIndexFiles(myIndicesDir);
}
}
public static void removeIndexFiles(File buildDir) {
@@ -232,89 +149,78 @@ public class CompilerBackwardReferenceIndex {
public static boolean versionDiffers(@NotNull File buildDir) {
File versionFile = new File(getIndexDir(buildDir), VERSION_FILE);
try {
return Integer.parseInt(FileUtil.loadFile(versionFile)) != VERSION;
return Integer.parseInt(FileUtil.loadFile(versionFile)) != CompilerIndices.VERSION;
}
catch (final IOException e) {
return true;
}
}
private static void close(Closeable closeable, Processor<BuildDataCorruptedException> exceptionProcessor) {
private static void close(InvertedIndex<?, ?, CompiledFileData> index, CommonProcessors.FindFirstProcessor<BuildDataCorruptedException> exceptionProcessor) {
try {
closeable.close();
}
catch (IOException e) {
exceptionProcessor.process(new BuildDataCorruptedException(e));
}
}
private static void close(CloseableMaplet closeable, Processor<BuildDataCorruptedException> exceptionProcessor) {
try {
closeable.close();
index.dispose();
}
catch (BuildDataCorruptedException e) {
exceptionProcessor.process(e);
}
}
public static class LightDefinition {
private final LightRef myUsage;
private final int myFileId;
LightDefinition(LightRef usage, int id) {
myUsage = usage;
myFileId = id;
}
public LightRef getRef() {
return myUsage;
}
public int getFileId() {
return myFileId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LightDefinition that = (LightDefinition)o;
if (!myUsage.equals(that.myUsage)) return false;
if (myFileId != that.myFileId) return false;
return true;
}
@Override
public int hashCode() {
return myUsage.hashCode();
}
private static KeyDescriptor<LightDefinition> createDescriptor(final DataExternalizer<LightRef> usageDataExternalizer) {
return new KeyDescriptor<LightDefinition>() {
@Override
public int getHashCode(LightDefinition value) {
return value.hashCode();
}
@Override
public boolean isEqual(LightDefinition val1, LightDefinition val2) {
return val1.equals(val2);
}
@Override
public void save(@NotNull DataOutput out, LightDefinition value) throws IOException {
usageDataExternalizer.save(out, value.getRef());
EnumeratorIntegerDescriptor.INSTANCE.save(out, value.getFileId());
}
@Override
public LightDefinition read(@NotNull DataInput in) throws IOException {
return new LightDefinition(usageDataExternalizer.read(in), EnumeratorIntegerDescriptor.INSTANCE.read(in));
}
};
private static void close(Closeable closeable, Processor<BuildDataCorruptedException> exceptionProcessor) {
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (closeable) {
try {
closeable.close();
}
catch (IOException e) {
exceptionProcessor.process(new BuildDataCorruptedException(e));
}
}
}
class CompilerMapReduceIndex<Key, Value> extends MapReduceIndex<Key, Value, CompiledFileData> {
public CompilerMapReduceIndex(@NotNull final IndexExtension<Key, Value, CompiledFileData> extension,
@NotNull final File indexDir)
throws IOException {
super(extension,
createIndexStorage(extension.getKeyDescriptor(), extension.getValueExternalizer(), extension.getName(), indexDir),
new MapBasedForwardIndex<Key, Value>(extension) {
@NotNull
@Override
public PersistentHashMap<Integer, Collection<Key>> createMap() throws IOException {
ID<Key, Value> id = extension.getName();
return new PersistentHashMap<Integer, Collection<Key>>(new File(indexDir, id + ".inputs"),
EnumeratorIntegerDescriptor.INSTANCE,
new InputIndexDataExternalizer<Key>(extension.getKeyDescriptor(),
id));
}
});
}
@Override
public void checkCanceled() {
}
@Override
protected void requestRebuild(Exception e) {
myRebuildRequired = true;
throw new BuildDataCorruptedException(e);
}
}
private static <Key, Value> IndexStorage<Key, Value> createIndexStorage(@NotNull KeyDescriptor<Key> keyDescriptor,
@NotNull DataExternalizer<Value> valueExternalizer,
@NotNull ID<Key, Value> indexId,
@NotNull File indexDir) throws IOException {
return new MapIndexStorage<Key, Value>(new File(indexDir, indexId.toString()),
keyDescriptor,
valueExternalizer,
16 * 1024,
false) {
@Override
public void checkCanceled() {
//TODO
}
};
}
}

View File

@@ -26,7 +26,9 @@ import java.io.IOException;
import static org.jetbrains.jps.backwardRefs.LightRef.*;
final class LightRefDescriptor implements KeyDescriptor<LightRef>, DifferentSerializableBytesImplyNonEqualityPolicy {
public final class LightRefDescriptor implements KeyDescriptor<LightRef>, DifferentSerializableBytesImplyNonEqualityPolicy {
public static final LightRefDescriptor INSTANCE = new LightRefDescriptor();
@Override
public int getHashCode(LightRef value) {
return value.hashCode();

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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 org.jetbrains.jps.backwardRefs.index;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.backwardRefs.LightRef;
import java.util.Collection;
import java.util.Map;
public class CompiledFileData {
private final Map<LightRef, Collection<LightRef>> myBackwardHierarchyMap;
private final Map<LightRef, Void> myReferences;
private final Map<LightRef, Void> myDefinitions;
public CompiledFileData(@NotNull Map<LightRef, Collection<LightRef>> backwardHierarchyMap,
@NotNull Map<LightRef, Void> references,
@NotNull Map<LightRef, Void> definitions) {
myBackwardHierarchyMap = backwardHierarchyMap;
myReferences = references;
myDefinitions = definitions;
}
@NotNull
public Map<LightRef, Collection<LightRef>> getBackwardHierarchy() {
return myBackwardHierarchyMap;
}
@NotNull
public Map<LightRef, Void> getReferences() {
return myReferences;
}
@NotNull
public Map<LightRef, Void> getDefinitions() {
return myDefinitions;
}
}

View File

@@ -0,0 +1,176 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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 org.jetbrains.jps.backwardRefs.index;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.util.ThrowableConsumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.DataIndexer;
import com.intellij.util.indexing.ID;
import com.intellij.util.indexing.IndexExtension;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.DataInputOutputUtil;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.io.VoidDataExternalizer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.backwardRefs.LightRef;
import org.jetbrains.jps.backwardRefs.LightRefDescriptor;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class CompilerIndices {
//TODO manage version separately
public final static int VERSION = 0;
public final static ID<LightRef, Void> BACK_USAGES = ID.create("back.refs");
public final static ID<LightRef, Collection<LightRef>> BACK_HIERARCHY = ID.create("back.hierarchy");
public final static ID<LightRef, Void> BACK_CLASS_DEF = ID.create("back.class.def");
public static List<IndexExtension<LightRef, ?, CompiledFileData>> getIndices() {
return ContainerUtil.list(createBackwardClassDefinitionExtension(), createBackwardUsagesExtension(), createBackwardHierarchyExtension());
}
private static IndexExtension<LightRef, Void, CompiledFileData> createBackwardUsagesExtension() {
return new IndexExtension<LightRef, Void, CompiledFileData>() {
@Override
public int getVersion() {
return VERSION;
}
@NotNull
public ID<LightRef, Void> getName() {
return BACK_USAGES;
}
@NotNull
public DataIndexer<LightRef, Void, CompiledFileData> getIndexer() {
return new DataIndexer<LightRef, Void, CompiledFileData>() {
@NotNull
@Override
public Map<LightRef, Void> map(@NotNull CompiledFileData inputData) {
return inputData.getReferences();
}
};
}
@NotNull
public KeyDescriptor<LightRef> getKeyDescriptor() {
return LightRefDescriptor.INSTANCE;
}
@NotNull
public DataExternalizer<Void> getValueExternalizer() {
return VoidDataExternalizer.INSTANCE;
}
};
}
private static IndexExtension<LightRef, Collection<LightRef>, CompiledFileData> createBackwardHierarchyExtension() {
return new IndexExtension<LightRef, Collection<LightRef>, CompiledFileData>() {
@Override
public int getVersion() {
return VERSION;
}
@NotNull
public ID<LightRef, Collection<LightRef>> getName() {
return BACK_HIERARCHY;
}
@NotNull
public DataIndexer<LightRef, Collection<LightRef>, CompiledFileData> getIndexer() {
return new DataIndexer<LightRef, Collection<LightRef>, CompiledFileData>() {
@NotNull
@Override
public Map<LightRef, Collection<LightRef>> map(@NotNull CompiledFileData inputData) {
return inputData.getBackwardHierarchy();
}
};
}
@NotNull
public KeyDescriptor<LightRef> getKeyDescriptor() {
return LightRefDescriptor.INSTANCE;
}
@NotNull
public DataExternalizer<Collection<LightRef>> getValueExternalizer() {
return new DataExternalizer<Collection<LightRef>>() {
@Override
public void save(@NotNull final DataOutput out, Collection<LightRef> value) throws IOException {
DataInputOutputUtil.writeSeq(out, value, new ThrowableConsumer<LightRef, IOException>() {
@Override
public void consume(LightRef lightRef) throws IOException {
LightRefDescriptor.INSTANCE.save(out, lightRef);
}
});
}
@Override
public Collection<LightRef> read(@NotNull final DataInput in) throws IOException {
return DataInputOutputUtil.readSeq(in, new ThrowableComputable<LightRef, IOException>() {
@Override
public LightRef compute() throws IOException {
return LightRefDescriptor.INSTANCE.read(in);
}
});
}
};
}
};
}
private static IndexExtension<LightRef, Void, CompiledFileData> createBackwardClassDefinitionExtension() {
return new IndexExtension<LightRef, Void, CompiledFileData>() {
@Override
public int getVersion() {
return VERSION;
}
@NotNull
public ID<LightRef, Void> getName() {
return BACK_CLASS_DEF;
}
@NotNull
public DataIndexer<LightRef, Void, CompiledFileData> getIndexer() {
return new DataIndexer<LightRef, Void, CompiledFileData>() {
@NotNull
@Override
public Map<LightRef, Void> map(@NotNull CompiledFileData inputData) {
return inputData.getDefinitions();
}
};
}
@NotNull
public KeyDescriptor<LightRef> getKeyDescriptor() {
return LightRefDescriptor.INSTANCE;
}
@NotNull
public DataExternalizer<Void> getValueExternalizer() {
return VoidDataExternalizer.INSTANCE;
}
};
}
}

View File

@@ -24,7 +24,7 @@ import java.io.IOException;
* @author nik
*/
public class BuildDataCorruptedException extends RuntimeException {
public BuildDataCorruptedException(IOException cause) {
public BuildDataCorruptedException(Exception cause) {
super(cause);
}

View File

@@ -18,12 +18,17 @@ package org.jetbrains.references
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.util.PathUtil
import com.intellij.util.indexing.ID
import com.intellij.util.indexing.impl.MapIndexStorage
import com.intellij.util.indexing.impl.MapReduceIndex
import com.intellij.util.io.PersistentStringEnumerator
import com.sun.tools.javac.util.Convert
import org.jetbrains.jps.backwardRefs.BackwardReferenceIndexWriter
import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator
import org.jetbrains.jps.backwardRefs.CompilerBackwardReferenceIndex
import org.jetbrains.jps.backwardRefs.LightRef
import org.jetbrains.jps.backwardRefs.index.CompiledFileData
import org.jetbrains.jps.backwardRefs.index.CompilerIndices
import org.jetbrains.jps.builders.JpsBuildTestCase
import org.jetbrains.jps.builders.TestProjectBuilderLogger
import org.jetbrains.jps.builders.logging.BuildLoggingManager
@@ -83,14 +88,17 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
val result = StringBuilder()
result.append("Backward Hierarchy:\n")
val hierarchyText = mutableListOf<String>()
index.backwardHierarchyMap.forEachEntry { superClass, inheritors ->
storage(index, CompilerIndices.BACK_HIERARCHY).processKeys { superClass ->
val superClassName = superClass.asText(nameEnumerator)
val inheritorsText = mutableListOf<String>()
inheritors.forEach { id ->
inheritorsText.add(id.asText(nameEnumerator))
index[CompilerIndices.BACK_HIERARCHY].getData(superClass).forEach { i, children ->
children.mapTo(inheritorsText) { it.asText(nameEnumerator) }
true
}
if (!inheritorsText.isEmpty()) {
inheritorsText.sort()
hierarchyText.add(superClassName + " -> " + inheritorsText.joinToString(separator = " "))
}
inheritorsText.sort()
hierarchyText.add(superClassName + " -> " + inheritorsText.joinToString(separator = " "))
true
}
hierarchyText.sort()
@@ -98,13 +106,20 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
result.append("\n\nBackward References:\n")
val referencesText = mutableListOf<String>()
index.backwardReferenceMap.forEachEntry { usage, files ->
storage(index, CompilerIndices.BACK_USAGES).processKeys { usage ->
val referents = mutableListOf<String>()
files.forEach { id ->
referents.add(id.asFileName(fileEnumerator))
val valueIt = index[CompilerIndices.BACK_USAGES].getData(usage).valueIterator
while (valueIt.hasNext()) {
valueIt.next()
val files = valueIt.inputIdsIterator
while (files.hasNext()) {
referents.add(files.next().asFileName(fileEnumerator))
}
}
if (!referents.isEmpty()) {
referents.sort()
referencesText.add(usage.asText(nameEnumerator) + " in " + referents.joinToString(separator = " "))
}
referents.sort()
referencesText.add(usage.asText(nameEnumerator) + " in " + referents.joinToString(separator = " "))
true
}
referencesText.sort()
@@ -112,13 +127,20 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
result.append("\n\nClass Definitions:\n")
val classDefs = mutableListOf<String>()
index.backwardClassDefinitionMap.forEachEntry { usage, files ->
storage(index, CompilerIndices.BACK_CLASS_DEF).processKeys { usage ->
val definitionFiles = mutableListOf<String>()
files.forEach { id ->
definitionFiles.add(id.asFileName(fileEnumerator))
val valueIt = index[CompilerIndices.BACK_CLASS_DEF].getData(usage).valueIterator
while (valueIt.hasNext()) {
valueIt.next()
val files = valueIt.inputIdsIterator
while (files.hasNext()) {
definitionFiles.add(files.next().asFileName(fileEnumerator))
}
}
if (!definitionFiles.isEmpty()) {
definitionFiles.sort()
classDefs.add(usage.asText(nameEnumerator) + " in " + definitionFiles.joinToString(separator = " "))
}
definitionFiles.sort()
classDefs.add(usage.asText(nameEnumerator) + " in " + definitionFiles.joinToString(separator = " "))
true
}
classDefs.sort()
@@ -130,12 +152,12 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
}
}
private fun <K, V> storage(index: CompilerBackwardReferenceIndex, id: ID<K, V>) = (index[id] as MapReduceIndex<K, V, CompiledFileData>).storage as MapIndexStorage<K, V>
private fun getTestDataPath() = testDataRootPath + "/" + getTestName(true) + "/"
private fun Int.asName(byteArrayEnumerator: ByteArrayEnumerator): String = Convert.utf2string(byteArrayEnumerator.valueOf(this))
private fun CompilerBackwardReferenceIndex.LightDefinition.asText(byteArrayEnumerator: ByteArrayEnumerator) = this.ref.asText(byteArrayEnumerator)
private fun LightRef.asText(byteArrayEnumerator: ByteArrayEnumerator): String =
when (this) {
is LightRef.JavaLightMethodRef -> "${this.owner.name.asName(byteArrayEnumerator)}.${this.name.asName(byteArrayEnumerator)}(${this.parameterCount})"