private static void download(@Nullable Project project, @NotNull Runnable onSuccess, @NotNull Runnable onFailure, boolean withReplace) {
    File directory = new File(PathManager.getPluginsPath(), ShLanguage.INSTANCE.getID());
    if (!directory.exists()) {
      //noinspection ResultOfMethodCallIgnored
      directory.mkdirs();
    }

    File shellcheck = new File(directory, SHELLCHECK_BIN);
    File oldShellcheck = new File(directory, "old_" + SHELLCHECK_BIN);
    if (shellcheck.exists()) {
      if (withReplace) {
        boolean successful = renameOldShellcheck(shellcheck, oldShellcheck, onFailure);
        if (!successful) return;
      }
      else {
        setupShellcheckPath(shellcheck, onSuccess, onFailure);
        return;
      }
    }

    String url = getShellcheckDistributionLink();
    if (StringUtil.isEmpty(url)) {
      LOG.debug("Unsupported OS for shellcheck");
      return;
    }

    String downloadName = SHELLCHECK + SHELLCHECK_ARCHIVE_EXTENSION;
    DownloadableFileService service = DownloadableFileService.getInstance();
    DownloadableFileDescription description = service.createFileDescription(url, downloadName);
    FileDownloader downloader = service.createDownloader(Collections.singletonList(description), downloadName);

    Task.Backgroundable task = new Task.Backgroundable(project, message("sh.shellcheck.download.label.text")) {
      @Override
      public void run(@NotNull ProgressIndicator indicator) {
        try {
          List<Pair<File, DownloadableFileDescription>> pairs = downloader.download(directory);
          Pair<File, DownloadableFileDescription> first = ContainerUtil.getFirstItem(pairs);
          File file = first != null ? first.first : null;
          if (file != null) {
            String path = decompressShellcheck(file, directory);
            if (StringUtil.isNotEmpty(path)) {
              FileUtil.setExecutable(new File(path));
              ShSettings.setShellcheckPath(path);
              if (withReplace) {
                LOG.debug("Remove old shellcheck");
                FileUtil.delete(oldShellcheck);
              }
              ApplicationManager.getApplication().invokeLater(onSuccess);
              EXTERNAL_ANNOTATOR_DOWNLOADED_EVENT_ID.log();
            }
          }
        }
        catch (IOException e) {
          LOG.warn("Can't download shellcheck", e);
          if (withReplace) rollbackToOldShellcheck(shellcheck, oldShellcheck);
          ApplicationManager.getApplication().invokeLater(onFailure);
        }
      }
    };
    BackgroundableProcessIndicator processIndicator = new BackgroundableProcessIndicator(task);
    processIndicator.setIndeterminate(false);
    ProgressManager.getInstance().runProcessWithProgressAsynchronously(task, processIndicator);
  }
private static void download(@Nullable Project project, @NotNull Runnable onSuccess, @NotNull Runnable onFailure, boolean withReplace)