public void compile() throws CompilerException, CacheCorruptedException {
    Application application = ApplicationManager.getApplication();
    try {
      if (!myFilesToCompile.isEmpty()) {
        if (application.isUnitTestMode()) {
          saveTestData();
        }
        compileModules(buildModuleToFilesMap(myFilesToCompile));
      }
    } catch (SecurityException e) {
      throw new CompilerException(
          CompilerBundle.message("error.compiler.process.not.started", e.getMessage()), e);
    } catch (IllegalArgumentException e) {
      throw new CompilerException(e.getMessage(), e);
    } finally {
      for (final VirtualFile file : myModuleToTempDirMap.values()) {
        if (file != null) {
          final File ioFile = new File(file.getPath());
          FileUtil.asyncDelete(ioFile);
        }
      }
      myModuleToTempDirMap.clear();
    }

    if (!myFilesToCompile.isEmpty()
        && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
      // package-info.java hack
      final List<TranslatingCompiler.OutputItem> outputs =
          new ArrayList<TranslatingCompiler.OutputItem>();
      ApplicationManager.getApplication()
          .runReadAction(
              new Runnable() {
                public void run() {
                  for (final VirtualFile file : myFilesToCompile) {
                    if (PACKAGE_ANNOTATION_FILE_NAME.equals(file.getName())
                        && !myProcessedPackageInfos.contains(file)) {
                      outputs.add(new OutputItemImpl(file));
                    }
                  }
                }
              });
      if (!outputs.isEmpty()) {
        mySink.add(null, outputs, VirtualFile.EMPTY_ARRAY);
      }
    }
  }
  private static void readFavoritesOneLevel(
      Element list, Project project, Collection<TreeItem<Pair<AbstractUrl, String>>> result) {
    final List listChildren = list.getChildren(FAVORITES_ROOT);
    if (listChildren == null || listChildren.isEmpty()) return;

    for (Object favorite : listChildren) {
      final Element favoriteElement = (Element) favorite;
      final String className = favoriteElement.getAttributeValue(CLASS_NAME);
      final AbstractUrl abstractUrl = readUrlFromElement(favoriteElement, project);
      if (abstractUrl != null) {
        final TreeItem<Pair<AbstractUrl, String>> treeItem =
            new TreeItem<Pair<AbstractUrl, String>>(Pair.create(abstractUrl, className));
        result.add(treeItem);
        readFavoritesOneLevel(favoriteElement, project, treeItem.getChildren());
      }
    }
  }
  public boolean setProjectRoot(@NotNull final VirtualFile projectRoot) {
    if (projectRoot.equals(myProjectRoot)) {
      return true;
    }

    boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode();

    myProjectRoot = projectRoot;
    if (!unitTestMode && projectRoot instanceof VirtualDirectoryImpl) {
      ((VirtualDirectoryImpl) projectRoot).refreshAndFindChild("deps");
    }

    ProgressManager.getInstance()
        .run(
            new Task.Modal(getCurrentProject(), "Scanning Rebar projects", true) {
              public void run(@NotNull final ProgressIndicator indicator) {

                List<VirtualFile> rebarConfigFiles = findRebarConfigs(myProjectRoot, indicator);
                final LinkedHashSet<ImportedOtpApp> importedOtpApps =
                    new LinkedHashSet<ImportedOtpApp>(rebarConfigFiles.size());

                VfsUtilCore.visitChildrenRecursively(
                    projectRoot,
                    new VirtualFileVisitor() {
                      @Override
                      public boolean visitFile(@NotNull VirtualFile file) {
                        indicator.checkCanceled();

                        if (file.isDirectory()) {
                          indicator.setText2(file.getPath());
                          if (isExamplesDirectory(file)
                              || isRelDirectory(projectRoot.getPath(), file.getPath()))
                            return false;
                        }

                        ContainerUtil.addAllNotNull(importedOtpApps, createImportedOtpApp(file));
                        return true;
                      }
                    });

                myFoundOtpApps = ContainerUtil.newArrayList(importedOtpApps);
              }
            });

    Collections.sort(
        myFoundOtpApps,
        new Comparator<ImportedOtpApp>() {
          @Override
          public int compare(ImportedOtpApp o1, ImportedOtpApp o2) {
            int nameCompareResult =
                String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName());
            if (nameCompareResult == 0) {
              return String.CASE_INSENSITIVE_ORDER.compare(
                  o1.getRoot().getPath(), o2.getRoot().getPath());
            }
            return nameCompareResult;
          }
        });

    mySelectedOtpApps = myFoundOtpApps;
    return !myFoundOtpApps.isEmpty();
  }
  public synchronized boolean addRoot(
      @NotNull String name,
      @NotNull List<AbstractTreeNode> parentElements,
      final AbstractTreeNode newElement,
      @Nullable AbstractTreeNode sibling) {
    final List<TreeItem<Pair<AbstractUrl, String>>> items = myName2FavoritesRoots.get(name);
    if (items == null) return false;
    AbstractUrl url = createUrlByElement(newElement.getValue(), myProject);
    if (url == null) return false;
    final TreeItem<Pair<AbstractUrl, String>> newItem =
        new TreeItem<Pair<AbstractUrl, String>>(Pair.create(url, newElement.getClass().getName()));

    if (parentElements.isEmpty()) {
      // directly to list
      if (sibling != null) {
        TreeItem<Pair<AbstractUrl, String>> after = null;
        AbstractUrl siblingUrl = createUrlByElement(sibling.getValue(), myProject);
        int idx = -1;
        for (int i = 0; i < items.size(); i++) {
          TreeItem<Pair<AbstractUrl, String>> item = items.get(i);
          if (item.getData().getFirst().equals(siblingUrl)) {
            idx = i;
            break;
          }
        }
        if (idx != -1) {
          items.add(idx, newItem);
        } else {
          items.add(newItem);
        }
      } else {
        items.add(newItem);
      }

      fireListeners.rootsChanged(name);
      return true;
    }

    Collection<TreeItem<Pair<AbstractUrl, String>>> list = items;
    TreeItem<Pair<AbstractUrl, String>> item = null;
    for (AbstractTreeNode obj : parentElements) {
      AbstractUrl objUrl = createUrlByElement(obj.getValue(), myProject);
      item = findNextItem(objUrl, list);
      if (item == null) return false;
      list = item.getChildren();
    }

    if (sibling != null) {
      TreeItem<Pair<AbstractUrl, String>> after = null;
      AbstractUrl siblingUrl = createUrlByElement(sibling.getValue(), myProject);
      for (TreeItem<Pair<AbstractUrl, String>> treeItem : list) {
        if (treeItem.getData().getFirst().equals(siblingUrl)) {
          after = treeItem;
          break;
        }
      }
      if (after == null) {
        item.addChild(newItem);
      } else {
        item.addChildAfter(newItem, after);
      }
    } else {
      item.addChild(newItem);
    }
    fireListeners.rootsChanged(name);
    return true;
  }