3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-12-25 15:50:19 +01:00

Record circular dependencies

Dieser Commit ist enthalten in:
Andrew Steinborn 2018-12-13 19:44:25 -05:00
Ursprung 1856fb6aad
Commit 2d54a2c15b

Datei anzeigen

@ -6,7 +6,9 @@ import com.google.common.graph.GraphBuilder;
import com.google.common.graph.MutableGraph; import com.google.common.graph.MutableGraph;
import com.velocitypowered.api.plugin.PluginDescription; import com.velocitypowered.api.plugin.PluginDescription;
import com.velocitypowered.api.plugin.meta.PluginDependency; import com.velocitypowered.api.plugin.meta.PluginDependency;
import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -53,27 +55,38 @@ public class PluginDependencyUtils {
Map<PluginDescription, Mark> marks = new HashMap<>(); Map<PluginDescription, Mark> marks = new HashMap<>();
for (PluginDescription node : graph.nodes()) { for (PluginDescription node : graph.nodes()) {
visitNode(graph, node, marks, sorted); visitNode(graph, node, marks, sorted, new ArrayDeque<>());
} }
return sorted; return sorted;
} }
private static void visitNode(Graph<PluginDescription> dependencyGraph, PluginDescription node, private static void visitNode(Graph<PluginDescription> dependencyGraph, PluginDescription node,
Map<PluginDescription, Mark> marks, List<PluginDescription> sorted) { Map<PluginDescription, Mark> marks, List<PluginDescription> sorted,
Deque<PluginDescription> currentIteration) {
Mark mark = marks.getOrDefault(node, Mark.NOT_VISITED); Mark mark = marks.getOrDefault(node, Mark.NOT_VISITED);
if (mark == Mark.PERMANENT) { if (mark == Mark.PERMANENT) {
return; return;
} else if (mark == Mark.TEMPORARY) { } else if (mark == Mark.TEMPORARY) {
throw new IllegalStateException("Improper plugin dependency graph"); // A circular dependency has been detected.
currentIteration.addLast(node);
StringBuilder loopGraph = new StringBuilder();
for (PluginDescription description : currentIteration) {
loopGraph.append(description.getId());
loopGraph.append(" -> ");
}
loopGraph.setLength(loopGraph.length() - 4);
throw new IllegalStateException("Circular dependency detected: " + loopGraph.toString());
} }
currentIteration.addLast(node);
marks.put(node, Mark.TEMPORARY); marks.put(node, Mark.TEMPORARY);
for (PluginDescription edge : dependencyGraph.successors(node)) { for (PluginDescription edge : dependencyGraph.successors(node)) {
visitNode(dependencyGraph, edge, marks, sorted); visitNode(dependencyGraph, edge, marks, sorted, currentIteration);
} }
marks.put(node, Mark.PERMANENT); marks.put(node, Mark.PERMANENT);
currentIteration.removeLast();
sorted.add(node); sorted.add(node);
} }