@Nullable
  @Override
  protected DiffRequestChain getDiffRequestChain(@NotNull AnActionEvent e) {
    Project project = e.getProject();
    DiffRequest diffRequest = getDiffRequest(e);
    if (diffRequest != null) {
      return new SimpleDiffRequestChain(diffRequest);
    }

    VirtualFile file1;
    VirtualFile file2;
    VirtualFile baseFile = null;

    VirtualFile[] files = e.getRequiredData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
    if (files.length == 1) {
      file1 = files[0];
      file2 = getOtherFile(project, file1);
      if (file2 == null || !hasContent(file2)) return null;
    }
    else if (files.length == 2) {
      file1 = files[0];
      file2 = files[1];
    }
    else {
      file1 = files[0];
      baseFile = files[1];
      file2 = files[2];
    }

    // getOtherFile() shows dialog that can invalidate files
    if (!file1.isValid() || !file2.isValid() || (baseFile != null && !baseFile.isValid())) return null;

    Set<Type> types = ContainerUtil.map2Set(files, CompareFilesAction::getType);
    if (types.contains(Type.DIRECTORY)) FeatureUsageTracker.getInstance().triggerFeatureUsed("dir.diff");
    if (types.contains(Type.ARCHIVE)) FeatureUsageTracker.getInstance().triggerFeatureUsed("jar.diff");
    if ("ipynb".equals(file1.getExtension()) && "ipynb".equals(file2.getExtension())) {
      FeatureUsageTracker.getInstance().triggerFeatureUsed("jupyter.compare.notebooks");
    }

    return createMutableChainFromFiles(project, file1, file2, baseFile);
  }
@Nullable
  @Override
  protected DiffRequestChain getDiffRequestChain(@NotNull AnActionEvent e)