mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DirectoryInfo made immutable for less memory
This commit is contained in:
@@ -32,12 +32,12 @@ import com.intellij.testFramework.IdeaTestCase;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
@@ -337,20 +337,20 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
VirtualFile output1 = myModule1Dir.createChildDirectory(this, "output1");
|
||||
VirtualFile output2 = myModule1Dir.createChildDirectory(this, "output2");
|
||||
|
||||
assertNotNull(myIndex.getInfoForDirectory(output1));
|
||||
assertNotNull(myIndex.getInfoForDirectory(output2));
|
||||
checkInfoNotNull(output1);
|
||||
checkInfoNotNull(output2);
|
||||
|
||||
getCompilerProjectExtension().setCompilerOutputUrl(output1.getUrl());
|
||||
fireRootsChanged();
|
||||
|
||||
assertNull(myIndex.getInfoForDirectory(output1));
|
||||
assertNotNull(myIndex.getInfoForDirectory(output2));
|
||||
checkInfoNull(output1);
|
||||
checkInfoNotNull(output2);
|
||||
|
||||
getCompilerProjectExtension().setCompilerOutputUrl(output2.getUrl());
|
||||
fireRootsChanged();
|
||||
|
||||
assertNotNull(myIndex.getInfoForDirectory(output1));
|
||||
assertNull(myIndex.getInfoForDirectory(output2));
|
||||
checkInfoNotNull(output1);
|
||||
checkInfoNull(output2);
|
||||
}
|
||||
|
||||
private void fireRootsChanged() {
|
||||
@@ -363,10 +363,10 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
VirtualFile module2Output = myModule1Dir.createChildDirectory(this, "module2Output");
|
||||
VirtualFile module2TestOutput = myModule2Dir.createChildDirectory(this, "module2TestOutput");
|
||||
|
||||
assertNotNull(myIndex.getInfoForDirectory(excluded));
|
||||
assertNotNull(myIndex.getInfoForDirectory(projectOutput));
|
||||
assertNotNull(myIndex.getInfoForDirectory(module2Output));
|
||||
assertNotNull(myIndex.getInfoForDirectory(module2TestOutput));
|
||||
checkInfoNotNull(excluded);
|
||||
checkInfoNotNull(projectOutput);
|
||||
checkInfoNotNull(module2Output);
|
||||
checkInfoNotNull(module2TestOutput);
|
||||
|
||||
getCompilerProjectExtension().setCompilerOutputUrl(projectOutput.getUrl());
|
||||
|
||||
@@ -375,44 +375,37 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
PsiTestUtil.setCompilerOutputPath(myModule2, module2TestOutput.getUrl(), true);
|
||||
PsiTestUtil.setExcludeCompileOutput(myModule2, true);
|
||||
|
||||
assertNull(myIndex.getInfoForDirectory(excluded));
|
||||
assertNull(myIndex.getInfoForDirectory(projectOutput));
|
||||
assertNull(myIndex.getInfoForDirectory(module2Output));
|
||||
assertNull(myIndex.getInfoForDirectory(module2TestOutput));
|
||||
checkInfoNull(excluded);
|
||||
checkInfoNull(projectOutput);
|
||||
checkInfoNull(module2Output);
|
||||
checkInfoNull(module2TestOutput);
|
||||
|
||||
excluded.delete(this);
|
||||
projectOutput.delete(this);
|
||||
module2Output.delete(this);
|
||||
module2TestOutput.delete(this);
|
||||
|
||||
final List<Boolean> isExcluded = new ArrayList<Boolean>();
|
||||
final List<VirtualFile> created = new ArrayList<VirtualFile>();
|
||||
VirtualFileListener l = new VirtualFileAdapter() {
|
||||
@Override
|
||||
public void fileCreated(VirtualFileEvent e) {
|
||||
isExcluded.add(myIndex.getInfoForDirectory(e.getFile()) == null);
|
||||
VirtualFile file = e.getFile();
|
||||
checkInfoNull(file);
|
||||
created.add(file);
|
||||
}
|
||||
};
|
||||
VirtualFileManager.getInstance().addVirtualFileListener(l);
|
||||
try {
|
||||
excluded = myModule1Dir.createChildDirectory(this, excluded.getName());
|
||||
projectOutput = myModule1Dir.createChildDirectory(this, projectOutput.getName());
|
||||
module2Output = myModule1Dir.createChildDirectory(this, module2Output.getName());
|
||||
module2TestOutput = myModule2Dir.createChildDirectory(this, module2TestOutput.getName());
|
||||
}
|
||||
finally {
|
||||
VirtualFileManager.getInstance().removeVirtualFileListener(l);
|
||||
}
|
||||
VirtualFileManager.getInstance().addVirtualFileListener(l, getTestRootDisposable());
|
||||
excluded = myModule1Dir.createChildDirectory(this, excluded.getName());
|
||||
projectOutput = myModule1Dir.createChildDirectory(this, projectOutput.getName());
|
||||
module2Output = myModule1Dir.createChildDirectory(this, module2Output.getName());
|
||||
module2TestOutput = myModule2Dir.createChildDirectory(this, module2TestOutput.getName());
|
||||
|
||||
assertNull(myIndex.getInfoForDirectory(excluded));
|
||||
assertNull(myIndex.getInfoForDirectory(projectOutput));
|
||||
assertNull(myIndex.getInfoForDirectory(module2Output));
|
||||
assertNull(myIndex.getInfoForDirectory(module2TestOutput));
|
||||
checkInfoNull(excluded);
|
||||
checkInfoNull(projectOutput);
|
||||
checkInfoNull(module2Output);
|
||||
checkInfoNull(module2TestOutput);
|
||||
|
||||
assertEquals(4, isExcluded.size());
|
||||
assertTrue(isExcluded.get(0));
|
||||
assertTrue(isExcluded.get(1));
|
||||
assertTrue(isExcluded.get(2));
|
||||
assertTrue(isExcluded.get(3));
|
||||
assertEquals(created.toString(), 4, created.size());
|
||||
}
|
||||
|
||||
public void testExcludesShouldBeRecognizedRightOnRefresh() throws Exception {
|
||||
@@ -430,28 +423,20 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
boolean created = new File(myModule1Dir.getPath(), "dir/excluded/foo").mkdirs();
|
||||
assertTrue(created);
|
||||
|
||||
final List<Boolean> toAssert = new ArrayList<Boolean>();
|
||||
VirtualFileListener l = new VirtualFileAdapter() {
|
||||
@Override
|
||||
public void fileCreated(VirtualFileEvent e) {
|
||||
assertEquals("dir", e.getFileName());
|
||||
|
||||
VirtualFile file = e.getFile();
|
||||
toAssert.add(myIndex.getInfoForDirectory(file) != null);
|
||||
toAssert.add(myIndex.getInfoForDirectory(file.findFileByRelativePath("excluded")) == null);
|
||||
toAssert.add(myIndex.getInfoForDirectory(file.findFileByRelativePath("excluded/foo")) == null);
|
||||
checkInfoNotNull(file);
|
||||
checkInfoNull(file.findFileByRelativePath("excluded"));
|
||||
checkInfoNull(file.findFileByRelativePath("excluded/foo"));
|
||||
}
|
||||
};
|
||||
|
||||
VirtualFileManager.getInstance().addVirtualFileListener(l);
|
||||
try {
|
||||
VirtualFileManager.getInstance().refresh(false);
|
||||
}
|
||||
finally {
|
||||
VirtualFileManager.getInstance().removeVirtualFileListener(l);
|
||||
}
|
||||
|
||||
assertEquals(Arrays.asList(true, true, true), toAssert);
|
||||
VirtualFileManager.getInstance().addVirtualFileListener(l, getTestRootDisposable());
|
||||
VirtualFileManager.getInstance().refresh(false);
|
||||
}
|
||||
|
||||
public void testProcessingNestedContentRootsOfExcludedDirsOnCreation() {
|
||||
@@ -475,8 +460,8 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
});
|
||||
|
||||
|
||||
assertNull(myIndex.getInfoForDirectory(LocalFileSystem.getInstance().findFileByIoFile(f.getParentFile().getParentFile())));
|
||||
assertNotNull(myIndex.getInfoForDirectory(LocalFileSystem.getInstance().findFileByIoFile(f)));
|
||||
checkInfoNull(LocalFileSystem.getInstance().findFileByIoFile(f.getParentFile().getParentFile()));
|
||||
checkInfoNotNull(LocalFileSystem.getInstance().findFileByIoFile(f));
|
||||
}
|
||||
|
||||
public void testLibraryDirInContent() throws Exception {
|
||||
@@ -504,9 +489,7 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
boolean isInLibrarySource,
|
||||
@Nullable String packageName,
|
||||
Module... modulesOfOrderEntries) {
|
||||
DirectoryInfo info = myIndex.getInfoForDirectory(dir);
|
||||
assertNotNull(info);
|
||||
info.assertConsistency();
|
||||
DirectoryInfo info = checkInfoNotNull(dir);
|
||||
assertEquals(module, info.getModule());
|
||||
assertEquals(isInModuleSource, info.isInModuleSource());
|
||||
assertEquals(isTestSource, info.isTestSource());
|
||||
@@ -520,20 +503,19 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
|
||||
assertEquals(modulesOfOrderEntries.length, info.getOrderEntries().length);
|
||||
for (Module aModule : modulesOfOrderEntries) {
|
||||
boolean found = false;
|
||||
for (OrderEntry orderEntry : info.getOrderEntries()) {
|
||||
if (orderEntry.getOwnerModule() == aModule) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertTrue(found);
|
||||
OrderEntry found = info.findOrderEntryWithOwnerModule(aModule);
|
||||
assertNotNull(found);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkInfoNull(VirtualFile dir) {
|
||||
DirectoryInfo info = myIndex.getInfoForDirectory(dir);
|
||||
assertNull(info);
|
||||
private void checkInfoNull(@NotNull VirtualFile dir) {
|
||||
assertNull(myIndex.getInfoForDirectory(dir));
|
||||
}
|
||||
private DirectoryInfo checkInfoNotNull(@NotNull VirtualFile output2) {
|
||||
DirectoryInfo info = myIndex.getInfoForDirectory(output2);
|
||||
assertNotNull(output2.toString(), info);
|
||||
info.assertConsistency();
|
||||
return info;
|
||||
}
|
||||
|
||||
private void checkPackage(String packageName, VirtualFile... expectedDirs) {
|
||||
|
||||
@@ -109,10 +109,12 @@ public class DirectoryIndexComponent extends DirectoryIndexImpl {
|
||||
myState = updateStateWithNewFile(file, parent);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private IndexState updateStateWithNewFile(@NotNull VirtualFile file, @NotNull VirtualFile parent) {
|
||||
final IndexState originalState = myState;
|
||||
IndexState state = originalState;
|
||||
DirectoryInfo parentInfo = originalState.myDirToInfoMap.get(getId(parent));
|
||||
int parentId = getId(parent);
|
||||
DirectoryInfo parentInfo = originalState.myDirToInfoMap.get(parentId);
|
||||
|
||||
// fill info for all nested roots
|
||||
for (Module eachModule : ModuleManager.getInstance(myProject).getModules()) {
|
||||
@@ -147,7 +149,7 @@ public class DirectoryIndexComponent extends DirectoryIndexImpl {
|
||||
if (state == originalState) state = state.copy();
|
||||
state.fillMapWithModuleContent(file, module, parentInfo.getContentRoot(), null);
|
||||
|
||||
String parentPackage = state.myDirToPackageName.get(getId(parent));
|
||||
String parentPackage = state.myDirToPackageName.get(parentId);
|
||||
|
||||
if (module != null) {
|
||||
if (parentInfo.isInModuleSource()) {
|
||||
|
||||
@@ -32,16 +32,16 @@ public abstract class DirectoryIndex {
|
||||
@TestOnly
|
||||
public abstract void checkConsistency();
|
||||
|
||||
public abstract DirectoryInfo getInfoForDirectory(VirtualFile dir);
|
||||
public abstract DirectoryInfo getInfoForDirectory(@NotNull VirtualFile dir);
|
||||
|
||||
public abstract boolean isProjectExcludeRoot(VirtualFile dir);
|
||||
public abstract boolean isProjectExcludeRoot(@NotNull VirtualFile dir);
|
||||
|
||||
@NotNull
|
||||
public abstract
|
||||
Query<VirtualFile> getDirectoriesByPackageName(@NotNull String packageName, boolean includeLibrarySources);
|
||||
|
||||
@Nullable
|
||||
public abstract String getPackageName(VirtualFile dir);
|
||||
public abstract String getPackageName(@NotNull VirtualFile dir);
|
||||
|
||||
public abstract boolean isInitialized();
|
||||
}
|
||||
|
||||
+60
-40
@@ -55,7 +55,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
private boolean myInitialized = false;
|
||||
private boolean myDisposed = false;
|
||||
|
||||
public DirectoryIndexImpl(Project project) {
|
||||
public DirectoryIndexImpl(@NotNull Project project) {
|
||||
myProject = project;
|
||||
myExcludePolicies = Extensions.getExtensions(DirectoryIndexExcludePolicy.EP_NAME, myProject);
|
||||
myState = new IndexState();
|
||||
@@ -142,18 +142,20 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
myState = newState;
|
||||
}
|
||||
|
||||
private boolean isExcludeRootForModule(Module module, VirtualFile excludeRoot) {
|
||||
private boolean isExcludeRootForModule(@NotNull Module module, VirtualFile excludeRoot) {
|
||||
for (DirectoryIndexExcludePolicy policy : myExcludePolicies) {
|
||||
if (policy.isExcludeRootForModule(module, excludeRoot)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static ContentEntry[] getContentEntries(Module module) {
|
||||
@NotNull
|
||||
protected static ContentEntry[] getContentEntries(@NotNull Module module) {
|
||||
return ModuleRootManager.getInstance(module).getContentEntries();
|
||||
}
|
||||
|
||||
private static OrderEntry[] getOrderEntries(Module module) {
|
||||
@NotNull
|
||||
private static OrderEntry[] getOrderEntries(@NotNull Module module) {
|
||||
return ModuleRootManager.getInstance(module).getOrderEntries();
|
||||
}
|
||||
|
||||
@@ -162,7 +164,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DirectoryInfo getInfoForDirectory(VirtualFile dir) {
|
||||
public DirectoryInfo getInfoForDirectory(@NotNull VirtualFile dir) {
|
||||
checkAvailability();
|
||||
dispatchPendingEvents();
|
||||
|
||||
@@ -171,7 +173,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProjectExcludeRoot(VirtualFile dir) {
|
||||
public boolean isProjectExcludeRoot(@NotNull VirtualFile dir) {
|
||||
checkAvailability();
|
||||
return dir instanceof VirtualFileWithId && myState.myProjectExcludeRoots.contains(getId(dir));
|
||||
}
|
||||
@@ -233,7 +235,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPackageName(VirtualFile dir) {
|
||||
public String getPackageName(@NotNull VirtualFile dir) {
|
||||
checkAvailability();
|
||||
if (!(dir instanceof VirtualFileWithId)) return null;
|
||||
return myState.myDirToPackageName.get(getId(dir));
|
||||
@@ -317,11 +319,15 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
private DirectoryInfo getOrCreateDirInfo(int dirId) {
|
||||
DirectoryInfo info = myDirToInfoMap.get(dirId);
|
||||
if (info == null) {
|
||||
info = new DirectoryInfo();
|
||||
info = new DirectoryInfo(null, null,null,null,(byte)0,null);
|
||||
myDirToInfoMap.put(dirId, info);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
private DirectoryInfo storeInfo(DirectoryInfo info, int dirId) {
|
||||
myDirToInfoMap.put(dirId, info);
|
||||
return info;
|
||||
}
|
||||
|
||||
void fillMapWithModuleContent(@NotNull VirtualFile root,
|
||||
final Module module,
|
||||
@@ -330,7 +336,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
final int contentRootId = contentRoot == null ? 0 : getId(contentRoot);
|
||||
VfsUtilCore.visitChildrenRecursively(root, new DirectoryVisitor() {
|
||||
@Override
|
||||
protected DirectoryInfo updateInfo(VirtualFile file) {
|
||||
protected DirectoryInfo updateInfo(@NotNull VirtualFile file) {
|
||||
if (progress != null) {
|
||||
progress.checkCanceled();
|
||||
}
|
||||
@@ -349,9 +355,9 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterChildrenVisited(DirectoryInfo info) {
|
||||
info.setModule(module);
|
||||
info.setContentRoot(contentRoot);
|
||||
protected void afterChildrenVisited(@NotNull VirtualFile file, @NotNull DirectoryInfo info) {
|
||||
info = info.withModule(module).withContentRoot(contentRoot);
|
||||
storeInfo(info, getId(file));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -372,13 +378,13 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
|
||||
@Override
|
||||
public void afterChildrenVisited(@NotNull VirtualFile file) {
|
||||
afterChildrenVisited(myDirectoryInfoStack.pop());
|
||||
afterChildrenVisited(file, myDirectoryInfoStack.pop());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract DirectoryInfo updateInfo(VirtualFile file);
|
||||
protected abstract DirectoryInfo updateInfo(@NotNull VirtualFile file);
|
||||
|
||||
protected void afterChildrenVisited(DirectoryInfo info) {}
|
||||
protected void afterChildrenVisited(@NotNull VirtualFile file, @NotNull DirectoryInfo info) {}
|
||||
}
|
||||
|
||||
private boolean isExcluded(int root, @NotNull VirtualFile dir) {
|
||||
@@ -387,7 +393,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
return excludes != null && excludes.contains(dir.getUrl());
|
||||
}
|
||||
|
||||
private void initModuleContents(Module module, boolean reverseAllSets, ProgressIndicator progress) {
|
||||
private void initModuleContents(@NotNull Module module, boolean reverseAllSets, @NotNull ProgressIndicator progress) {
|
||||
progress.checkCanceled();
|
||||
progress.setText2(ProjectBundle.message("project.index.processing.module.content.progress", module.getName()));
|
||||
|
||||
@@ -436,7 +442,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
private final Stack<String> myPackages = new Stack<String>();
|
||||
|
||||
@Override
|
||||
protected DirectoryInfo updateInfo(VirtualFile file) {
|
||||
protected DirectoryInfo updateInfo(@NotNull VirtualFile file) {
|
||||
if (progress != null) {
|
||||
progress.checkCanceled();
|
||||
}
|
||||
@@ -450,9 +456,10 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
if (definedPackage != null && definedPackage.isEmpty()) return null; // another source root starts here
|
||||
}
|
||||
|
||||
info.setInModuleSource(true);
|
||||
info.setTestSource(isTestSource);
|
||||
info.setSourceRoot(sourceRoot);
|
||||
info = info.withInModuleSource(true)
|
||||
.withTestSource(isTestSource)
|
||||
.withSourceRoot(sourceRoot);
|
||||
storeInfo(info, id);
|
||||
|
||||
String currentPackage = myPackages.isEmpty() ? packageName : getPackageNameForSubdir(myPackages.peek(), file.getName());
|
||||
myPackages.push(currentPackage);
|
||||
@@ -461,8 +468,8 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterChildrenVisited(DirectoryInfo info) {
|
||||
super.afterChildrenVisited(info);
|
||||
protected void afterChildrenVisited(@NotNull VirtualFile file, @NotNull DirectoryInfo info) {
|
||||
super.afterChildrenVisited(file, info);
|
||||
myPackages.pop();
|
||||
}
|
||||
});
|
||||
@@ -501,8 +508,9 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
if (definedPackage != null && definedPackage.isEmpty()) return false; // another library source root starts here
|
||||
}
|
||||
|
||||
info.setInLibrarySource(true);
|
||||
info.setSourceRoot(sourceRoot);
|
||||
info = info.withInLibrarySource(true)
|
||||
.withSourceRoot(sourceRoot);
|
||||
storeInfo(info, dirId);
|
||||
|
||||
final String packageName = getCurrentValue();
|
||||
final String newPackageName = Comparing.equal(file, dir) ? packageName : getPackageNameForSubdir(packageName, file.getName());
|
||||
@@ -548,7 +556,8 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
if (definedPackage != null && definedPackage.isEmpty()) return false; // another library root starts here
|
||||
}
|
||||
|
||||
info.setLibraryClassRoot(classRoot);
|
||||
info = info.withLibraryClassRoot(classRoot);
|
||||
storeInfo(info, dirId);
|
||||
|
||||
final String packageName = getCurrentValue();
|
||||
final String childPackageName = Comparing.equal(file, dir) ? packageName : getPackageNameForSubdir(packageName, file.getName());
|
||||
@@ -656,13 +665,14 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
private final Stack<OrderEntry[]> myEntries = new Stack<OrderEntry[]>();
|
||||
|
||||
@Override
|
||||
protected DirectoryInfo updateInfo(VirtualFile dir) {
|
||||
protected DirectoryInfo updateInfo(@NotNull VirtualFile dir) {
|
||||
if (progress != null) {
|
||||
progress.checkCanceled();
|
||||
}
|
||||
if (isIgnored(dir)) return null;
|
||||
|
||||
DirectoryInfo info = myDirToInfoMap.get(getId(dir)); // do not create it here!
|
||||
int dirId = getId(dir);
|
||||
DirectoryInfo info = myDirToInfoMap.get(dirId); // do not create it here!
|
||||
if (info == null) return null;
|
||||
|
||||
if (module != null) {
|
||||
@@ -682,12 +692,13 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
OrderEntry[] oldParentEntries = myEntries.isEmpty() ? null : myEntries.peek();
|
||||
OrderEntry[] oldEntries = info.getOrderEntries();
|
||||
myEntries.push(oldEntries);
|
||||
info.addOrderEntries(orderEntries, parentInfo, oldParentEntries);
|
||||
info = info.withOrderEntries(orderEntries, parentInfo, oldParentEntries);
|
||||
storeInfo(info, dirId);
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterChildrenVisited(DirectoryInfo info) {
|
||||
protected void afterChildrenVisited(@NotNull VirtualFile file, @NotNull DirectoryInfo info) {
|
||||
myEntries.pop();
|
||||
}
|
||||
});
|
||||
@@ -730,11 +741,12 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
}
|
||||
fillMapWithOrderEntries(depEntries, libClassRootEntries, libSourceRootEntries, progress);
|
||||
|
||||
killOrderEntryArrayDuplicates();
|
||||
internDirectoryInfos();
|
||||
}
|
||||
|
||||
private void killOrderEntryArrayDuplicates() {
|
||||
Map<OrderEntry[], OrderEntry[]> interner = new THashMap<OrderEntry[], OrderEntry[]>(new TObjectHashingStrategy<OrderEntry[]>() {
|
||||
private void internDirectoryInfos() {
|
||||
final Map<DirectoryInfo, DirectoryInfo> diInterner = new THashMap<DirectoryInfo, DirectoryInfo>();
|
||||
final Map<OrderEntry[], OrderEntry[]> oeInterner = new THashMap<OrderEntry[], OrderEntry[]>(new TObjectHashingStrategy<OrderEntry[]>() {
|
||||
@Override
|
||||
public int computeHashCode(OrderEntry[] object) {
|
||||
return Arrays.hashCode(object);
|
||||
@@ -745,17 +757,25 @@ public class DirectoryIndexImpl extends DirectoryIndex {
|
||||
return Arrays.equals(o1, o2);
|
||||
}
|
||||
});
|
||||
for (Object v : myDirToInfoMap.getValues()) {
|
||||
DirectoryInfo info = (DirectoryInfo)v;
|
||||
OrderEntry[] entries = info.getOrderEntries();
|
||||
if (entries.length != 0) {
|
||||
OrderEntry[] interned = interner.get(entries);
|
||||
|
||||
myDirToInfoMap.transformValues(new TObjectFunction<DirectoryInfo, DirectoryInfo>() {
|
||||
@Override
|
||||
public DirectoryInfo execute(DirectoryInfo info) {
|
||||
DirectoryInfo interned = diInterner.get(info);
|
||||
if (interned == null) {
|
||||
interner.put(entries, interned = entries);
|
||||
OrderEntry[] entries = info.getOrderEntries();
|
||||
OrderEntry[] internedEntries = oeInterner.get(entries);
|
||||
if (internedEntries == null) {
|
||||
oeInterner.put(entries, entries);
|
||||
}
|
||||
else if (internedEntries != entries) {
|
||||
info = info.withInternedEntries(internedEntries);
|
||||
}
|
||||
diInterner.put(info, interned = info);
|
||||
}
|
||||
info.setInternedOrderEntries(interned);
|
||||
return interned;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initExcludedDirMap(Module[] modules, ProgressIndicator progress) {
|
||||
|
||||
@@ -16,12 +16,10 @@
|
||||
|
||||
package com.intellij.openapi.roots.impl;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.RootPolicy;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayFactory;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
@@ -32,52 +30,69 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public final class DirectoryInfo {
|
||||
private Module module; // module to which content it belongs or null
|
||||
private VirtualFile libraryClassRoot; // class root in library
|
||||
private VirtualFile contentRoot;
|
||||
private VirtualFile sourceRoot;
|
||||
private final Module module; // module to which content it belongs or null
|
||||
private final VirtualFile libraryClassRoot; // class root in library
|
||||
private final VirtualFile contentRoot;
|
||||
private final VirtualFile sourceRoot;
|
||||
|
||||
private static final byte TEST_SOURCE_FLAG = 1; // (makes sense only if MODULE_SOURCE_FLAG is set)
|
||||
private static final byte LIBRARY_SOURCE_FLAG = 2; // set if it's a directory with sources of some library
|
||||
private static final byte MODULE_SOURCE_FLAG = 4; // set if files in this directory belongs to sources of the module (if field 'module' is not null)
|
||||
|
||||
@MagicConstant(flags = {TEST_SOURCE_FLAG, LIBRARY_SOURCE_FLAG, MODULE_SOURCE_FLAG})
|
||||
private byte sourceFlag;
|
||||
private final byte sourceFlag;
|
||||
|
||||
/**
|
||||
* orderEntry to (classes of) which a directory belongs
|
||||
* MUST BE SORTED WITH {@link #BY_OWNER_MODULE}
|
||||
*/
|
||||
private OrderEntry[] orderEntries;
|
||||
private final OrderEntry[] orderEntries;
|
||||
|
||||
public DirectoryInfo() {
|
||||
public DirectoryInfo(Module module,
|
||||
VirtualFile contentRoot,
|
||||
VirtualFile sourceRoot,
|
||||
VirtualFile libraryClassRoot,
|
||||
@MagicConstant(flags = {TEST_SOURCE_FLAG, LIBRARY_SOURCE_FLAG, MODULE_SOURCE_FLAG}) byte sourceFlag,
|
||||
OrderEntry[] orderEntries) {
|
||||
this.module = module;
|
||||
this.libraryClassRoot = libraryClassRoot;
|
||||
this.contentRoot = contentRoot;
|
||||
this.sourceRoot = sourceRoot;
|
||||
this.sourceFlag = sourceFlag;
|
||||
this.orderEntries = orderEntries;
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@SuppressWarnings({"unchecked"})
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
assert ApplicationManager.getApplication().isUnitTestMode() : "DirectoryInfo.equals should only be used in tests";
|
||||
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof DirectoryInfo)) return false;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final DirectoryInfo info = (DirectoryInfo)o;
|
||||
DirectoryInfo info = (DirectoryInfo)o;
|
||||
|
||||
if (sourceFlag != info.sourceFlag) return false;
|
||||
if (getModule() != null ? !getModule().equals(info.getModule()) : info.getModule() != null) return false;
|
||||
if (orderEntries != null ? !new HashSet(Arrays.asList(orderEntries)).equals(new HashSet(Arrays.asList(info.orderEntries))) : info.orderEntries != null) return false;
|
||||
if (!Comparing.equal(getLibraryClassRoot(), info.getLibraryClassRoot())) return false;
|
||||
if (!Comparing.equal(getContentRoot(), info.getContentRoot())) return false;
|
||||
if (!Comparing.equal(getSourceRoot(), info.getSourceRoot())) return false;
|
||||
if (contentRoot != null ? !contentRoot.equals(info.contentRoot) : info.contentRoot != null) return false;
|
||||
if (libraryClassRoot != null ? !libraryClassRoot.equals(info.libraryClassRoot) : info.libraryClassRoot != null) return false;
|
||||
if (module != null ? !module.equals(info.module) : info.module != null) return false;
|
||||
if (!Arrays.equals(orderEntries, info.orderEntries)) return false;
|
||||
if (sourceRoot != null ? !sourceRoot.equals(info.sourceRoot) : info.sourceRoot != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
throw new UnsupportedOperationException("DirectoryInfo shall not be used as a key to HashMap");
|
||||
int result = module != null ? module.hashCode() : 0;
|
||||
result = 31 * result + (libraryClassRoot != null ? libraryClassRoot.hashCode() : 0);
|
||||
result = 31 * result + (contentRoot != null ? contentRoot.hashCode() : 0);
|
||||
result = 31 * result + (sourceRoot != null ? sourceRoot.hashCode() : 0);
|
||||
result = 31 * result + (int)sourceFlag;
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
@@ -95,7 +110,8 @@ public final class DirectoryInfo {
|
||||
|
||||
@NotNull
|
||||
public OrderEntry[] getOrderEntries() {
|
||||
return orderEntries == null ? OrderEntry.EMPTY_ARRAY : orderEntries;
|
||||
OrderEntry[] entries = orderEntries;
|
||||
return entries == null ? OrderEntry.EMPTY_ARRAY : entries;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -193,21 +209,25 @@ public final class DirectoryInfo {
|
||||
}
|
||||
|
||||
// orderEntries must be sorted BY_OWNER_MODULE
|
||||
void addOrderEntries(@NotNull OrderEntry[] orderEntries,
|
||||
@Nullable final DirectoryInfo parentInfo,
|
||||
@Nullable final OrderEntry[] oldParentEntries) {
|
||||
@NotNull
|
||||
DirectoryInfo withOrderEntries(@NotNull OrderEntry[] orderEntries,
|
||||
@Nullable final DirectoryInfo parentInfo,
|
||||
@Nullable final OrderEntry[] oldParentEntries) {
|
||||
OrderEntry[] newOrderEntries;
|
||||
if (orderEntries.length == 0) {
|
||||
this.orderEntries = null;
|
||||
newOrderEntries = null;
|
||||
}
|
||||
else if (this.orderEntries == null) {
|
||||
this.orderEntries = orderEntries;
|
||||
newOrderEntries = orderEntries;
|
||||
}
|
||||
else if (parentInfo != null && oldParentEntries == this.orderEntries) {
|
||||
this.orderEntries = parentInfo.orderEntries;
|
||||
newOrderEntries = parentInfo.orderEntries;
|
||||
}
|
||||
else {
|
||||
this.orderEntries = mergeWith(orderEntries);
|
||||
newOrderEntries = mergeWith(orderEntries);
|
||||
}
|
||||
|
||||
return new DirectoryInfo(module, contentRoot, sourceRoot, libraryClassRoot, sourceFlag, newOrderEntries);
|
||||
}
|
||||
|
||||
// entries must be sorted BY_OWNER_MODULE
|
||||
@@ -249,10 +269,6 @@ public final class DirectoryInfo {
|
||||
}
|
||||
};
|
||||
|
||||
public void setInternedOrderEntries(@NotNull OrderEntry[] internedOrderEntries) {
|
||||
orderEntries = internedOrderEntries;
|
||||
}
|
||||
|
||||
public VirtualFile getSourceRoot() {
|
||||
return sourceRoot;
|
||||
}
|
||||
@@ -275,48 +291,63 @@ public final class DirectoryInfo {
|
||||
return BitUtil.isSet(sourceFlag, MODULE_SOURCE_FLAG);
|
||||
}
|
||||
|
||||
public void setInModuleSource(boolean inModuleSource) {
|
||||
sourceFlag = (byte)BitUtil.set(sourceFlag, MODULE_SOURCE_FLAG, inModuleSource);
|
||||
@NotNull
|
||||
DirectoryInfo withInModuleSource(boolean inModuleSource) {
|
||||
byte sourceFlag = (byte)BitUtil.set(this.sourceFlag, MODULE_SOURCE_FLAG, inModuleSource);
|
||||
return new DirectoryInfo(module, contentRoot, sourceRoot, libraryClassRoot, sourceFlag, orderEntries);
|
||||
}
|
||||
|
||||
public boolean isTestSource() {
|
||||
return BitUtil.isSet(sourceFlag, TEST_SOURCE_FLAG);
|
||||
}
|
||||
|
||||
public void setTestSource(boolean testSource) {
|
||||
sourceFlag = (byte)BitUtil.set(sourceFlag, TEST_SOURCE_FLAG, testSource);
|
||||
@NotNull
|
||||
DirectoryInfo withTestSource(boolean testSource) {
|
||||
byte sourceFlag = (byte)BitUtil.set(this.sourceFlag, TEST_SOURCE_FLAG, testSource);
|
||||
return new DirectoryInfo(module, contentRoot, sourceRoot, libraryClassRoot, sourceFlag, orderEntries);
|
||||
}
|
||||
|
||||
public boolean isInLibrarySource() {
|
||||
return BitUtil.isSet(sourceFlag, LIBRARY_SOURCE_FLAG);
|
||||
}
|
||||
|
||||
public void setInLibrarySource(boolean inLibrarySource) {
|
||||
sourceFlag = (byte)BitUtil.set(sourceFlag, LIBRARY_SOURCE_FLAG, inLibrarySource);
|
||||
@NotNull
|
||||
DirectoryInfo withInLibrarySource(boolean inLibrarySource) {
|
||||
byte sourceFlag = (byte)BitUtil.set(this.sourceFlag, LIBRARY_SOURCE_FLAG, inLibrarySource);
|
||||
return new DirectoryInfo(module, contentRoot, sourceRoot, libraryClassRoot, sourceFlag, orderEntries);
|
||||
}
|
||||
|
||||
public Module getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public void setModule(Module module) {
|
||||
this.module = module;
|
||||
@NotNull
|
||||
DirectoryInfo withModule(Module module) {
|
||||
return new DirectoryInfo(module, contentRoot, sourceRoot, libraryClassRoot, sourceFlag, orderEntries);
|
||||
}
|
||||
|
||||
public void setLibraryClassRoot(@NotNull VirtualFile libraryClassRoot) {
|
||||
this.libraryClassRoot = libraryClassRoot;
|
||||
@NotNull
|
||||
DirectoryInfo withLibraryClassRoot(@NotNull VirtualFile libraryClassRoot) {
|
||||
return new DirectoryInfo(module, contentRoot, sourceRoot, libraryClassRoot, sourceFlag, orderEntries);
|
||||
}
|
||||
|
||||
public void setContentRoot(VirtualFile contentRoot) {
|
||||
this.contentRoot = contentRoot;
|
||||
@NotNull
|
||||
DirectoryInfo withContentRoot(VirtualFile contentRoot) {
|
||||
return new DirectoryInfo(module, contentRoot, sourceRoot, libraryClassRoot, sourceFlag, orderEntries);
|
||||
}
|
||||
|
||||
public void setSourceRoot(@NotNull VirtualFile sourceRoot) {
|
||||
this.sourceRoot = sourceRoot;
|
||||
@NotNull
|
||||
DirectoryInfo withSourceRoot(@NotNull VirtualFile sourceRoot) {
|
||||
return new DirectoryInfo(module, contentRoot, sourceRoot, libraryClassRoot, sourceFlag, orderEntries);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
DirectoryInfo withInternedEntries(@NotNull OrderEntry[] orderEntries) {
|
||||
return new DirectoryInfo(module, contentRoot, sourceRoot, libraryClassRoot, sourceFlag, orderEntries);
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public void assertConsistency() {
|
||||
void assertConsistency() {
|
||||
OrderEntry[] entries = getOrderEntries();
|
||||
for (int i=1; i<entries.length; i++) {
|
||||
assert BY_OWNER_MODULE.compare(entries[i-1], entries[i]) <= 0;
|
||||
|
||||
Reference in New Issue
Block a user