mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 13:28:16 +08:00
Add cycle detection to tree rendering
This commit is contained in:
15
src/Spectre.Console/Widgets/CircularTreeException.cs
Normal file
15
src/Spectre.Console/Widgets/CircularTreeException.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the tree being rendered includes a cycle, and cannot be rendered.
|
||||
/// </summary>
|
||||
public sealed class CircularTreeException : Exception
|
||||
{
|
||||
internal CircularTreeException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,8 @@ using Spectre.Console.Rendering;
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// A renderable tree.
|
||||
/// Representation of non-circular tree data.
|
||||
/// Each node added to the tree may only be present in it a single time, in order to facilitate cycle detection.
|
||||
/// </summary>
|
||||
public sealed class Tree : Renderable, IHasTreeNodes
|
||||
{
|
||||
@ -54,6 +55,7 @@ namespace Spectre.Console
|
||||
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
|
||||
{
|
||||
var result = new List<Segment>();
|
||||
var visitedNodes = new HashSet<TreeNode>();
|
||||
|
||||
var stack = new Stack<Queue<TreeNode>>();
|
||||
stack.Push(new Queue<TreeNode>(new[] { _root }));
|
||||
@ -77,6 +79,10 @@ namespace Spectre.Console
|
||||
|
||||
var isLastChild = stackNode.Count == 1;
|
||||
var current = stackNode.Dequeue();
|
||||
if (!visitedNodes.Add(current))
|
||||
{
|
||||
throw new CircularTreeException("Cycle detected in tree - unable to render.");
|
||||
}
|
||||
|
||||
stack.Push(stackNode);
|
||||
|
||||
|
Reference in New Issue
Block a user