background index update for modified files
[fedora-idea.git] / platform / lang-impl / src / com / intellij / util / indexing / UnindexedFilesUpdater.java
blobd8933c9f2bec67b7d8eb4fb9dc57fc90b06883df
1 package com.intellij.util.indexing;
3 import com.intellij.ide.startup.BackgroundableCacheUpdater;
4 import com.intellij.ide.startup.FileContent;
5 import com.intellij.openapi.application.ApplicationManager;
6 import com.intellij.openapi.diagnostic.Logger;
7 import com.intellij.openapi.extensions.Extensions;
8 import com.intellij.openapi.module.Module;
9 import com.intellij.openapi.module.ModuleManager;
10 import com.intellij.openapi.progress.ProgressIndicator;
11 import com.intellij.openapi.progress.ProgressManager;
12 import com.intellij.openapi.project.DumbServiceImpl;
13 import com.intellij.openapi.project.Project;
14 import com.intellij.openapi.roots.*;
15 import com.intellij.openapi.ui.Messages;
16 import com.intellij.openapi.util.Key;
17 import com.intellij.openapi.util.registry.Registry;
18 import com.intellij.openapi.util.registry.RegistryValue;
19 import com.intellij.openapi.vfs.VirtualFile;
20 import com.intellij.openapi.vfs.VirtualFileManager;
21 import com.intellij.util.containers.HashSet;
22 import com.intellij.util.ui.UIUtil;
23 import org.jetbrains.annotations.Nullable;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Set;
30 /**
31 * @author Eugene Zhuravlev
32 * Date: Jan 29, 2008
34 public class UnindexedFilesUpdater implements BackgroundableCacheUpdater {
35 private static final Logger LOG = Logger.getInstance("#com.intellij.util.indexing.UnindexedFilesUpdater");
36 private static final Key<Boolean> DONT_INDEX_AGAIN_KEY = Key.create("DONT_INDEX_AGAIN_KEY");
37 private final FileBasedIndex myIndex;
38 private final Project myProject;
39 private final ProjectRootManager myRootManager;
41 public UnindexedFilesUpdater(final Project project, final ProjectRootManager rootManager, FileBasedIndex index) {
42 myIndex = index;
43 myProject = project;
44 myRootManager = rootManager;
47 public VirtualFile[] queryNeededFiles() {
48 CollectingContentIterator finder = myIndex.createContentIterator();
49 iterateIndexableFiles(finder);
50 final List<VirtualFile> files = finder.getFiles();
51 for (Iterator<VirtualFile> virtualFileIterator = files.iterator(); virtualFileIterator.hasNext();) {
52 VirtualFile file = virtualFileIterator.next();
53 if (file.getUserData(DONT_INDEX_AGAIN_KEY) != null) {
54 virtualFileIterator.remove();
57 return files.toArray(new VirtualFile[files.size()]);
60 public boolean initiallyBackgrounded() {
61 if (ApplicationManager.getApplication().isCommandLine() || ApplicationManager.getApplication().isUnitTestMode()) return false;
62 return Registry.get(DumbServiceImpl.FILE_INDEX_BACKGROUND).asBoolean();
65 public boolean canBeSentToBackground(Collection<VirtualFile> remaining) {
66 if (remaining.size() < 42) {
67 return false;
70 final RegistryValue value = Registry.get(DumbServiceImpl.FILE_INDEX_BACKGROUND);
71 if (!value.asBoolean()) {
72 if (Messages.showDialog(myProject, "<html>" +
73 "Sending indices update to background allows you to immediately use the most<br>" +
74 "basic editing capabilities of IntelliJ IDEA, plus version control operations.<p>" +
75 "However, many advanced functions such as 'Go to Class', advanced error highlighting,<br>" +
76 "refactorings and some others <b>will not be available</b> until indexing is complete.<p>" +
77 "Do you still want to send indexing to background?</html>", "Background Indexing",
78 new String[]{"Yes", "No"}, 1, UIUtil.getInformationIcon()) != 0) {
79 return false;
83 value.setValue("true");
85 return true;
88 public void backgrounded(final Collection<VirtualFile> remaining) {
89 new BackgroundCacheUpdaterRunner(myProject, remaining).processFiles(this);
92 public void processFile(final FileContent fileContent) {
93 fileContent.putUserData(FileBasedIndex.PROJECT, myProject);
94 myIndex.indexFileContent(fileContent);
95 IndexingStamp.flushCache();
98 private void iterateIndexableFiles(final ContentIterator processor) {
99 final ProjectFileIndex projectFileIndex = myRootManager.getFileIndex();
100 // iterate associated libraries
101 final Module[] modules = ModuleManager.getInstance(myProject).getModules();
102 // iterate project content
103 projectFileIndex.iterateContent(processor);
105 ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
107 Set<VirtualFile> visitedRoots = new HashSet<VirtualFile>();
108 for (IndexedRootsProvider provider : Extensions.getExtensions(IndexedRootsProvider.EP_NAME)) {
109 //important not to depend on project here, to support per-project background reindex
110 // each client gives a project to FileBasedIndex
111 final Set<String> rootsToIndex = provider.getRootsToIndex();
112 for (String url : rootsToIndex) {
113 final VirtualFile root = VirtualFileManager.getInstance().findFileByUrl(url);
114 if (visitedRoots.add(root)) {
115 iterateRecursively(root, processor, indicator);
119 for (Module module : modules) {
120 OrderEntry[] orderEntries = ModuleRootManager.getInstance(module).getOrderEntries();
121 for (OrderEntry orderEntry : orderEntries) {
122 if (orderEntry instanceof LibraryOrderEntry || orderEntry instanceof JdkOrderEntry) {
123 final VirtualFile[] libSources = orderEntry.getFiles(OrderRootType.SOURCES);
124 final VirtualFile[] libClasses = orderEntry.getFiles(OrderRootType.CLASSES);
125 for (VirtualFile[] roots : new VirtualFile[][]{libSources, libClasses}) {
126 for (VirtualFile root : roots) {
127 if (visitedRoots.add(root)) {
128 iterateRecursively(root, processor, indicator);
137 private static void iterateRecursively(@Nullable final VirtualFile root, final ContentIterator processor, ProgressIndicator indicator) {
138 if (root != null) {
139 if (indicator != null) {
140 indicator.setText("Scanning files to index");
141 indicator.setText2(root.getPresentableUrl());
144 if (root.isDirectory()) {
145 for (VirtualFile file : root.getChildren()) {
146 if (file.isDirectory()) {
147 iterateRecursively(file, processor, indicator);
149 else {
150 processor.processFile(file);
153 } else {
154 processor.processFile(root);
159 public void updatingDone() {
160 myIndex.flushCaches();
163 public void canceled() {
164 myIndex.flushCaches();