private void showConflictNotification(@Nullable Project project,
                                        @NotNull FileNameMatcher matcher,
                                        @NotNull FileTypeManagerImpl.FileTypeWithDescriptor oldFtd,
                                        @NotNull ResolveConflictResult result) {
    FileType resolvedFileType = result.resolved.fileType();
    @Nls String notificationText = result.notification;
    String oldDisplayName = oldFtd.fileType().getDisplayName();
    String resolvedDisplayName = resolvedFileType.getDisplayName();
    if (ApplicationManager.getApplication().isUnitTestMode()) {
      return;
    }

    ApplicationManager.getApplication().invokeLater(() -> {
      NotificationGroup group = NotificationGroupManager.getInstance().getNotificationGroup("File type conflict");
      Notification notification = group.createNotification(
        notificationText,
        result.explanation,
        NotificationType.INFORMATION);
      String message =
        result.resolved.pluginDescriptor().isBundled() ? FileTypesBundle.message("notification.content.conflict.confirm.reassign", resolvedDisplayName) :
        FileTypesBundle.message("notification.content.conflict.confirm.reassign.from.plugin", resolvedDisplayName, result.resolved.pluginDescriptor()
          .getName());
      notification.addAction(NotificationAction.createSimple(message, () -> {
        // mark as removed from fileTypeOld and associated with fileTypeNew
        ApplicationManager.getApplication().runWriteAction(() -> {
          myRemovedMappingTracker.add(matcher, oldFtd.getName(), true);
          ((FileTypeManagerImpl)FileTypeManager.getInstance()).associate(result.resolved, matcher, true);
        });
        notification.expire();
        String m = FileTypesBundle.message("dialog.message.file.pattern.was.assigned.to", matcher.getPresentableString(), resolvedDisplayName);
        showReassignedInfoNotification(project, m);
      }));
      String revertMessage =
        oldFtd.pluginDescriptor().isBundled() ? FileTypesBundle.message("notification.content.revert.reassign", oldDisplayName) :
        FileTypesBundle.message("notification.content.revert.reassign.from.plugin", oldDisplayName, oldFtd.pluginDescriptor().getName());
      notification.addAction(NotificationAction.createSimple(revertMessage, () -> {
        // mark as removed from fileTypeNew and associated with fileTypeOld
        ApplicationManager.getApplication().runWriteAction(() -> {
          myRemovedMappingTracker.add(matcher, resolvedFileType.getName(), true);
          ((FileTypeManagerImpl)FileTypeManager.getInstance()).associate(oldFtd, matcher, true);
        });
        notification.expire();
        String m = FileTypesBundle.message("dialog.message.file.pattern.was.reassigned.back.to", matcher.getPresentableString(), oldDisplayName);
        showReassignedInfoNotification(project, m);
      }));
      if (!oldFtd.fileType().isReadOnly()) {
        notification.addAction(NotificationAction.createSimple(FileTypesBundle.message("notification.content.edit", oldDisplayName),
                                                               () -> editFileType(project, oldFtd.fileType())));
      }
      if (!resolvedFileType.isReadOnly()) {
        notification.addAction(NotificationAction.createSimple(FileTypesBundle.message("notification.content.edit", resolvedDisplayName),
                                                               () -> editFileType(project, resolvedFileType)));
      }
      Notifications.Bus.notify(notification, project);
    }, project == null ? ApplicationManager.getApplication().getDisposed() : project.getDisposed());
  }
private void showConflictNotification(@Nullable Project project,
                                        @NotNull FileNameMatcher matcher,
                                        @NotNull FileTypeManagerImpl.FileTypeWithDescriptor oldFtd,
                                        @NotNull ResolveConflictResult result)