blob: eb8a9ddf55876b625be0b5ae509e1f8fe7ad6d2e [file] [log] [blame]
/*
* Copyright 2000-2012 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 com.intellij.openapi.roots.impl;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class ModuleFileIndexImpl extends FileIndexBase implements ModuleFileIndex {
private final Module myModule;
private final ContentFilter myContentFilter;
public ModuleFileIndexImpl(Module module, DirectoryIndex directoryIndex) {
super(directoryIndex, FileTypeRegistry.getInstance(), module.getProject());
myModule = module;
myContentFilter = new ContentFilter();
}
@Override
public boolean iterateContent(@NotNull ContentIterator iterator) {
VirtualFile[] contentRoots = ModuleRootManager.getInstance(myModule).getContentRoots();
for (VirtualFile contentRoot : contentRoots) {
VirtualFile parent = contentRoot.getParent();
if (parent != null) {
DirectoryInfo parentInfo = myDirectoryIndex.getInfoForFile(parent);
if (parentInfo.isInProject() && myModule.equals(parentInfo.getModule())) continue; // inner content - skip it
}
boolean finished = VfsUtilCore.iterateChildrenRecursively(contentRoot, myContentFilter, iterator);
if (!finished) return false;
}
return true;
}
@Override
public boolean iterateContentUnderDirectory(@NotNull VirtualFile dir, @NotNull ContentIterator iterator) {
return VfsUtilCore.iterateChildrenRecursively(dir, myContentFilter, iterator);
}
@Override
public boolean isInContent(@NotNull VirtualFile fileOrDir) {
DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
return info.isInProject() && myModule.equals(info.getModule());
}
@Override
public boolean isInSourceContent(@NotNull VirtualFile fileOrDir) {
DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
return info.isInModuleSource() && myModule.equals(info.getModule());
}
@Override
@NotNull
public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile fileOrDir) {
return findAllOrderEntriesWithOwnerModule(myModule, myDirectoryIndex.getOrderEntries(getInfoForFileOrDirectory(fileOrDir)));
}
@Override
public OrderEntry getOrderEntryForFile(@NotNull VirtualFile fileOrDir) {
return findOrderEntryWithOwnerModule(myModule, myDirectoryIndex.getOrderEntries(getInfoForFileOrDirectory(fileOrDir)));
}
@Override
public boolean isInTestSourceContent(@NotNull VirtualFile fileOrDir) {
DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
return info.isInModuleSource() && myModule.equals(info.getModule())
&& JavaModuleSourceRootTypes.isTestSourceOrResource(myDirectoryIndex.getSourceRootType(info));
}
@Override
public boolean isUnderSourceRootOfType(@NotNull VirtualFile fileOrDir, @NotNull Set<? extends JpsModuleSourceRootType<?>> rootTypes) {
DirectoryInfo info = getInfoForFileOrDirectory(fileOrDir);
return info.isInModuleSource() && myModule.equals(info.getModule()) && rootTypes.contains(myDirectoryIndex.getSourceRootType(info));
}
@Nullable
static OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule, @NotNull OrderEntry[] orderEntries) {
if (orderEntries.length < 10) {
for (OrderEntry entry : orderEntries) {
if (entry.getOwnerModule() == ownerModule) return entry;
}
return null;
}
int index = Arrays.binarySearch(orderEntries, new FakeOrderEntry(ownerModule), RootIndex.BY_OWNER_MODULE);
return index < 0 ? null : orderEntries[index];
}
@NotNull
private static List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule, @NotNull OrderEntry[] entries) {
if (entries.length == 0) return Collections.emptyList();
if (entries.length == 1) {
OrderEntry entry = entries[0];
return entry.getOwnerModule() == ownerModule ? Arrays.asList(entries) : Collections.<OrderEntry>emptyList();
}
int index = Arrays.binarySearch(entries, new FakeOrderEntry(ownerModule), RootIndex.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);
}
private static class FakeOrderEntry implements OrderEntry {
private final Module myOwnerModule;
public FakeOrderEntry(Module ownerModule) {
myOwnerModule = ownerModule;
}
@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 myOwnerModule;
}
@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();
}
}
private class ContentFilter implements VirtualFileFilter {
@Override
public boolean accept(@NotNull VirtualFile file) {
if (file.isDirectory()) {
DirectoryInfo info = myDirectoryIndex.getInfoForFile(file);
return info.isInProject() && myModule.equals(info.getModule());
}
else {
return !myFileTypeRegistry.isFileIgnored(file);
}
}
}
}