fix "IDEA-221944 Deadlock on opening second project" and support preloading for proje...
[idea/community.git] / platform / editor-ui-ex / src / com / intellij / psi / impl / search / PsiTodoSearchHelperImpl.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.psi.impl.search;
3
4 import com.intellij.ide.todo.TodoConfiguration;
5 import com.intellij.ide.todo.TodoIndexPatternProvider;
6 import com.intellij.openapi.project.Project;
7 import com.intellij.openapi.util.TextRange;
8 import com.intellij.psi.PsiFile;
9 import com.intellij.psi.impl.PsiManagerEx;
10 import com.intellij.psi.impl.cache.TodoCacheManager;
11 import com.intellij.psi.search.IndexPatternOccurrence;
12 import com.intellij.psi.search.PsiTodoSearchHelper;
13 import com.intellij.psi.search.TodoItem;
14 import com.intellij.psi.search.TodoPattern;
15 import com.intellij.psi.search.searches.IndexPatternSearch;
16 import org.jetbrains.annotations.NotNull;
17
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.List;
21
22 public final class PsiTodoSearchHelperImpl implements PsiTodoSearchHelper {
23   private final PsiManagerEx myManager;
24   private static final TodoItem[] EMPTY_TODO_ITEMS = new TodoItem[0];
25
26   public PsiTodoSearchHelperImpl(@NotNull Project project) {
27     myManager = PsiManagerEx.getInstanceEx(project);
28   }
29
30   /**
31    * @deprecated Use {@link #PsiTodoSearchHelperImpl(Project)}
32    */
33   @Deprecated
34   public PsiTodoSearchHelperImpl(@NotNull PsiManagerEx psiManager) {
35     myManager = psiManager;
36   }
37
38   @Override
39   @NotNull
40   public PsiFile[] findFilesWithTodoItems() {
41     return TodoCacheManager.SERVICE.getInstance(myManager.getProject()).getFilesWithTodoItems();
42   }
43
44   @Override
45   @NotNull
46   public TodoItem[] findTodoItems(@NotNull PsiFile file) {
47     return findTodoItems(file, 0, file.getTextLength());
48   }
49
50   @Override
51   @NotNull
52   public TodoItem[] findTodoItems(@NotNull PsiFile file, int startOffset, int endOffset) {
53     final Collection<IndexPatternOccurrence> occurrences =
54       IndexPatternSearch.search(file, TodoIndexPatternProvider.getInstance(), TodoConfiguration.getInstance().isMultiLine()).findAll();
55     if (occurrences.isEmpty()) {
56       return EMPTY_TODO_ITEMS;
57     }
58
59     return processTodoOccurences(startOffset, endOffset, occurrences);
60   }
61
62   @NotNull
63   private static TodoItem[] processTodoOccurences(int startOffset, int endOffset, Collection<? extends IndexPatternOccurrence> occurrences) {
64     List<TodoItem> items = new ArrayList<>(occurrences.size());
65     TextRange textRange = new TextRange(startOffset, endOffset);
66     final TodoItemsCreator todoItemsCreator = new TodoItemsCreator();
67     for (IndexPatternOccurrence occurrence: occurrences) {
68       TextRange occurrenceRange = occurrence.getTextRange();
69       if (textRange.intersectsStrict(occurrenceRange) ||
70           occurrence.getAdditionalTextRanges().stream().anyMatch(r -> textRange.intersectsStrict(r))) {
71         items.add(todoItemsCreator.createTodo(occurrence));
72       }
73     }
74
75     return items.toArray(new TodoItem[0]);
76   }
77
78   @NotNull
79   @Override
80   public TodoItem[] findTodoItemsLight(@NotNull PsiFile file) {
81     return findTodoItemsLight(file, 0, file.getTextLength());
82   }
83
84   @NotNull
85   @Override
86   public TodoItem[] findTodoItemsLight(@NotNull PsiFile file, int startOffset, int endOffset) {
87     final Collection<IndexPatternOccurrence> occurrences =
88       LightIndexPatternSearch.SEARCH.createQuery(
89         new IndexPatternSearch.SearchParameters(file, TodoIndexPatternProvider.getInstance(), TodoConfiguration.getInstance().isMultiLine())
90       ).findAll();
91
92     if (occurrences.isEmpty()) {
93       return EMPTY_TODO_ITEMS;
94     }
95
96     return processTodoOccurences(startOffset, endOffset, occurrences);
97   }
98
99   @Override
100   public int getTodoItemsCount(@NotNull PsiFile file) {
101     int count = TodoCacheManager.SERVICE.getInstance(myManager.getProject()).getTodoCount(file.getVirtualFile(), TodoIndexPatternProvider.getInstance());
102     if (count != -1) return count;
103     return findTodoItems(file).length;
104   }
105
106   @Override
107   public int getTodoItemsCount(@NotNull PsiFile file, @NotNull TodoPattern pattern) {
108     int count = TodoCacheManager.SERVICE.getInstance(myManager.getProject()).getTodoCount(file.getVirtualFile(), pattern.getIndexPattern());
109     if (count != -1) return count;
110     TodoItem[] items = findTodoItems(file);
111     count = 0;
112     for (TodoItem item : items) {
113       if (item.getPattern().equals(pattern)) count++;
114     }
115     return count;
116   }
117
118
119   /**
120    * Returns if td items should be highlighted in editor
121    *
122    * @param file    the file to return the to do count for.
123    * @return if td items should be highlighted in editor. True by default
124    */
125   public boolean shouldHighlightInEditor(@NotNull PsiFile file) {
126     return true;
127   }
128 }