diff options
Diffstat (limited to 'platform/core-impl/src/com/intellij/ide/plugins')
-rw-r--r-- | platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java | 79 | ||||
-rw-r--r-- | platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java | 73 |
2 files changed, 55 insertions, 97 deletions
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java deleted file mode 100644 index a6b957c0c508..000000000000 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.ide.plugins; - -import com.intellij.openapi.extensions.PluginId; -import com.intellij.util.containers.HashMap; -import gnu.trove.TObjectIntHashMap; - -import java.util.Comparator; -import java.util.Map; -import java.util.Stack; - -/** - * @author Eugene Zhuravlev - * Date: Aug 3, 2004 - */ -public class PluginDescriptorComparator implements Comparator<IdeaPluginDescriptor>{ - private final TObjectIntHashMap<PluginId> myIdToNumberMap = new TObjectIntHashMap<PluginId>(); - private int myAvailableNumber = 1; - - public PluginDescriptorComparator(IdeaPluginDescriptor[] descriptors){ - final Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap = new HashMap<PluginId, IdeaPluginDescriptor>(); - for (final IdeaPluginDescriptor descriptor : descriptors) { - idToDescriptorMap.put(descriptor.getPluginId(), descriptor); - } - myIdToNumberMap.put(PluginId.getId(PluginManagerCore.CORE_PLUGIN_ID), 0); - - final Stack<PluginId> visited = new Stack<PluginId>(); - for (int idx = 0; idx < descriptors.length && myIdToNumberMap.size() != descriptors.length; idx++) { - assignNumbers(descriptors[idx].getPluginId(), idToDescriptorMap, visited); - visited.clear(); - } - } - - private void assignNumbers(PluginId id, Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap, Stack<PluginId> visited){ - visited.push(id); - try { - final IdeaPluginDescriptor ideaPluginDescriptor = idToDescriptorMap.get(id); - if (ideaPluginDescriptor == null || !ideaPluginDescriptor.isEnabled()) { - // missing optional dependency or already disabled due to cycles - return; - } - final PluginId[] parentIds = ideaPluginDescriptor.getDependentPluginIds(); - for (final PluginId parentId : parentIds) { - if (visited.contains(parentId)) { - //disable plugins in the cycle - ideaPluginDescriptor.setEnabled(false); - break; - } - } - for (PluginId parentId1 : parentIds) { - assignNumbers(parentId1, idToDescriptorMap, visited); - } - if (!myIdToNumberMap.contains(id)) { - myIdToNumberMap.put(id, myAvailableNumber++); - } - } - finally { - visited.pop(); - } - } - - public int compare(IdeaPluginDescriptor d1, IdeaPluginDescriptor d2) { - return myIdToNumberMap.get(d1.getPluginId()) - myIdToNumberMap.get(d2.getPluginId()); - } -} diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java index 8f4fd771ebdd..e834e33f0f42 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java @@ -30,10 +30,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.io.ZipFileCache; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.ArrayUtil; -import com.intellij.util.Function; -import com.intellij.util.PlatformUtilsCore; -import com.intellij.util.ReflectionUtil; +import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.execution.ParametersListUtil; @@ -43,6 +40,7 @@ import com.intellij.util.graph.Graph; import com.intellij.util.graph.GraphGenerator; import com.intellij.util.xmlb.XmlSerializationException; import gnu.trove.THashMap; +import gnu.trove.TIntProcedure; import org.jdom.Document; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -498,26 +496,38 @@ public class PluginManagerCore { } } - @Deprecated - static Comparator<IdeaPluginDescriptor> getPluginDescriptorComparator(Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap) { + static Comparator<IdeaPluginDescriptor> getPluginDescriptorComparator(final Map<PluginId, ? extends IdeaPluginDescriptor> idToDescriptorMap) { final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap); final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph); - /* if (!builder.isAcyclic()) { - final Pair<String,String> circularDependency = builder.getCircularDependency(); - throw new Exception("Cyclic dependencies between plugins are not allowed: \"" + circularDependency.getFirst() + "\" and \"" + circularDependency.getSecond() + ""); + builder.getSCCs().forEach(new TIntProcedure() { + int myTNumber = 0; + public boolean execute(int size) { + if (size > 1) { + for (int j = 0; j < size; j++) { + idToDescriptorMap.get(builder.getNodeByTNumber(myTNumber + j)).setEnabled(false); + } + } + myTNumber += size; + return true; + } + }); } - */ + final Comparator<PluginId> idComparator = builder.comparator(); return new Comparator<IdeaPluginDescriptor>() { @Override public int compare(IdeaPluginDescriptor o1, IdeaPluginDescriptor o2) { - return idComparator.compare(o1.getPluginId(), o2.getPluginId()); + final PluginId pluginId1 = o1.getPluginId(); + final PluginId pluginId2 = o2.getPluginId(); + if (pluginId1.getIdString().equals(CORE_PLUGIN_ID)) return -1; + if (pluginId2.getIdString().equals(CORE_PLUGIN_ID)) return 1; + return idComparator.compare(pluginId1, pluginId2); } }; } - private static Graph<PluginId> createPluginIdGraph(final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap) { + private static Graph<PluginId> createPluginIdGraph(final Map<PluginId, ? extends IdeaPluginDescriptor> idToDescriptorMap) { final List<PluginId> ids = new ArrayList<PluginId>(idToDescriptorMap.keySet()); // this magic ensures that the dependent plugins always follow their dependencies in lexicographic order // needed to make sure that extensions are always in the same order @@ -539,7 +549,7 @@ public class PluginManagerCore { ArrayList<PluginId> plugins = new ArrayList<PluginId>(); for (PluginId dependentPluginId : descriptor.getDependentPluginIds()) { // check for missing optional dependency - IdeaPluginDescriptorImpl dep = idToDescriptorMap.get(dependentPluginId); + IdeaPluginDescriptor dep = idToDescriptorMap.get(dependentPluginId); if (dep != null) { plugins.add(dep.getPluginId()); } @@ -901,7 +911,12 @@ public class PluginManagerCore { loadDescriptorsFromClassPath(result, fromSources ? progress : null); IdeaPluginDescriptorImpl[] pluginDescriptors = result.toArray(new IdeaPluginDescriptorImpl[result.size()]); - Arrays.sort(pluginDescriptors, new PluginDescriptorComparator(pluginDescriptors)); + final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap = new com.intellij.util.containers.HashMap<PluginId, IdeaPluginDescriptorImpl>(); + for (final IdeaPluginDescriptorImpl descriptor : pluginDescriptors) { + idToDescriptorMap.put(descriptor.getPluginId(), descriptor); + } + + Arrays.sort(pluginDescriptors, getPluginDescriptorComparator(idToDescriptorMap)); return pluginDescriptors; } @@ -1110,13 +1125,35 @@ public class PluginManagerCore { final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap); final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph); if (!builder.isAcyclic()) { - final Couple<PluginId> circularDependency = builder.getCircularDependency(); - final PluginId id = circularDependency.getFirst(); - final PluginId parentId = circularDependency.getSecond(); if (!StringUtil.isEmptyOrSpaces(errorMessage)) { errorMessage += "<br>"; } - errorMessage += IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + id + "->" + parentId + "->...->" + id; + + final String cyclePresentation; + if (ApplicationManager.getApplication().isInternal()) { + final List<String> cycles = new ArrayList<String>(); + builder.getSCCs().forEach(new TIntProcedure() { + int myTNumber = 0; + public boolean execute(int size) { + if (size > 1) { + String cycle = ""; + for (int j = 0; j < size; j++) { + cycle += builder.getNodeByTNumber(myTNumber + j).getIdString() + " "; + } + cycles.add(cycle); + } + myTNumber += size; + return true; + } + }); + cyclePresentation = ": " + StringUtil.join(cycles, ";"); + } else { + final Couple<PluginId> circularDependency = builder.getCircularDependency(); + final PluginId id = circularDependency.getFirst(); + final PluginId parentId = circularDependency.getSecond(); + cyclePresentation = id + "->" + parentId + "->...->" + id; + } + errorMessage += IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + cyclePresentation; } prepareLoadingPluginsErrorMessage(errorMessage); |