private static List<RootModelImpl> getSortedChangedModels(
      Collection<ModifiableRootModel> rootModels, ModifiableModuleModel moduleModel) {
    List<RootModelImpl> result = ContainerUtil.newArrayListWithCapacity(rootModels.size());

    for (ModifiableRootModel model : rootModels) {
      RootModelImpl rootModel = (RootModelImpl) model;
      if (rootModel.isChanged()) {
        result.add(rootModel);
      }
    }

    DFSTBuilder<RootModelImpl> builder = createDFSTBuilder(result, moduleModel);
    Collections.sort(result, builder.comparator());

    return result;
  }
  private static DFSTBuilder<RootModelImpl> createDFSTBuilder(
      List<RootModelImpl> rootModels, final ModifiableModuleModel moduleModel) {
    final Map<String, RootModelImpl> nameToModel = ContainerUtil.newHashMap();
    for (RootModelImpl rootModel : rootModels) {
      String name = rootModel.getModule().getName();
      LOG.assertTrue(!nameToModel.containsKey(name), name);
      nameToModel.put(name, rootModel);
    }

    Module[] modules = moduleModel.getModules();
    for (Module module : modules) {
      String name = module.getName();
      if (!nameToModel.containsKey(name)) {
        RootModelImpl rootModel =
            ((ModuleRootManagerImpl) ModuleRootManager.getInstance(module)).getRootModel();
        nameToModel.put(name, rootModel);
      }
    }

    final Collection<RootModelImpl> allRootModels = nameToModel.values();
    GraphGenerator.SemiGraph<RootModelImpl> graph =
        new GraphGenerator.SemiGraph<RootModelImpl>() {
          @Override
          public Collection<RootModelImpl> getNodes() {
            return allRootModels;
          }

          @Override
          public Iterator<RootModelImpl> getIn(RootModelImpl rootModel) {
            OrderEnumerator entries =
                rootModel
                    .orderEntries()
                    .withoutSdk()
                    .withoutLibraries()
                    .withoutModuleSourceEntries();
            List<String> namesList =
                entries.process(
                    new RootPolicy<List<String>>() {
                      @Override
                      public List<String> visitModuleOrderEntry(
                          ModuleOrderEntry moduleOrderEntry, List<String> strings) {
                        Module module = moduleOrderEntry.getModule();
                        if (module != null && !module.isDisposed()) {
                          strings.add(module.getName());
                        } else {
                          final Module moduleToBeRenamed =
                              moduleModel.getModuleToBeRenamed(moduleOrderEntry.getModuleName());
                          if (moduleToBeRenamed != null && !moduleToBeRenamed.isDisposed()) {
                            strings.add(moduleToBeRenamed.getName());
                          }
                        }
                        return strings;
                      }
                    },
                    new ArrayList<String>());

            String[] names = ArrayUtil.toStringArray(namesList);
            List<RootModelImpl> result = new ArrayList<RootModelImpl>();
            for (String name : names) {
              RootModelImpl depRootModel = nameToModel.get(name);
              if (depRootModel != null) { // it is ok not to find one
                result.add(depRootModel);
              }
            }
            return result.iterator();
          }
        };
    return new DFSTBuilder<RootModelImpl>(
        new GraphGenerator<RootModelImpl>(new CachingSemiGraph<RootModelImpl>(graph)));
  }