mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-17 16:19:58 +07:00
stub hierarchy: don't process duplicate units
This commit is contained in:
@@ -20,6 +20,8 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
|
||||
import com.intellij.psi.stubsHierarchy.stubs.Unit;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class HierarchyService {
|
||||
private NameEnvironment myNameEnvironment;
|
||||
@@ -37,11 +39,12 @@ public class HierarchyService {
|
||||
clear();
|
||||
}
|
||||
|
||||
public void processUnit(IndexTree.Unit unit) {
|
||||
Unit compUnit = Translator.translate(myNameEnvironment, unit);
|
||||
if (compUnit != null) {
|
||||
myStubEnter.unitEnter(compUnit);
|
||||
}
|
||||
void processUnit(@NotNull Unit compUnit) {
|
||||
myStubEnter.unitEnter(compUnit);
|
||||
}
|
||||
|
||||
@Nullable Unit compact(@NotNull IndexTree.Unit unit) {
|
||||
return Translator.translate(myNameEnvironment, unit);
|
||||
}
|
||||
|
||||
public void connect1() {
|
||||
|
||||
+48
-54
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.stubsHierarchy.impl;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -24,107 +24,101 @@ import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.ui.MessageDialogBuilder;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
|
||||
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaStubIndexKeys;
|
||||
import com.intellij.psi.stubs.StubIndex;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.psi.stubsHierarchy.stubs.Unit;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class SingleClassHierarchyBuilder {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubsHierarchy.HierarchyBuilder");
|
||||
private static final boolean TEST_MEMORY_USAGE = false;
|
||||
|
||||
public static void build(@NotNull Project project) {
|
||||
ProgressManager progress = ProgressManager.getInstance();
|
||||
progress.runProcessWithProgressSynchronously(new BuildSingleClassHierarchy(project), "Building Hierarchy", false, project);
|
||||
}
|
||||
|
||||
private static class UnitProcessor implements Processor<IndexTree.Unit> {
|
||||
private final Project myProject;
|
||||
private final HierarchyService myHierarchyService;
|
||||
private final ProjectFileIndex myProjectIndex;
|
||||
boolean isInSourceMode;
|
||||
|
||||
private UnitProcessor(Project project, HierarchyService hierarchyService) {
|
||||
myProject = project;
|
||||
myHierarchyService = hierarchyService;
|
||||
myProjectIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
|
||||
private static final TObjectHashingStrategy<Unit> UNIT_HASHING_STRATEGY = new TObjectHashingStrategy<Unit>() {
|
||||
@Override
|
||||
public int computeHashCode(Unit object) {
|
||||
return object.myClasses[0].myClassAnchor.myFileId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(IndexTree.Unit unit) {
|
||||
VirtualFile file = PersistentFS.getInstance().findFileById(unit.myFileId);
|
||||
if (file == null) {
|
||||
return true;
|
||||
}
|
||||
boolean process = isInSourceMode ? myProjectIndex.isInSourceContent(file) : myProjectIndex.isInLibraryClasses(file);
|
||||
if (process) {
|
||||
myHierarchyService.processUnit(unit);
|
||||
}
|
||||
return true;
|
||||
public boolean equals(Unit o1, Unit o2) {
|
||||
return computeHashCode(o1) == computeHashCode(o2);
|
||||
}
|
||||
};
|
||||
|
||||
public static void build(@NotNull Project project) {
|
||||
ProgressManager progress = ProgressManager.getInstance();
|
||||
progress.runProcessWithProgressSynchronously(() -> ReadAction.run(() -> new BuildSingleClassHierarchy(project).run()),
|
||||
"Building Hierarchy", false, project);
|
||||
}
|
||||
|
||||
private static class BuildSingleClassHierarchy implements Runnable {
|
||||
Project myProject;
|
||||
private ProjectFileIndex myFileIndex;
|
||||
|
||||
BuildSingleClassHierarchy(Project project) {
|
||||
myProject = project;
|
||||
myFileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HierarchyService service = HierarchyService.instance(myProject);
|
||||
if (service.getSingleClassHierarchy() != null) {
|
||||
return;
|
||||
}
|
||||
service.clear();
|
||||
|
||||
LOG.info("BuildHierarchy started");
|
||||
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
|
||||
final double classes = 0.3;
|
||||
final double completeClasses = 0.1;
|
||||
final double sources = 0.3;
|
||||
|
||||
final UnitProcessor processor = new UnitProcessor(myProject, service);
|
||||
|
||||
// 1. entering classes
|
||||
LOG.info("read classes start");
|
||||
indicator.setText("Reading classes");
|
||||
ApplicationManager.getApplication().runReadAction(() -> {
|
||||
StubIndex.getInstance().processAllKeys(JavaStubIndexKeys.UNITS, myProject, processor);
|
||||
});
|
||||
indicator.setFraction(classes);
|
||||
processUnits(service, false);
|
||||
indicator.setFraction(0.3);
|
||||
testMemory("0");
|
||||
|
||||
// 2. completing classes
|
||||
LOG.info("complete classes start");
|
||||
indicator.setText("Completing classes");
|
||||
service.connect1();
|
||||
indicator.setFraction(classes + completeClasses);
|
||||
indicator.setFraction(0.4);
|
||||
testMemory("1");
|
||||
|
||||
// 3. reading sources
|
||||
LOG.info("read sources start");
|
||||
indicator.setText("Reading sources");
|
||||
processor.isInSourceMode = true;
|
||||
ApplicationManager.getApplication().runReadAction(() -> {
|
||||
StubIndex.getInstance().processAllKeys(JavaStubIndexKeys.UNITS, myProject, processor);
|
||||
});
|
||||
indicator.setFraction(classes + completeClasses + sources);
|
||||
processUnits(service, true);
|
||||
indicator.setFraction(0.7);
|
||||
|
||||
// 4. completing sources
|
||||
indicator.setText("Completing sources");
|
||||
service.complete2();
|
||||
LOG.info("Complete end");
|
||||
testMemory("2");
|
||||
indicator.setFraction(0.9);
|
||||
|
||||
// 5. connect subtypes
|
||||
indicator.setText("Connecting subtypes");
|
||||
service.connectSubtypes();
|
||||
LOG.info("Subtypes connected");
|
||||
indicator.setFraction(1);
|
||||
}
|
||||
|
||||
private void processUnits(HierarchyService service, final boolean sourceMode) {
|
||||
Set<Unit> result = new THashSet<>(UNIT_HASHING_STRATEGY);
|
||||
StubIndex.getInstance().processAllKeys(JavaStubIndexKeys.UNITS, myProject, unit -> {
|
||||
Unit compact = shouldProcess(sourceMode, unit.myFileId) ? service.compact(unit) : null;
|
||||
if (compact != null && compact.myClasses.length > 0) {
|
||||
result.remove(compact); // there can be several (outdated) stub keys for the same file id, only the last one counts
|
||||
result.add(compact);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
result.forEach(service::processUnit);
|
||||
}
|
||||
|
||||
private boolean shouldProcess(boolean sourceMode, final int fileId) {
|
||||
VirtualFile file = PersistentFS.getInstance().findFileById(fileId);
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
return sourceMode ? myFileIndex.isInSourceContent(file) : myFileIndex.isInLibraryClasses(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user