@NotNull
  protected Collection<AbstractTreeNode<?>> modulesAndGroups(@NotNull Collection<? extends ModuleDescription> modules) {
    if (getSettings().isFlattenModules()) {
      return ContainerUtil.mapNotNull(modules, moduleDescription -> {
        try {
          return createModuleNode(moduleDescription);
        }
        catch (InvocationTargetException | NoSuchMethodException | InstantiationException | IllegalAccessException e) {
          LOG.error(e);
          return null;
        }
      });
    }

    Set<String> topLevelGroups = new LinkedHashSet<>();
    Set<ModuleDescription> nonGroupedModules = new LinkedHashSet<>(modules);
    List<String> commonGroupsPath = null;
    for (final ModuleDescription moduleDescription : modules) {
      final List<String> path = ModuleGrouper.instanceFor(myProject).getGroupPath(moduleDescription);
      if (!path.isEmpty()) {
        final String topLevelGroupName = path.get(0);
        topLevelGroups.add(topLevelGroupName);
        nonGroupedModules.remove(moduleDescription);
        if (commonGroupsPath == null) {
          commonGroupsPath = path;
        }
        else {
          int commonPartLen = Math.min(commonGroupsPath.size(), path.size());
          OptionalLong firstDifference = StreamEx.zip(commonGroupsPath.subList(0, commonPartLen), path.subList(0, commonPartLen), String::equals).indexOf(false);
          if (firstDifference.isPresent()) {
            commonGroupsPath = commonGroupsPath.subList(0, (int)firstDifference.getAsLong());
          }
          else if (commonPartLen < commonGroupsPath.size()) {
            commonGroupsPath = commonGroupsPath.subList(0, commonPartLen);
          }
        }
      }
    }

    List<AbstractTreeNode<?>> result = new ArrayList<>();
    try {
      if (modules.size() > 1) {
        if (commonGroupsPath != null && !commonGroupsPath.isEmpty()) {
          result.add(createModuleGroupNode(new ModuleGroup(commonGroupsPath)));
        }
        else {
          for (String groupPath : topLevelGroups) {
            result.add(createModuleGroupNode(new ModuleGroup(Collections.singletonList(groupPath))));
          }
        }
        for (ModuleDescription moduleDescription : nonGroupedModules) {
          ContainerUtil.addIfNotNull(result, createModuleNode(moduleDescription));
        }
      }
      else {
        ContainerUtil.addIfNotNull(result, createModuleNode(ContainerUtil.getFirstItem(modules)));
      }
    }
    catch (ProcessCanceledException e) {
      throw e;
    }
    catch (Exception e) {
      LOG.error(e);
      return new ArrayList<>();
    }
    return result;
  }
@NotNull
  protected Collection<AbstractTreeNode<?>> modulesAndGroups(@NotNull Collection<? extends ModuleDescription> modules)