@@ -85,19 +85,6 @@ public static void delay(long millis) {
8585 ProgressManager .checkCanceled ();
8686 }
8787
88- private static long timeOfLastRescanRequest = 0 ;
89- // BackgroundTaskQueue ??? com.intellij.openapi.wm.ex.StatusBarEx#getBackgroundProcesses ???
90- public static void rescanProject (@ NotNull Project project , long delayMilliseconds ) {
91- long timeOfThisRequest = timeOfLastRescanRequest = System .currentTimeMillis ();
92- DCLogger .info ("Full rescan requested. Timestamp: " + timeOfThisRequest );
93- delay (delayMilliseconds );
94- if (timeOfLastRescanRequest > timeOfThisRequest ) return ;
95- DCLogger .info ("Full rescan PERFORMED with Timestamp: " + timeOfThisRequest );
96- AnalysisData .removeAllFilesFromCache (project );
97- // AnalysisData.clearCache(project);
98- updateCachedAnalysisResults (project , null );
99- }
100-
10188 public static void runInBackground (@ NotNull Project project , @ NotNull Runnable runnable ) {
10289 DCLogger .info ("runInBackground requested" );
10390 final ProgressManager progressManager = ProgressManager .getInstance ();
@@ -154,6 +141,7 @@ public static void cancelRunningIndicators(@NotNull Project project) {
154141 forceUnsetBulkMode (project );
155142 getRunningIndicators (project ).forEach (ProgressIndicator ::cancel );
156143 getRunningIndicators (project ).clear ();
144+ projectsWithFullRescanRequested .remove (project );
157145 }
158146
159147 private static final Map <VirtualFile , ProgressIndicator > mapFileProcessed2CancellableIndicator =
@@ -163,18 +151,20 @@ public static void cancelRunningIndicators(@NotNull Project project) {
163151
164152 public static void runInBackgroundCancellable (
165153 @ NotNull PsiFile psiFile , @ NotNull Runnable runnable ) {
166- final String runId = runnable .toString ();
154+ final String s = runnable .toString ();
155+ final String runId = s .substring (s .lastIndexOf ('/' ), s .length () - 1 );
167156 DCLogger .info (
168157 "runInBackgroundCancellable requested for: "
169158 + psiFile .getName ()
170159 + " with Runnable "
171- + runId . substring ( runId . lastIndexOf ( '/' ), runId . length () - 1 ) );
160+ + runId );
172161 final VirtualFile virtualFile = psiFile .getVirtualFile ();
173162
174163 // To proceed multiple PSI events in a bunch (every 100 milliseconds)
175164 Runnable prevRunnable = mapFile2Runnable .put (virtualFile , runnable );
176165 if (prevRunnable != null ) return ;
177- DCLogger .info ("new Background task registered for: " + psiFile .getName ());
166+ DCLogger .info (
167+ "new Background task registered for: " + psiFile .getName () + " with Runnable " + runId );
178168
179169 final Project project = psiFile .getProject ();
180170 ProgressManager .getInstance ()
@@ -206,12 +196,10 @@ && getRunningIndicators(project).contains(prevProgressIndicator)) {
206196
207197 Runnable actualRunnable = mapFile2Runnable .get (virtualFile );
208198 if (actualRunnable != null ) {
209- final String runId = actualRunnable .toString ();
199+ final String s1 = actualRunnable .toString ();
200+ final String runId = s1 .substring (s1 .lastIndexOf ('/' ), s1 .length () - 1 );
210201 DCLogger .info (
211- "New Process started for "
212- + psiFile .getName ()
213- + " with Runnable "
214- + runId .substring (runId .lastIndexOf ('/' ), runId .length () - 1 ));
202+ "New Process started for " + psiFile .getName () + " with Runnable " + runId );
215203 mapFile2Runnable .remove (virtualFile );
216204 actualRunnable .run ();
217205 } else {
@@ -222,6 +210,104 @@ && getRunningIndicators(project).contains(prevProgressIndicator)) {
222210 });
223211 }
224212
213+ public static boolean isFullRescanRequested (@ NotNull Project project ) {
214+ return projectsWithFullRescanRequested .contains (project );
215+ }
216+
217+ private static final Set <Project > projectsWithFullRescanRequested =
218+ ContainerUtil .newConcurrentSet ();
219+
220+ private static final Map <Project , ProgressIndicator > mapProject2CancellableIndicator =
221+ new ConcurrentHashMap <>();
222+ private static final Map <Project , Long > mapProject2CancellableRequestId =
223+ new ConcurrentHashMap <>();
224+
225+ private static final Map <Project , Long > mapProject2RequestId = new ConcurrentHashMap <>();
226+ private static final Set <Long > bulkModeRequests = ContainerUtil .newConcurrentSet ();
227+
228+ public static void rescanInBackgroundCancellableDelayed (
229+ @ NotNull Project project , long delayMilliseconds , boolean inBulkMode ) {
230+ final long requestId = System .currentTimeMillis ();
231+ DCLogger .info (
232+ "rescanInBackgroundCancellableDelayed requested for: "
233+ + project .getName ()
234+ + "] with RequestId "
235+ + requestId );
236+ projectsWithFullRescanRequested .add (project );
237+
238+ // To proceed multiple events in a bunch (every <delayMilliseconds>)
239+ Long prevRequestId = mapProject2RequestId .put (project , requestId );
240+ if (inBulkMode ) bulkModeRequests .add (requestId );
241+ if (prevRequestId != null ) {
242+ if (bulkModeRequests .remove (prevRequestId )) {
243+ RunUtils .unsetBulkMode (project );
244+ }
245+ return ;
246+ }
247+ DCLogger .info (
248+ "new Background Rescan task registered for ["
249+ + project .getName ()
250+ + "] with RequestId "
251+ + requestId );
252+
253+ ProgressManager .getInstance ()
254+ .run (
255+ new Task .Backgroundable (project , "DeepCode: Analysing Files..." ) {
256+ @ Override
257+ public void run (@ NotNull ProgressIndicator indicator ) {
258+
259+ // To let new event cancel the currently running one
260+ ProgressIndicator prevProgressIndicator =
261+ mapProject2CancellableIndicator .put (project , indicator );
262+ if (prevProgressIndicator != null
263+ // can't use prevProgressIndicator.isRunning() due to
264+ // https://youtrack.jetbrains.com/issue/IDEA-241055
265+ && getRunningIndicators (project ).remove (prevProgressIndicator )) {
266+ DCLogger .info (
267+ "Previous Rescan cancelling for "
268+ + project .getName ()
269+ + "\n ProgressIndicator ["
270+ + prevProgressIndicator .toString ()
271+ + "]" );
272+ prevProgressIndicator .cancel ();
273+ }
274+ getRunningIndicators (project ).add (indicator );
275+
276+ // unset BulkMode if cancelled process did run under BulkMode
277+ Long prevRequestId = mapProject2CancellableRequestId .put (project , requestId );
278+ if (prevRequestId != null && bulkModeRequests .remove (prevRequestId )) {
279+ RunUtils .unsetBulkMode (project );
280+ }
281+
282+ // delay to let new consequent requests proceed and cancel current one
283+ // or to let Idea proceed internal events (.gitignore update)
284+ delay (delayMilliseconds );
285+
286+ Long actualRequestId = mapProject2RequestId .get (project );
287+ if (actualRequestId != null ) {
288+ DCLogger .info (
289+ "New Rescan started for ["
290+ + project .getName ()
291+ + "] with RequestId "
292+ + actualRequestId );
293+ mapProject2RequestId .remove (project );
294+
295+ // actual rescan
296+ AnalysisData .removeProjectFromCache (project );
297+ updateCachedAnalysisResults (project , null );
298+
299+ if (bulkModeRequests .remove (actualRequestId )) {
300+ RunUtils .unsetBulkMode (project );
301+ }
302+ } else {
303+ DCLogger .warn ("No actual RequestId found for: " + project .getName ());
304+ }
305+ projectsWithFullRescanRequested .remove (project );
306+ DCLogger .info ("Rescan ending for " + project .getName ());
307+ }
308+ });
309+ }
310+
225311 public static void asyncAnalyseProjectAndUpdatePanel (@ Nullable Project project ) {
226312 final Project [] projects =
227313 (project == null )
0 commit comments