private void runAutoMake() {
   if (ApplicationManager.getApplication().isUnitTestMode()) {
     return;
   }
   final Project[] openProjects = myProjectManager.getOpenProjects();
   if (openProjects.length > 0) {
     final List<RequestFuture> futures = new ArrayList<RequestFuture>();
     for (final Project project : openProjects) {
       if (project.isDefault() || project.isDisposed()) {
         continue;
       }
       final CompilerWorkspaceConfiguration config =
           CompilerWorkspaceConfiguration.getInstance(project);
       if (!config.useOutOfProcessBuild() || !config.MAKE_PROJECT_ON_SAVE) {
         continue;
       }
       final List<String> emptyList = Collections.emptyList();
       final RequestFuture future =
           scheduleBuild(
               project,
               false,
               true,
               emptyList,
               emptyList,
               emptyList,
               Collections.<String, String>emptyMap(),
               new AutoMakeMessageHandler(project));
       if (future != null) {
         futures.add(future);
         synchronized (myAutomakeFutures) {
           myAutomakeFutures.put(future, project);
         }
       }
     }
     try {
       for (RequestFuture future : futures) {
         future.waitFor();
       }
     } finally {
       synchronized (myAutomakeFutures) {
         myAutomakeFutures.keySet().removeAll(futures);
       }
     }
   }
 }
  @Override
  @Nullable
  public Project newProject(
      final String projectName,
      @NotNull String filePath,
      boolean useDefaultProjectSettings,
      boolean isDummy) {
    filePath = toCanonicalName(filePath);

    //noinspection ConstantConditions
    if (LOG_PROJECT_LEAKAGE_IN_TESTS && ApplicationManager.getApplication().isUnitTestMode()) {
      for (int i = 0; i < 42; i++) {
        if (myProjects.size() < MAX_LEAKY_PROJECTS) break;
        System.gc();
        TimeoutUtil.sleep(100);
        System.gc();
      }

      if (myProjects.size() >= MAX_LEAKY_PROJECTS) {
        List<Project> copy = new ArrayList<Project>(myProjects.keySet());
        myProjects.clear();
        throw new TooManyProjectLeakedException(copy);
      }
    }

    ProjectImpl project =
        createProject(
            projectName, filePath, false, ApplicationManager.getApplication().isUnitTestMode());
    try {
      initProject(project, useDefaultProjectSettings ? (ProjectImpl) getDefaultProject() : null);
      if (LOG_PROJECT_LEAKAGE_IN_TESTS) {
        myProjects.put(project, null);
      }
      return project;
    } catch (final Exception e) {
      LOG.info(e);
      Messages.showErrorDialog(message(e), ProjectBundle.message("project.load.default.error"));
    }
    return null;
  }
  protected void handleErrorsOnSave(@NotNull Map<Document, IOException> failures) {
    for (IOException exception : failures.values()) {
      LOG.warn(exception);
    }

    final String text =
        StringUtil.join(
            failures.values(),
            new Function<IOException, String>() {
              @Override
              public String fun(IOException e) {
                return e.getMessage();
              }
            },
            "\n");

    final DialogWrapper dialog =
        new DialogWrapper(null) {
          {
            init();
            setTitle(UIBundle.message("cannot.save.files.dialog.title"));
          }

          @Override
          protected void createDefaultActions() {
            super.createDefaultActions();
            myOKAction.putValue(
                Action.NAME,
                UIBundle.message(
                    myOnClose
                        ? "cannot.save.files.dialog.ignore.changes"
                        : "cannot.save.files.dialog.revert.changes"));
            myOKAction.putValue(DEFAULT_ACTION, null);

            if (!myOnClose) {
              myCancelAction.putValue(Action.NAME, CommonBundle.getCloseButtonText());
            }
          }

          @Override
          protected JComponent createCenterPanel() {
            final JPanel panel = new JPanel(new BorderLayout(0, 5));

            panel.add(
                new JLabel(UIBundle.message("cannot.save.files.dialog.message")),
                BorderLayout.NORTH);

            final JTextPane area = new JTextPane();
            area.setText(text);
            area.setEditable(false);
            area.setMinimumSize(new Dimension(area.getMinimumSize().width, 50));
            panel.add(
                new JBScrollPane(
                    area,
                    ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                    ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER),
                BorderLayout.CENTER);

            return panel;
          }
        };

    dialog.show();

    if (dialog.isOK()) {
      for (Document document : failures.keySet()) {
        reloadFromDisk(document);
      }
    }
  }
  public static boolean doPrepare(
      final Module module, final List<String> errorMessages, final List<String> successMessages) {
    final String pluginName = module.getName();
    final String defaultPath =
        new File(module.getModuleFilePath()).getParent() + File.separator + pluginName;
    final HashSet<Module> modules = new HashSet<Module>();
    PluginBuildUtil.getDependencies(module, modules);
    modules.add(module);
    final Set<Library> libs = new HashSet<Library>();
    for (Module dep : modules) {
      PluginBuildUtil.getLibraries(dep, libs);
    }

    final Map<Module, String> jpsModules = collectJpsPluginModules(module);
    modules.removeAll(jpsModules.keySet());

    final boolean isZip = !libs.isEmpty() || !jpsModules.isEmpty();
    final String oldPath = defaultPath + (isZip ? JAR_EXTENSION : ZIP_EXTENSION);
    final File oldFile = new File(oldPath);
    if (oldFile.exists()) {
      if (Messages.showYesNoDialog(
              module.getProject(),
              DevKitBundle.message("suggest.to.delete", oldPath),
              DevKitBundle.message("info.message"),
              Messages.getInformationIcon())
          == Messages.YES) {
        FileUtil.delete(oldFile);
      }
    }

    final String dstPath = defaultPath + (isZip ? ZIP_EXTENSION : JAR_EXTENSION);
    final File dstFile = new File(dstPath);
    return clearReadOnly(module.getProject(), dstFile)
        && ProgressManager.getInstance()
            .runProcessWithProgressSynchronously(
                new Runnable() {
                  public void run() {

                    final ProgressIndicator progressIndicator =
                        ProgressManager.getInstance().getProgressIndicator();
                    if (progressIndicator != null) {
                      progressIndicator.setText(
                          DevKitBundle.message("prepare.for.deployment.common"));
                      progressIndicator.setIndeterminate(true);
                    }
                    try {
                      File jarFile = preparePluginsJar(module, modules);
                      if (isZip) {
                        processLibrariesAndJpsPlugins(
                            jarFile, dstFile, pluginName, libs, jpsModules, progressIndicator);
                      } else {
                        FileUtil.copy(jarFile, dstFile);
                      }
                      LocalFileSystem.getInstance()
                          .refreshIoFiles(Collections.singleton(dstFile), true, false, null);
                      successMessages.add(
                          DevKitBundle.message(
                              "saved.message", isZip ? 1 : 2, pluginName, dstPath));
                    } catch (final IOException e) {
                      errorMessages.add(e.getMessage() + "\n(" + dstPath + ")");
                    }
                  }
                },
                DevKitBundle.message("prepare.for.deployment", pluginName),
                true,
                module.getProject());
  }
 @TestOnly
 int numberOfListeners() {
   return myPointers.keySet().size();
 }
  @Override
  public void before(@NotNull final List<? extends VFileEvent> events) {
    List<FilePointerPartNode> toFireEvents = new ArrayList<FilePointerPartNode>();
    List<FilePointerPartNode> toUpdateUrl = new ArrayList<FilePointerPartNode>();
    VirtualFilePointer[] toFirePointers;

    synchronized (this) {
      incModificationCount();
      for (VFileEvent event : events) {
        if (event instanceof VFileDeleteEvent) {
          final VFileDeleteEvent deleteEvent = (VFileDeleteEvent) event;
          addPointersUnder(deleteEvent.getFile(), false, "", toFireEvents);

        } else if (event instanceof VFileCreateEvent) {
          final VFileCreateEvent createEvent = (VFileCreateEvent) event;
          addPointersUnder(createEvent.getParent(), true, createEvent.getChildName(), toFireEvents);
        } else if (event instanceof VFileCopyEvent) {
          final VFileCopyEvent copyEvent = (VFileCopyEvent) event;
          addPointersUnder(
              copyEvent.getNewParent(), true, copyEvent.getFile().getName(), toFireEvents);
        } else if (event instanceof VFileMoveEvent) {
          final VFileMoveEvent moveEvent = (VFileMoveEvent) event;
          VirtualFile eventFile = moveEvent.getFile();
          addPointersUnder(moveEvent.getNewParent(), true, eventFile.getName(), toFireEvents);

          List<FilePointerPartNode> nodes = new ArrayList<FilePointerPartNode>();
          addPointersUnder(eventFile, false, "", nodes);
          for (FilePointerPartNode pair : nodes) {
            VirtualFile file = pair.leaf.getFile();
            if (file != null) {
              toUpdateUrl.add(pair);
            }
          }
        } else if (event instanceof VFilePropertyChangeEvent) {
          final VFilePropertyChangeEvent change = (VFilePropertyChangeEvent) event;
          if (VirtualFile.PROP_NAME.equals(change.getPropertyName())) {
            VirtualFile eventFile = change.getFile();
            VirtualFile parent = eventFile.getParent(); // e.g. for LightVirtualFiles
            addPointersUnder(parent, true, change.getNewValue().toString(), toFireEvents);

            List<FilePointerPartNode> nodes = new ArrayList<FilePointerPartNode>();
            addPointersUnder(eventFile, false, "", nodes);
            for (FilePointerPartNode pair : nodes) {
              VirtualFile file = pair.leaf.getFile();
              if (file != null) {
                toUpdateUrl.add(pair);
              }
            }
          }
        }
      }

      myEvents = new ArrayList<EventDescriptor>();
      toFirePointers = toPointers(toFireEvents);
      for (final VirtualFilePointerListener listener : myPointers.keySet()) {
        if (listener == null) continue;
        List<VirtualFilePointer> filtered =
            ContainerUtil.filter(
                toFirePointers,
                new Condition<VirtualFilePointer>() {
                  @Override
                  public boolean value(VirtualFilePointer pointer) {
                    return ((VirtualFilePointerImpl) pointer).getListener() == listener;
                  }
                });
        if (!filtered.isEmpty()) {
          EventDescriptor event =
              new EventDescriptor(
                  listener, filtered.toArray(new VirtualFilePointer[filtered.size()]));
          myEvents.add(event);
        }
      }
    }

    for (EventDescriptor descriptor : myEvents) {
      descriptor.fireBefore();
    }

    if (!toFireEvents.isEmpty()) {
      myBus.syncPublisher(VirtualFilePointerListener.TOPIC).beforeValidityChanged(toFirePointers);
    }

    myPointersToFire = toFireEvents;
    myPointersToUpdateUrl = toUpdateUrl;
  }