diff options
Diffstat (limited to 'platform/projectModel-impl/src/com')
16 files changed, 175 insertions, 245 deletions
diff --git a/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java b/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java index 7acb0fb12243..7b436b53c8d6 100644 --- a/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java +++ b/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -41,21 +41,21 @@ public class ProjectRootsUtil { return directoryFile.equals(fileIndex.getSourceRootForFile(directoryFile)); } - public static boolean isInSource(final PsiDirectory directory) { + public static boolean isInSource(@NotNull PsiDirectory directory) { return isInSource(directory.getVirtualFile(), directory.getProject()); } - public static boolean isInSource(final VirtualFile directoryFile, final Project project) { + public static boolean isInSource(@NotNull VirtualFile directoryFile, @NotNull Project project) { final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); return projectFileIndex.isInSourceContent(directoryFile); } - public static boolean isInTestSource(final VirtualFile directoryFile, final Project project) { + public static boolean isInTestSource(@NotNull VirtualFile directoryFile, @NotNull Project project) { final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); return projectFileIndex.isInTestSourceContent(directoryFile); } - public static boolean isModuleSourceRoot(@NotNull VirtualFile virtualFile, final @NotNull Project project) { + public static boolean isModuleSourceRoot(@NotNull VirtualFile virtualFile, @NotNull final Project project) { return getModuleSourceRoot(virtualFile, project) != null; } @@ -66,7 +66,7 @@ public class ProjectRootsUtil { return module != null && !module.isDisposed() ? findSourceFolder(module, root) : null; } - public static boolean isLibraryRoot(final VirtualFile directoryFile, final Project project) { + public static boolean isLibraryRoot(@NotNull VirtualFile directoryFile, @NotNull Project project) { final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); if (projectFileIndex.isInLibraryClasses(directoryFile)) { final VirtualFile parent = directoryFile.getParent(); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java index 83984e11a80b..7a62c35d0390 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java @@ -18,6 +18,7 @@ package com.intellij.openapi.roots; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -65,4 +66,12 @@ public abstract class OrderEnumerationHandler { @NotNull Collection<String> urls) { return false; } + + public boolean addCustomModuleRoots(@NotNull OrderRootType type, + @NotNull ModuleRootModel rootModel, + @NotNull Collection<String> result, + boolean includeProduction, + boolean includeTests) { + return false; + } } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java index 9fdd8e09a57d..e87d3c749b10 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java @@ -17,23 +17,23 @@ package com.intellij.openapi.roots.impl; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Query; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; import org.jetbrains.jps.model.module.JpsModuleSourceRootType; +import java.util.List; + public abstract class DirectoryIndex { public static DirectoryIndex getInstance(Project project) { assert !project.isDefault() : "Must not call DirectoryIndex for default project"; return ServiceManager.getService(project, DirectoryIndex.class); } - @TestOnly - public abstract void checkConsistency(); - /** * The same as {@link #getInfoForFile} but works only for directories or file roots and returns {@code null} for directories * which aren't included in project content or libraries @@ -62,4 +62,13 @@ public abstract class DirectoryIndex { public boolean isInitialized() { return true; } + + @NotNull + public abstract OrderEntry[] getOrderEntries(@NotNull DirectoryInfo info); + + @Nullable + abstract OrderEntry findOrderEntryWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule); + + @NotNull + abstract List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule); } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java index b31519ccb4a2..61838f51ac1d 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java @@ -17,7 +17,6 @@ package com.intellij.openapi.roots.impl; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; @@ -29,10 +28,9 @@ import org.jetbrains.annotations.NotNull; public interface DirectoryIndexExcludePolicy { ExtensionPointName<DirectoryIndexExcludePolicy> EP_NAME = ExtensionPointName.create("com.intellij.directoryIndexExcludePolicy"); - boolean isExcludeRoot(VirtualFile file); - boolean isExcludeRootForModule(@NotNull Module module, final VirtualFile file); @NotNull VirtualFile[] getExcludeRootsForProject(); + @NotNull VirtualFilePointer[] getExcludeRootsForModule(@NotNull ModuleRootModel rootModel); } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java index 87448a584a23..cd5fbd7d5867 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java @@ -17,13 +17,8 @@ package com.intellij.openapi.roots.impl; import com.intellij.openapi.module.Module; -import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; - -import java.util.List; public abstract class DirectoryInfo { /** @@ -61,16 +56,4 @@ public abstract class DirectoryInfo { @Nullable public abstract Module getModule(); - - @NotNull - public abstract OrderEntry[] getOrderEntries(); - - @Nullable - abstract OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule); - - @NotNull - abstract List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule); - - @TestOnly - abstract void assertConsistency(); } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java index 0be339bf3c5f..1c3ca4f2ff8d 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java @@ -16,34 +16,16 @@ package com.intellij.openapi.roots.impl; 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.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; /** * @author nik */ -public abstract class DirectoryInfoImpl extends DirectoryInfo { - public static final Comparator<OrderEntry> BY_OWNER_MODULE = new Comparator<OrderEntry>() { - @Override - public int compare(OrderEntry o1, OrderEntry o2) { - String name1 = o1.getOwnerModule().getName(); - String name2 = o2.getOwnerModule().getName(); - return name1.compareTo(name2); - } - }; +public class DirectoryInfoImpl extends DirectoryInfo { public static final int MAX_ROOT_TYPE_ID = Byte.MAX_VALUE; + private final VirtualFile myRoot;//original project root for which this information is calculated private final Module module; // module to which content it belongs or null private final VirtualFile libraryClassRoot; // class root in library private final VirtualFile contentRoot; @@ -53,8 +35,9 @@ public abstract class DirectoryInfoImpl extends DirectoryInfo { private final boolean myExcluded; private final byte mySourceRootTypeId; - DirectoryInfoImpl(Module module, VirtualFile contentRoot, VirtualFile sourceRoot, VirtualFile libraryClassRoot, + DirectoryInfoImpl(@NotNull VirtualFile root, Module module, VirtualFile contentRoot, VirtualFile sourceRoot, VirtualFile libraryClassRoot, boolean inModuleSource, boolean inLibrarySource, boolean isExcluded, int sourceRootTypeId) { + myRoot = root; this.module = module; this.libraryClassRoot = libraryClassRoot; this.contentRoot = contentRoot; @@ -74,30 +57,12 @@ public abstract class DirectoryInfoImpl extends DirectoryInfo { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - DirectoryInfoImpl info = (DirectoryInfoImpl)o; - - return mySourceRootTypeId == info.mySourceRootTypeId && - myInModuleSource == info.myInModuleSource && - myInLibrarySource == info.myInLibrarySource && - myExcluded == info.myExcluded && - Comparing.equal(contentRoot, info.contentRoot) && - Comparing.equal(libraryClassRoot, info.libraryClassRoot) && - Comparing.equal(module, info.module) && - Arrays.equals(getOrderEntries(), info.getOrderEntries()) && - Comparing.equal(sourceRoot, info.sourceRoot); + return myRoot.equals(((DirectoryInfoImpl)o).myRoot); } @Override public int hashCode() { - 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 + (myInModuleSource ? 1 : 0); - result = 31 * result + (myInLibrarySource ? 1 : 0); - result = 31 * result + (myExcluded ? 1 : 0); - result = 31 * result + (int)mySourceRootTypeId; - return result; + return myRoot.hashCode(); } @SuppressWarnings({"HardCodedStringLiteral"}) @@ -111,98 +76,9 @@ public abstract class DirectoryInfoImpl extends DirectoryInfo { ", libraryClassRoot=" + getLibraryClassRoot() + ", contentRoot=" + getContentRoot() + ", sourceRoot=" + getSourceRoot() + - ", orderEntries=" + Arrays.toString(getOrderEntries()) + "}"; } - @NotNull - private static OrderEntry createFakeOrderEntry(@NotNull final Module ownerModule) { - return new OrderEntry() { - @NotNull - @Override - public VirtualFile[] getFiles(OrderRootType type) { - throw new IncorrectOperationException(); - } - - @NotNull - @Override - public String[] getUrls(OrderRootType rootType) { - throw new IncorrectOperationException(); - } - - @NotNull - @Override - public String getPresentableName() { - throw new IncorrectOperationException(); - } - - @Override - public boolean isValid() { - throw new IncorrectOperationException(); - } - - @NotNull - @Override - public Module getOwnerModule() { - return ownerModule; - } - - @Override - public <R> R accept(RootPolicy<R> policy, @Nullable R initialValue) { - throw new IncorrectOperationException(); - } - - @Override - public int compareTo(@NotNull OrderEntry o) { - throw new IncorrectOperationException(); - } - - @Override - public boolean isSynthetic() { - throw new IncorrectOperationException(); - } - }; - } - - @Nullable - OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule) { - OrderEntry[] entries = getOrderEntries(); - if (entries.length < 10) { - for (OrderEntry entry : entries) { - if (entry.getOwnerModule() == ownerModule) return entry; - } - return null; - } - int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), BY_OWNER_MODULE); - return index < 0 ? null : entries[index]; - } - - @NotNull - List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule) { - OrderEntry[] entries = getOrderEntries(); - if (entries.length == 1) { - OrderEntry entry = entries[0]; - return entry.getOwnerModule() == ownerModule ? Arrays.asList(entries) : Collections.<OrderEntry>emptyList(); - } - int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), BY_OWNER_MODULE); - if (index < 0) { - return Collections.emptyList(); - } - int firstIndex = index; - while (firstIndex-1 >= 0 && entries[firstIndex-1].getOwnerModule() == ownerModule) { - firstIndex--; - } - int lastIndex = index+1; - while (lastIndex < entries.length && entries[lastIndex].getOwnerModule() == ownerModule) { - lastIndex++; - } - - OrderEntry[] subArray = new OrderEntry[lastIndex - firstIndex]; - System.arraycopy(entries, firstIndex, subArray, 0, lastIndex - firstIndex); - - return Arrays.asList(subArray); - } - public boolean isInProject() { return !isExcluded(); } @@ -241,15 +117,12 @@ public abstract class DirectoryInfoImpl extends DirectoryInfo { return module; } - @TestOnly - void assertConsistency() { - OrderEntry[] entries = getOrderEntries(); - for (int i=1; i<entries.length; i++) { - assert BY_OWNER_MODULE.compare(entries[i-1], entries[i]) <= 0; - } - } - public int getSourceRootTypeId() { return mySourceRootTypeId; } + + @NotNull + public VirtualFile getRoot() { + return myRoot; + } } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java index 3b5ea4fa1610..8140a3c15211 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java @@ -79,12 +79,12 @@ public class ModuleFileIndexImpl extends FileIndexBase implements ModuleFileInde @Override @NotNull public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile fileOrDir) { - return getInfoForFileOrDirectory(fileOrDir).findAllOrderEntriesWithOwnerModule(myModule); + return myDirectoryIndex.findAllOrderEntriesWithOwnerModule(getInfoForFileOrDirectory(fileOrDir), myModule); } @Override public OrderEntry getOrderEntryForFile(@NotNull VirtualFile fileOrDir) { - return getInfoForFileOrDirectory(fileOrDir).findOrderEntryWithOwnerModule(myModule); + return myDirectoryIndex.findOrderEntryWithOwnerModule(getInfoForFileOrDirectory(fileOrDir), myModule); } @Override diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java index 7937f08fc7b4..ce09ec2fb819 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java @@ -16,14 +16,9 @@ package com.intellij.openapi.roots.impl; import com.intellij.openapi.module.Module; -import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collections; -import java.util.List; - /** * @author nik */ @@ -53,22 +48,6 @@ class NonProjectDirectoryInfo extends DirectoryInfo { return false; } - @NotNull - @Override - public OrderEntry[] getOrderEntries() { - return OrderEntry.EMPTY_ARRAY; - } - - @Nullable - OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule) { - return null; - } - - @NotNull - List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule) { - return Collections.emptyList(); - } - @Override public String toString() { return "DirectoryInfo: " + myDebugName; @@ -118,9 +97,6 @@ class NonProjectDirectoryInfo extends DirectoryInfo { return null; } - void assertConsistency() { - } - public int getSourceRootTypeId() { return 0; } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java index 61a6aee9315b..b13df0560292 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java @@ -356,6 +356,38 @@ abstract class OrderEnumeratorBase extends OrderEnumerator implements OrderEnume return false; } + boolean addCustomRootsForModule(OrderRootType type, + ModuleRootModel rootModel, + Collection<VirtualFile> result, + boolean includeProduction, + boolean includeTests) { + for (OrderEnumerationHandler handler : myCustomHandlers) { + final List<String> urls = new ArrayList<String>(); + final boolean added = handler.addCustomModuleRoots(type, rootModel, urls, includeProduction, includeTests); + for (String url : urls) { + ContainerUtil.addIfNotNull(VirtualFileManager.getInstance().findFileByUrl(url), result); + } + + if (added) return true; + } + return false; + } + + boolean addCustomRootUrlsForModule(OrderRootType type, + ModuleRootModel rootModel, + Collection<String> result, + boolean includeProduction, + boolean includeTests) { + for (OrderEnumerationHandler handler : myCustomHandlers) { + final List<String> urls = new ArrayList<String>(); + final boolean added = handler.addCustomModuleRoots(type, rootModel, urls, includeProduction, includeTests); + result.addAll(urls); + + if (added) return true; + } + return false; + } + @Override public boolean isRuntimeOnly() { return myRuntimeOnly; diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java index ea5742cce176..fb9a75176255 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java @@ -240,6 +240,7 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator { } } } + myOrderEnumerator.addCustomRootsForModule(type, rootModel, result, includeProduction, includeTests); } private void collectModuleRootsUrls(OrderRootType type, diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java index 0bb65c600083..e15763716280 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java @@ -69,6 +69,11 @@ public class ProjectFileIndexFacade extends FileIndexFacade { return myFileIndex.isExcluded(file); } + @Override + public boolean isUnderIgnored(@NotNull VirtualFile file) { + return myFileIndex.isUnderIgnored(file); + } + @Nullable @Override public Module getModuleForFile(@NotNull VirtualFile file) { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java index acb6598f55c8..e2417193149e 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java @@ -85,6 +85,11 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn } @Override + public boolean isUnderIgnored(@NotNull VirtualFile file) { + return getInfoForFileOrDirectory(file).isIgnored(); + } + + @Override public Module getModuleForFile(@NotNull VirtualFile file) { if (file instanceof VirtualFileWindow) file = ((VirtualFileWindow)file).getDelegate(); DirectoryInfo info = getInfoForFileOrDirectory(file); @@ -95,7 +100,7 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn @Override @NotNull public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile file) { - return Arrays.asList(getInfoForFileOrDirectory(file).getOrderEntries()); + return Arrays.asList(myDirectoryIndex.getOrderEntries(getInfoForFileOrDirectory(file))); } @Override diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java index 85a098341e4e..8e80670b1f76 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java @@ -131,8 +131,7 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj return (ProjectRootManagerImpl)getInstance(project); } - public ProjectRootManagerImpl(Project project, - DirectoryIndex directoryIndex) { + public ProjectRootManagerImpl(Project project) { myProject = project; myRootsCache = new OrderRootsCache(project); } @@ -143,8 +142,6 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj return ProjectFileIndex.SERVICE.getInstance(myProject); } - private final Map<ModuleRootListener, MessageBusConnection> myListenerAdapters = new HashMap<ModuleRootListener, MessageBusConnection>(); - @Override @NotNull public List<String> getContentRootUrls() { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java index ca68cee3d061..eb04fb6c103e 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java @@ -25,13 +25,16 @@ import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.libraries.LibraryEx; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.LowMemoryWatcher; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.CollectionQuery; +import com.intellij.util.EmptyQuery; import com.intellij.util.Query; +import com.intellij.util.containers.ConcurrentHashSet; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import gnu.trove.TObjectIntHashMap; @@ -41,7 +44,15 @@ import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import java.util.*; -public class RootIndex extends DirectoryIndex { +public class RootIndex { + public static final Comparator<OrderEntry> BY_OWNER_MODULE = new Comparator<OrderEntry>() { + @Override + public int compare(OrderEntry o1, OrderEntry o2) { + String name1 = o1.getOwnerModule().getName(); + String name2 = o2.getOwnerModule().getName(); + return name1.compareTo(name2); + } + }; private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.RootIndex"); private final Set<VirtualFile> myProjectExcludedRoots = ContainerUtil.newHashSet(); @@ -54,11 +65,20 @@ public class RootIndex extends DirectoryIndex { }; private final Map<String, List<VirtualFile>> myDirectoriesByPackageNameCache = ContainerUtil.newConcurrentMap(); + private final Set<String> myNonExistentPackages = new ConcurrentHashSet<String>(); private final InfoCache myInfoCache; private final List<JpsModuleSourceRootType<?>> myRootTypes = ContainerUtil.newArrayList(); private final TObjectIntHashMap<JpsModuleSourceRootType<?>> myRootTypeId = new TObjectIntHashMap<JpsModuleSourceRootType<?>>(); @NotNull private final Project myProject; private volatile Map<VirtualFile, OrderEntry[]> myOrderEntries; + @SuppressWarnings("UnusedDeclaration") + private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() { + @Override + public void run() { + myNonExistentPackages.clear(); + } + }); + // made public for Upsource public RootIndex(@NotNull Project project, @NotNull InfoCache cache) { @@ -145,7 +165,6 @@ public class RootIndex extends DirectoryIndex { } } } - } } } @@ -171,7 +190,8 @@ public class RootIndex extends DirectoryIndex { if (orderEntry instanceof ModuleOrderEntry) { final Module depModule = ((ModuleOrderEntry)orderEntry).getModule(); if (depModule != null) { - VirtualFile[] importedClassRoots = OrderEnumerator.orderEntries(depModule).exportedOnly().recursively().classes().usingCache().getRoots(); + VirtualFile[] importedClassRoots = + OrderEnumerator.orderEntries(depModule).exportedOnly().recursively().classes().usingCache().getRoots(); for (VirtualFile importedClassRoot : importedClassRoots) { depEntries.putValue(importedClassRoot, orderEntry); } @@ -197,7 +217,9 @@ public class RootIndex extends DirectoryIndex { Set<VirtualFile> allRoots = rootInfo.getAllRoots(); for (VirtualFile file : allRoots) { List<VirtualFile> hierarchy = getHierarchy(file, allRoots, rootInfo); - result.put(file, hierarchy == null ? OrderEntry.EMPTY_ARRAY : calcOrderEntries(rootInfo, depEntries, libClassRootEntries, libSourceRootEntries, hierarchy)); + result.put(file, hierarchy == null + ? OrderEntry.EMPTY_ARRAY + : calcOrderEntries(rootInfo, depEntries, libClassRootEntries, libSourceRootEntries, hierarchy)); } myOrderEntries = result; return result; @@ -211,7 +233,8 @@ public class RootIndex extends DirectoryIndex { @Nullable VirtualFile libraryClassRoot = info.findLibraryRootInfo(hierarchy, false); @Nullable VirtualFile librarySourceRoot = info.findLibraryRootInfo(hierarchy, true); Set<OrderEntry> orderEntries = ContainerUtil.newLinkedHashSet(); - orderEntries.addAll(info.getLibraryOrderEntries(hierarchy, libraryClassRoot, librarySourceRoot, libClassRootEntries, libSourceRootEntries)); + orderEntries + .addAll(info.getLibraryOrderEntries(hierarchy, libraryClassRoot, librarySourceRoot, libClassRootEntries, libSourceRootEntries)); for (VirtualFile root : hierarchy) { orderEntries.addAll(depEntries.get(root)); } @@ -224,12 +247,11 @@ public class RootIndex extends DirectoryIndex { } OrderEntry[] array = orderEntries.toArray(new OrderEntry[orderEntries.size()]); - Arrays.sort(array, DirectoryInfoImpl.BY_OWNER_MODULE); + Arrays.sort(array, BY_OWNER_MODULE); return array; } - @Override public void checkConsistency() { for (VirtualFile file : myProjectExcludedRoots) { assert file.exists() : file.getPath() + " does not exist"; @@ -247,21 +269,14 @@ public class RootIndex extends DirectoryIndex { int id = myRootTypes.size(); if (id > DirectoryInfoImpl.MAX_ROOT_TYPE_ID) { - LOG.error("Too many different types of module source roots (" + id + ") registered: " + myRootTypes); + LOG.error("Too many different types of module source roots (" + id + ") registered: " + myRootTypes); } myRootTypes.add(rootType); myRootTypeId.put(rootType, id); return id; } - @Override - public DirectoryInfo getInfoForDirectory(@NotNull VirtualFile dir) { - DirectoryInfo info = getInfoForFile(dir); - return info.isInProject() ? info : null; - } - @NotNull - @Override public DirectoryInfo getInfoForFile(@NotNull VirtualFile file) { if (!file.isValid()) { return NonProjectDirectoryInfo.INVALID; @@ -314,28 +329,41 @@ public class RootIndex extends DirectoryIndex { return info; } - @Override @NotNull public Query<VirtualFile> getDirectoriesByPackageName(@NotNull final String packageName, final boolean includeLibrarySources) { List<VirtualFile> result = myDirectoriesByPackageNameCache.get(packageName); if (result == null) { + if (myNonExistentPackages.contains(packageName)) return EmptyQuery.getEmptyQuery(); + result = ContainerUtil.newSmartList(); - + if (StringUtil.isNotEmpty(packageName) && !StringUtil.startsWithChar(packageName, '.')) { - String shortName = StringUtil.getShortName(packageName); - for (VirtualFile parentDir : getDirectoriesByPackageName(StringUtil.getPackageName(packageName), true)) { - VirtualFile child = parentDir.findChild(shortName); - if (child != null && child.isDirectory() && getInfoForFile(child).isInProject() - && packageName.equals(getPackageName(child))) { - result.add(child); + int i = packageName.lastIndexOf('.'); + while (true) { + String shortName = packageName.substring(i + 1); + String parentPackage = i > 0 ? packageName.substring(0, i) : ""; + for (VirtualFile parentDir : getDirectoriesByPackageName(parentPackage, true)) { + VirtualFile child = parentDir.findChild(shortName); + if (child != null && child.isDirectory() && getInfoForFile(child).isInProject() + && packageName.equals(getPackageName(child))) { + result.add(child); + } } + if (i < 0) break; + i = packageName.lastIndexOf('.', i - 1); } } - result.addAll(myPackagePrefixRoots.get(packageName)); + for (VirtualFile file : myPackagePrefixRoots.get(packageName)) { + if (file.isDirectory()) { + result.add(file); + } + } if (!result.isEmpty()) { myDirectoriesByPackageNameCache.put(packageName, result); + } else { + myNonExistentPackages.add(packageName); } } @@ -351,7 +379,6 @@ public class RootIndex extends DirectoryIndex { return new CollectionQuery<VirtualFile>(result); } - @Override @Nullable public String getPackageName(@NotNull final VirtualFile dir) { if (dir.isDirectory()) { @@ -380,7 +407,6 @@ public class RootIndex extends DirectoryIndex { return parentPackageName.isEmpty() ? subdirName : parentPackageName + "." + subdirName; } - @Override @Nullable public JpsModuleSourceRootType<?> getSourceRootType(@NotNull DirectoryInfo directoryInfo) { return myRootTypes.get(directoryInfo.getSourceRootTypeId()); @@ -487,8 +513,9 @@ public class RootIndex extends DirectoryIndex { if (source && libraryOrSdkSources.contains(root) && (!sourceOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(sourceOfLibraries.get(root)))) { return root; - } else if (!source && libraryOrSdkClasses.contains(root) && - (!classOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(classOfLibraries.get(root)))) { + } + else if (!source && libraryOrSdkClasses.contains(root) && + (!classOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(classOfLibraries.get(root)))) { return root; } } @@ -569,8 +596,11 @@ public class RootIndex extends DirectoryIndex { } } + @NotNull - private Pair<DirectoryInfo, String> calcDirectoryInfo(@NotNull final VirtualFile root, @NotNull final List<VirtualFile> hierarchy, @NotNull RootInfo info) { + private static Pair<DirectoryInfo, String> calcDirectoryInfo(@NotNull final VirtualFile root, + @NotNull final List<VirtualFile> hierarchy, + @NotNull RootInfo info) { VirtualFile moduleContentRoot = info.findModuleRootInfo(hierarchy); VirtualFile libraryClassRoot = info.findLibraryRootInfo(hierarchy, false); VirtualFile librarySourceRoot = info.findLibraryRootInfo(hierarchy, true); @@ -590,23 +620,26 @@ public class RootIndex extends DirectoryIndex { int typeId = moduleSourceRoot != null ? info.rootTypeId.get(moduleSourceRoot) : 0; Module module = parentModuleForExcluded != null ? parentModuleForExcluded : info.contentRootOf.get(moduleContentRoot); - DirectoryInfo directoryInfo = new DirectoryInfoImpl(module, moduleContentRoot, sourceRoot, libraryClassRoot, inModuleSources, inLibrarySource, - parentModuleForExcluded != null, typeId) { - @NotNull - @Override - public OrderEntry[] getOrderEntries() { - OrderEntry[] entries = RootIndex.this.getOrderEntries().get(root); - return entries == null ? OrderEntry.EMPTY_ARRAY : entries; - } - }; + DirectoryInfo directoryInfo = + new DirectoryInfoImpl(root, module, moduleContentRoot, sourceRoot, libraryClassRoot, inModuleSources, inLibrarySource, + parentModuleForExcluded != null, typeId); String packagePrefix = info.calcPackagePrefix(root, hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot); return Pair.create(directoryInfo, packagePrefix); } - + + @NotNull + public OrderEntry[] getOrderEntries(@NotNull DirectoryInfo info) { + if (!(info instanceof DirectoryInfoImpl)) return OrderEntry.EMPTY_ARRAY; + OrderEntry[] entries = this.getOrderEntries().get(((DirectoryInfoImpl)info).getRoot()); + return entries == null ? OrderEntry.EMPTY_ARRAY : entries; + } + public interface InfoCache { - @Nullable DirectoryInfo getCachedInfo(@NotNull VirtualFile dir); - void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info); + @Nullable + DirectoryInfo getCachedInfo(@NotNull VirtualFile dir); + + void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info); } -}
\ No newline at end of file +} diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java index 8ece843b5972..540bfe290645 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java @@ -213,6 +213,8 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel LOG.assertTrue(myContent.contains(entry)); if (entry instanceof RootModelComponentBase) { Disposer.dispose((RootModelComponentBase)entry); + RootModelImpl entryModel = ((RootModelComponentBase)entry).getRootModel(); + LOG.assertTrue(entryModel == this, "Removing from " + this + " content entry obtained from " + entryModel); } myContent.remove(entry); } @@ -731,6 +733,15 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel return myModuleRootManager.getRootModel(); } + @Override + public String toString() { + return "RootModelImpl{" + + "module=" + getModule().getName() + + ", writable=" + myWritable + + ", disposed=" + myDisposed + + '}'; + } + @Nullable @Override public <T> T getModuleExtension(@NotNull final Class<T> klass) { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java index 7a8e9ca01922..fa901849867f 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java @@ -522,10 +522,8 @@ public class LibraryImpl extends TraceableDisposable implements LibraryEx.Modifi private boolean isUnderRoots(@NotNull String url) { for (VirtualFilePointerContainer container : myRoots.values()) { - for (String rootUrl : container.getUrls()) { - if (VfsUtilCore.isEqualOrAncestor(rootUrl, url)) { - return true; - } + if (VfsUtilCore.isUnder(url, Arrays.asList(container.getUrls()))) { + return true; } } return false; |