String (IdeaPluginDescriptorImpl @NotNull [] descriptors) { // place breakpoint in PluginManagerCore#loadDescriptors before sorting var sb = new StringBuilder("<root>"); Function<String, String> escape = s -> { return s.equals("com.intellij") || s.startsWith("com.intellij.modules.") ? s : "-" + s.replace(".", "-") + "-"; }; for (var d : descriptors) { sb.append("\n <idea-plugin url=\"file://out/").append(d.getPluginPath().getFileName().getParent()).append("/META-INF/plugin.xml\">"); sb.append("\n <id>").append(escape.apply(d.getPluginId().getIdString())).append("</id>"); sb.append("\n <name>").append(StringUtil.escapeXmlEntities(d.getName())).append("</name>"); for (PluginId module : d.modules) { sb.append("\n <module value=\"").append(module.getIdString()).append("\"/>"); } for (var dependency : d.pluginDependencies) { if (!dependency.isOptional()) { sb.append("\n <depends>").append(escape.apply(dependency.getPluginId().getIdString())).append("</depends>"); } else { var optionalConfigPerId = dependency.subDescriptor; if (optionalConfigPerId == null) { sb.append("\n <depends optional=\"true\" config-file=\"???\">") .append(escape.apply(dependency.getPluginId().getIdString())) .append("</depends>"); } else { sb.append("\n <depends optional=\"true\" config-file=\"") .append(optionalConfigPerId.getPluginPath().getFileName().toString()) .append("\">") .append(escape.apply(dependency.getPluginId().getIdString())) .append("</depends>"); } } } sb.append("\n </idea-plugin>"); } sb.append("\n</root>"); return sb.toString(); }