private @Nullable Function<ProgressIndicator, List<UnknownSdkFix>> createProcessSdksAction(@NotNull UnknownSdkSnapshot snapshot) {
    //it may run on EDT, e.g. in default task
    //we cannot use snapshot#missingSdks here, because it affects other IDEs/languages where our logic is not good enough
    List<UnknownSdk> fixable = filterOnlyAllowedEntries(snapshot.getResolvableSdks());
    List<Sdk> usedSdks = filterOnlyAllowedSdkEntries(snapshot.getKnownSdks());

    if (fixable.isEmpty() && usedSdks.isEmpty()) {
      return null;
    }

    return indicator -> {
             try {
               List<UnknownInvalidSdk> invalidSdks = new ArrayList<>();
               Map<UnknownSdk, UnknownSdkLocalSdkFix> localFixes = new HashMap<>();
               Map<UnknownSdk, UnknownSdkDownloadableSdkFix> downloadFixes = new HashMap<>();

               if (!usedSdks.isEmpty()) {
                 indicator.pushState();
                 indicator.setText(ProjectBundle.message("progress.text.resolving.existing.sdks"));
                 invalidSdks = UnknownInvalidSdk.resolveInvalidSdks(usedSdks);
                 fixable.addAll(invalidSdks);
                 indicator.popState();
               }

               if (!fixable.isEmpty()) {
                 indicator.pushState();
                 indicator.setText(ProjectBundle.message("progress.text.resolving.missing.sdks"));
                 List<UnknownSdkLookup> lookups = collectSdkLookups(indicator);

                 if (!lookups.isEmpty()) {
                   indicator.setText(ProjectBundle.message("progress.text.looking.for.local.sdks"));
                   localFixes = findFixesAndRemoveFixable(indicator, fixable, lookups, UnknownSdkLookup::proposeLocalFix);

                   if (!fixable.isEmpty()) {
                     indicator.setText(ProjectBundle.message("progress.text.looking.for.downloadable.sdks"));
                     downloadFixes = findFixesAndRemoveFixable(indicator, fixable, lookups, UnknownSdkLookup::proposeDownload);
                   }
                 }

                 indicator.popState();
               }

               List<UnknownSdkFix> fixProposals = new ArrayList<>();

               fixable.removeAll(invalidSdks);
               for (UnknownInvalidSdk invalidSdk : invalidSdks) {
                 var localSdkFix = localFixes.remove(invalidSdk);
                 var downloadableSdkFix = downloadFixes.remove(invalidSdk);
                 fixProposals.add(invalidSdk.buildFix(myProject, localSdkFix, downloadableSdkFix));
               }

               var missingSdkSets = new HashSet<UnknownSdk>();
               missingSdkSets.addAll(downloadFixes.keySet());
               missingSdkSets.addAll(localFixes.keySet());
               missingSdkSets.addAll(fixable);

               var allMissingSdks = Set.copyOf(missingSdkSets);

               for (UnknownSdk unknownSdk : allMissingSdks) {
                 String name = unknownSdk.getSdkName();
                 if (name == null) continue;

                 var downloadFix = downloadFixes.get(unknownSdk);
                 var localSdkFix = localFixes.get(unknownSdk);

                 fixProposals.add(UnknownMissingSdk.createMissingSdkFix(myProject, unknownSdk, localSdkFix, downloadFix));
               }

               return List.copyOf(fixProposals);
             } catch (Throwable t) {
               if (t instanceof ControlFlowException) ExceptionUtil.rethrow(t);
               LOG.warn("Failed to complete SDKs lookup. " + t.getMessage(), t);
               return List.of();
             }
         };
  }
private @Nullable Function<ProgressIndicator, List<UnknownSdkFix>> createProcessSdksAction(@NotNull UnknownSdkSnapshot snapshot)