package com.haskforce.index; import com.haskforce.HaskellFileType; import com.haskforce.psi.HaskellFile; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.*; import com.intellij.util.io.EnumeratorStringDescriptor; import com.intellij.util.io.KeyDescriptor; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; public class HaskellModuleIndex extends ScalarIndexExtension<String> { private static final ID<String, Void> HASKELL_MODULE_INDEX = ID.create("HaskellModuleIndex"); private static final int INDEX_VERSION = 0; private static final EnumeratorStringDescriptor KEY_DESCRIPTOR = new EnumeratorStringDescriptor(); private static final MyDataIndexer INDEXER = new MyDataIndexer(); public static final FileBasedIndex.InputFilter HASKELL_MODULE_FILTER = new FileBasedIndex.InputFilter() { @Override public boolean acceptInput(@NotNull VirtualFile file) { //noinspection ObjectEquality return file.getFileType() == HaskellFileType.INSTANCE && file.isInLocalFileSystem(); // to avoid renaming modules that are somewhere in a lib folder // and added as a library. Can get nasty otherwise. } }; @NotNull public static List<HaskellFile> getFilesByModuleName(@NotNull Project project, @NotNull String moduleName, @NotNull GlobalSearchScope searchScope) { final PsiManager psiManager = PsiManager.getInstance(project); Collection<VirtualFile> virtualFiles = getVirtualFilesByModuleName(moduleName, searchScope); return ContainerUtil.mapNotNull(virtualFiles, new Function<VirtualFile, HaskellFile>() { @Override public HaskellFile fun(VirtualFile virtualFile) { final PsiFile psiFile = psiManager.findFile(virtualFile); return psiFile instanceof HaskellFile ? (HaskellFile)psiFile : null; } }); } @NotNull public static Collection<VirtualFile> getVirtualFilesByModuleName(@NotNull String moduleName, @NotNull GlobalSearchScope searchScope) { return FileBasedIndex.getInstance().getContainingFiles(HASKELL_MODULE_INDEX, moduleName, searchScope); } @NotNull @Override public ID<String, Void> getName() { return HASKELL_MODULE_INDEX; } @NotNull @Override public DataIndexer<String, Void, FileContent> getIndexer() { return INDEXER; } @NotNull @Override public KeyDescriptor<String> getKeyDescriptor() { return KEY_DESCRIPTOR; } @NotNull @Override public FileBasedIndex.InputFilter getInputFilter() { return HASKELL_MODULE_FILTER; } @Override public boolean dependsOnFileContent() { return true; } @Override public int getVersion() { return INDEX_VERSION; } private static class MyDataIndexer implements DataIndexer<String, Void, FileContent> { @NotNull @Override public Map<String, Void> map(@NotNull FileContent inputData) { final PsiFile psiFile = inputData.getPsiFile(); final String moduleName = psiFile instanceof HaskellFile ? ((HaskellFile) psiFile).getModuleName() : null; if (moduleName == null) { return Collections.emptyMap(); } return Collections.singletonMap(moduleName, null); } } }