a more economical way of traversing plugin dependencies (IDEA-90706)

This commit is contained in:
peter
2012-08-30 19:18:05 +02:00
parent 6ce4918e7c
commit 086e1ea5b5
3 changed files with 41 additions and 28 deletions
@@ -28,6 +28,8 @@ import com.intellij.psi.xml.XmlTag;
import com.intellij.refactoring.psi.PropertyUtils;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.LinkedMultiMap;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.xml.*;
import com.intellij.util.xml.reflect.DomExtender;
import com.intellij.util.xml.reflect.DomExtension;
@@ -80,34 +82,48 @@ public class ExtensionDomExtender extends DomExtender<Extensions> {
if (ideaPlugin == null) return;
String prefix = extensions.getDefaultExtensionNs().getStringValue();
if (prefix == null) prefix = extensions.getXmlns().getStringValue();
if (prefix != null) {
prefix += ".";
} else {
prefix = "";
String prefix = getEpPrefix(extensions);
for (IdeaPlugin plugin : getVisiblePlugins(ideaPlugin)) {
final String pluginId = StringUtil.notNullize(plugin.getPluginId(), "com.intellij");
for (ExtensionPoints points : plugin.getExtensionPoints()) {
for (ExtensionPoint point : points.getExtensionPoints()) {
registerExtensionPoint(registrar, point, prefix, pluginId);
}
}
}
registerExtensions(prefix, ideaPlugin, registrar, CollectionFactory.<IdeaPlugin>hashSet());
}
private static void registerExtensions(final String prefix, final IdeaPlugin ideaPlugin, final DomExtensionsRegistrar registrar, Set<IdeaPlugin> visited) {
if (!visited.add(ideaPlugin)) {
private static String getEpPrefix(Extensions extensions) {
String prefix = extensions.getDefaultExtensionNs().getStringValue();
if (prefix == null) prefix = extensions.getXmlns().getStringValue();
return prefix != null ? prefix + "." : "";
}
private static Set<IdeaPlugin> getVisiblePlugins(IdeaPlugin ideaPlugin) {
Set<IdeaPlugin> result = CollectionFactory.hashSet();
MultiMap<String, IdeaPlugin> byId = getPluginMap(ideaPlugin.getManager().getProject());
collectDependencies(ideaPlugin, result, byId);
//noinspection NullableProblems
result.addAll(byId.get(null));
return result;
}
private static MultiMap<String, IdeaPlugin> getPluginMap(final Project project) {
MultiMap<String, IdeaPlugin> byId = new LinkedMultiMap<String, IdeaPlugin>();
for (IdeaPlugin each : IdeaPluginConverter.getAllPlugins(project)) {
byId.putValue(each.getPluginId(), each);
}
return byId;
}
private static void collectDependencies(final IdeaPlugin ideaPlugin, Set<IdeaPlugin> result, final MultiMap<String, IdeaPlugin> byId) {
if (!result.add(ideaPlugin)) {
return;
}
final String pluginId = StringUtil.notNullize(ideaPlugin.getPluginId(), "com.intellij");
for (ExtensionPoints points : ideaPlugin.getExtensionPoints()) {
for (ExtensionPoint point : points.getExtensionPoints()) {
registerExtensionPoint(registrar, point, prefix, pluginId);
}
}
final Collection<String> dependencies = getDependencies(ideaPlugin);
for (IdeaPlugin anotherPlugin : IdeaPluginConverter.collectAllVisiblePlugins(DomUtil.getFile(ideaPlugin))) {
final String value = anotherPlugin.getPluginId();
// value == null for "included" platform plugins like DomPlugin.xml, XmlPlugin.xml, etc.
if (value == null || dependencies.contains(value)) {
registerExtensions(prefix, anotherPlugin, registrar, visited);
for (String id : getDependencies(ideaPlugin)) {
for (IdeaPlugin dep : byId.get(id)) {
collectDependencies(dep, result, byId);
}
}
}
@@ -42,7 +42,7 @@ public class ExtensionNsConverter extends ResolvingConverter<IdeaPlugin> {
final Collection<String> dependencies = ExtensionDomExtender.getDependencies(ideaPlugin);
final List<IdeaPlugin> depPlugins = new ArrayList<IdeaPlugin>();
for (IdeaPlugin plugin : IdeaPluginConverter.collectAllVisiblePlugins(context.getFile())) {
for (IdeaPlugin plugin : IdeaPluginConverter.getAllPlugins(context.getProject())) {
final String value = plugin.getPluginId();
if (value != null && dependencies.contains(value)) {
depPlugins.add(plugin);
@@ -19,7 +19,6 @@ import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.ConvertContext;
@@ -47,7 +46,7 @@ public class IdeaPluginConverter extends ResolvingConverter<IdeaPlugin> {
@NotNull
public Collection<? extends IdeaPlugin> getVariants(final ConvertContext context) {
Collection<IdeaPlugin> plugins = collectAllVisiblePlugins(context.getFile());
Collection<IdeaPlugin> plugins = getAllPlugins(context.getProject());
return new THashSet<IdeaPlugin>(plugins, new TObjectHashingStrategy<IdeaPlugin>() {
@Override
public int computeHashCode(IdeaPlugin object) {
@@ -78,9 +77,7 @@ public class IdeaPluginConverter extends ResolvingConverter<IdeaPlugin> {
return DevKitBundle.message("error.cannot.resolve.plugin", s);
}
public static Collection<IdeaPlugin> collectAllVisiblePlugins(@NotNull XmlFile xmlFile) {
Project project = xmlFile.getProject();
public static Collection<IdeaPlugin> getAllPlugins(final Project project) {
if (DumbService.isDumb(project)) return Collections.emptyList();
GlobalSearchScope scope = GlobalSearchScope.allScope(project);
List<DomFileElement<IdeaPlugin>> files = DomService.getInstance().getFileElements(IdeaPlugin.class, project, scope);