summaryrefslogtreecommitdiff
path: root/platform/core-impl/src/com/intellij/ide
diff options
context:
space:
mode:
Diffstat (limited to 'platform/core-impl/src/com/intellij/ide')
-rw-r--r--platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java79
-rw-r--r--platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java73
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);