11package ai .deepcode .jbplugin .core ;
22
33import ai .deepcode .javaclient .DeepCodeRestApi ;
4- import ai .deepcode .javaclient .requests .ExtendBundleRequest ;
5- import ai .deepcode .javaclient .requests .FileContent ;
6- import ai .deepcode .javaclient .requests .FileHash2ContentRequest ;
7- import ai .deepcode .javaclient .requests .FileHashRequest ;
4+ import ai .deepcode .javaclient .requests .*;
85import ai .deepcode .javaclient .responses .*;
96import ai .deepcode .jbplugin .ui .myTodoView ;
107import com .intellij .openapi .components .ServiceManager ;
@@ -164,33 +161,42 @@ public static void updateCachedResultsForFiles(
164161 return ;
165162 }
166163 info ("Update requested for " + psiFiles .size () + " files: " + psiFiles .toString ());
167- Collection <PsiFile > filesToProceed = null ;
168164 try {
169165 MUTEX .lock ();
170166 info ("MUTEX LOCK" );
171167 updateInProgress = true ;
172- filesToProceed =
173- // DeepCodeUtils.computeNonBlockingReadAction(
174- // () ->
168+ Collection <PsiFile > filesToProceed =
175169 psiFiles .stream ()
176170 .filter (Objects ::nonNull )
177- // .filter(PsiFile::isValid)
178171 .filter (file -> !mapFile2Suggestions .containsKey (file ))
179172 .collect (Collectors .toSet ());
180173 if (!filesToProceed .isEmpty ()) {
181- // deepcode ignore checkIsPresent~Optional: collection already checked to be not empty
182- final PsiFile firstFile = filesToProceed .stream ().findFirst ().get ();
174+ // collection already checked to be not empty
175+ final PsiFile firstFile = filesToProceed .iterator ().next ();
176+ final String fileHash = HashContentUtils .getHash (firstFile );
183177 info (
184178 "Files to proceed (not found in cache): "
185179 + filesToProceed .size ()
186180 // fixme debug only
187181 + "\n Hash for first file "
188182 + firstFile .getName ()
189183 + " ["
190- + HashContentUtils . getHash ( firstFile )
184+ + fileHash
191185 + "]" );
192186
193- mapFile2Suggestions .putAll (retrieveSuggestions (project , filesToProceed , filesToRemove ));
187+ if (filesToProceed .size () == 1 && filesToRemove .isEmpty ()) {
188+ // if only one file updates then its most likely from annotator. So we need to get
189+ // suggestions asap:
190+ // we do that through createBundle with fileContent
191+ mapFile2Suggestions .put (firstFile , retrieveSuggestions (firstFile ));
192+ // and then request normal extendBundle later to synchronize results on server
193+ RunUtils .runInBackgroundCancellable (
194+ firstFile ,
195+ () -> retrieveSuggestions (project , filesToProceed , filesToRemove ));
196+ } else {
197+
198+ mapFile2Suggestions .putAll (retrieveSuggestions (project , filesToProceed , filesToRemove ));
199+ }
194200
195201 } else if (!filesToRemove .isEmpty ()) {
196202 info ("Files to remove: " + filesToRemove .size () + " files: " + filesToRemove .toString ());
@@ -238,14 +244,38 @@ private static Map<PsiFile, List<SuggestionForFile>> retrieveSuggestions(
238244 }
239245 // no needs to check login here as it will be checked anyway during every api response's check
240246 // if (!LoginUtils.isLogged(project, false)) return EMPTY_MAP;
241- Map <PsiFile , List <SuggestionForFile >> result ;
247+
248+ List <String > missingFiles = createBundleStep (project , filesToProceed , filesToRemove );
249+
250+ uploadFilesStep (project , filesToProceed , missingFiles );
251+
252+ // ---------------------------------------- Get Analysis
242253 ProgressIndicator progress =
243254 ProgressManager .getInstance ().getProgressIndicator (); // new StatusBarProgress();
244- progress .setIndeterminate (false );
255+ final String bundleId = mapProject2BundleId .getOrDefault (project , "" );
256+ if (bundleId .isEmpty ()) return EMPTY_MAP ; // no sense to proceed without bundleId
257+ long startTime = System .currentTimeMillis ();
258+ progress .setText (WAITING_FOR_ANALYSIS_TEXT );
259+ ProgressManager .checkCanceled ();
260+ GetAnalysisResponse getAnalysisResponse = doGetAnalysis (project , bundleId , progress );
261+ Map <PsiFile , List <SuggestionForFile >> result =
262+ parseGetAnalysisResponse (project , filesToProceed , getAnalysisResponse );
263+ info ("--- Get Analysis took: " + (System .currentTimeMillis () - startTime ) + " milliseconds" );
264+ return result ;
265+ }
245266
246- long startTime ;
247- // ---------------------------------------- Create Bundle
248- startTime = System .currentTimeMillis ();
267+ /**
268+ * Perform costly network request. <b>No cache checks!</b>
269+ *
270+ * @return missingFiles
271+ */
272+ private static List <String > createBundleStep (
273+ @ NotNull Project project ,
274+ @ NotNull Collection <PsiFile > filesToProceed ,
275+ @ NotNull Collection <PsiFile > filesToRemove ) {
276+ ProgressIndicator progress =
277+ ProgressManager .getInstance ().getProgressIndicator (); // new StatusBarProgress();
278+ long startTime = System .currentTimeMillis ();
249279 progress .setText (PREPARE_FILES_TEXT );
250280 info (PREPARE_FILES_TEXT );
251281 ProgressManager .checkCanceled ();
@@ -276,7 +306,6 @@ private static Map<PsiFile, List<SuggestionForFile>> retrieveSuggestions(
276306 CreateBundleResponse createBundleResponse = makeNewBundle (project , mapPath2Hash , filesToRemove );
277307
278308 final String bundleId = createBundleResponse .getBundleId ();
279- if (bundleId .isEmpty ()) return EMPTY_MAP ; // no sense to proceed without bundleId
280309
281310 List <String > missingFiles = createBundleResponse .getMissingFiles ();
282311 info (
@@ -287,36 +316,90 @@ private static Map<PsiFile, List<SuggestionForFile>> retrieveSuggestions(
287316 + bundleId
288317 + "\n missingFiles: "
289318 + missingFiles .size ());
319+ return missingFiles ;
320+ }
290321
291- // ---------------------------------------- Upload Files
292- startTime = System .currentTimeMillis ();
322+ /** Perform costly network request. <b>No cache checks!</b> */
323+ private static void uploadFilesStep (
324+ @ NotNull Project project ,
325+ @ NotNull Collection <PsiFile > filesToProceed ,
326+ @ NotNull List <String > missingFiles ) {
327+ ProgressIndicator progress =
328+ ProgressManager .getInstance ().getProgressIndicator (); // new StatusBarProgress();
329+ long startTime = System .currentTimeMillis ();
293330 progress .setText (UPLOADING_FILES_TEXT );
294331 ProgressManager .checkCanceled ();
295332
296- final int attempts = 5 ;
297- for (int counter = 0 ; counter < attempts ; counter ++) {
298- uploadFiles (project , filesToProceed , missingFiles , bundleId , progress );
299- missingFiles = checkBundle (project , bundleId , progress );
300- if (missingFiles .isEmpty ()) {
301- break ;
302- } else {
303- warn (
304- "Check Bundle found some missingFiles to be NOT uploaded, will try to upload "
305- + (attempts - counter )
306- + " more times:\n missingFiles = "
307- + missingFiles );
333+ final String bundleId = mapProject2BundleId .getOrDefault (project , "" );
334+ if (bundleId .isEmpty ()) {
335+ info ("BundleId is empty" );
336+ } else if (missingFiles .isEmpty ()) {
337+ info ("No missingFiles to Upload" );
338+ } else {
339+ final int attempts = 5 ;
340+ for (int counter = 0 ; counter < attempts ; counter ++) {
341+ uploadFiles (project , filesToProceed , missingFiles , bundleId , progress );
342+ missingFiles = checkBundle (project , bundleId , progress );
343+ if (missingFiles .isEmpty ()) {
344+ break ;
345+ } else {
346+ warn (
347+ "Check Bundle found some missingFiles to be NOT uploaded, will try to upload "
348+ + (attempts - counter )
349+ + " more times:\n missingFiles = "
350+ + missingFiles );
351+ }
308352 }
309353 }
310- // mapPsiFile2Hash.clear();
311- // HashContentUtils.mapPsiFile2Content.clear();
312354 info ("--- Upload Files took: " + (System .currentTimeMillis () - startTime ) + " milliseconds" );
355+ }
313356
314- // ---------------------------------------- Get Analysis
357+ /** Perform costly network request. <b>No cache checks!</b> */
358+ @ NotNull
359+ private static List <SuggestionForFile > retrieveSuggestions (@ NotNull PsiFile file ) {
360+ final Project project = file .getProject ();
361+ List <SuggestionForFile > result ;
362+ long startTime ;
363+ // ---------------------------------------- Create Bundle
315364 startTime = System .currentTimeMillis ();
316- progress . setText ( WAITING_FOR_ANALYSIS_TEXT );
365+ info ( "Creating temporary Bundle from File content" );
317366 ProgressManager .checkCanceled ();
318- GetAnalysisResponse getAnalysisResponse = doGetAnalysis (project , bundleId , progress );
319- result = parseGetAnalysisResponse (project , filesToProceed , getAnalysisResponse , progress );
367+
368+ FileContent fileContent =
369+ new FileContent (
370+ DeepCodeUtils .getDeepCodedFilePath (file ), HashContentUtils .getFileContent (file ));
371+ FileContentRequest fileContentRequest =
372+ new FileContentRequest (Collections .singletonList (fileContent ));
373+
374+ // todo?? it might be cheaper on server side to extend one temporary bundle
375+ // rather then create the new one every time
376+ final CreateBundleResponse createBundleResponse =
377+ DeepCodeRestApi .createBundle (DeepCodeParams .getSessionToken (), fileContentRequest );
378+ isNotSucceed (project , createBundleResponse , "Bad Create/Extend Bundle request: " );
379+
380+ final String bundleId = createBundleResponse .getBundleId ();
381+ if (bundleId .isEmpty ()) return Collections .emptyList (); // no sense to proceed without bundleId
382+
383+ List <String > missingFiles = createBundleResponse .getMissingFiles ();
384+ info (
385+ "--- Create temporary Bundle took: "
386+ + (System .currentTimeMillis () - startTime )
387+ + " milliseconds"
388+ + "\n bundleId: "
389+ + bundleId
390+ + "\n missingFiles: "
391+ + missingFiles );
392+ if (!missingFiles .isEmpty ()) warn ("missingFiles is NOT empty!" );
393+
394+ // ---------------------------------------- Get Analysis
395+ ProgressManager .checkCanceled ();
396+ startTime = System .currentTimeMillis ();
397+ GetAnalysisResponse getAnalysisResponse = doGetAnalysis (project , bundleId , null );
398+ result =
399+ parseGetAnalysisResponse (project , Collections .singleton (file ), getAnalysisResponse )
400+ .get (file );
401+ mapProject2analysisUrl .put (project , "" );
402+
320403 info ("--- Get Analysis took: " + (System .currentTimeMillis () - startTime ) + " milliseconds" );
321404 // progress.stop();
322405 return result ;
@@ -328,10 +411,6 @@ private static void uploadFiles(
328411 @ NotNull List <String > missingFiles ,
329412 @ NotNull String bundleId ,
330413 @ NotNull ProgressIndicator progress ) {
331- if (missingFiles .isEmpty ()) {
332- info ("No missingFiles to Upload" );
333- return ;
334- }
335414 Map <String , PsiFile > mapPath2File =
336415 psiFiles .stream ().collect (Collectors .toMap (DeepCodeUtils ::getDeepCodedFilePath , it -> it ));
337416 int fileCounter = 0 ;
@@ -354,8 +433,8 @@ private static void uploadFiles(
354433 + "\n First broken missingFile: "
355434 + filePath
356435 + "\n Full file path example: "
357- // deepcode ignore checkIsPresent~Optional: collection already is not empty
358- + psiFiles .stream ().findFirst (). get ().getVirtualFile ().getPath ()
436+ // we know collection already is not empty
437+ + psiFiles .iterator ().next ().getVirtualFile ().getPath ()
359438 + "\n BaseDir path: "
360439 + project .getBasePath ();
361440 }
@@ -471,7 +550,7 @@ private static void doUploadFiles(
471550 private static GetAnalysisResponse doGetAnalysis (
472551 @ NotNull Project project ,
473552 @ NotNull String bundleId ,
474- @ NotNull ProgressIndicator progressIndicator ) {
553+ @ Nullable ProgressIndicator progressIndicator ) {
475554 GetAnalysisResponse response ;
476555 int counter = 0 ;
477556 do {
@@ -488,10 +567,12 @@ private static GetAnalysisResponse doGetAnalysis(
488567 if (isNotSucceed (project , response , "Bad GetAnalysis request: " ))
489568 return new GetAnalysisResponse ();
490569 ProgressManager .checkCanceled ();
491- double progress = response .getProgress ();
492- if (progress <= 0 || progress > 1 ) progress = ((double ) counter ) / 200 ;
493- progressIndicator .setFraction (progress );
494- progressIndicator .setText (WAITING_FOR_ANALYSIS_TEXT + (int ) (progress * 100 ) + "% done" );
570+ if (progressIndicator != null ) {
571+ double progress = response .getProgress ();
572+ if (progress <= 0 || progress > 1 ) progress = ((double ) counter ) / 200 ;
573+ progressIndicator .setFraction (progress );
574+ progressIndicator .setText (WAITING_FOR_ANALYSIS_TEXT + (int ) (progress * 100 ) + "% done" );
575+ }
495576 // fixme
496577 if (counter == 200 ) break ;
497578 if (response .getStatus ().equals ("FAILED" )) {
@@ -514,8 +595,7 @@ private static GetAnalysisResponse doGetAnalysis(
514595 private static Map <PsiFile , List <SuggestionForFile >> parseGetAnalysisResponse (
515596 @ NotNull Project project ,
516597 @ NotNull Collection <PsiFile > psiFiles ,
517- GetAnalysisResponse response ,
518- @ NotNull ProgressIndicator progressIndicator ) {
598+ GetAnalysisResponse response ) {
519599 Map <PsiFile , List <SuggestionForFile >> result = new HashMap <>();
520600 if (!response .getStatus ().equals ("DONE" )) return EMPTY_MAP ;
521601 AnalysisResults analysisResults = response .getAnalysisResults ();
0 commit comments