Add cycle detection to tree rendering

This commit is contained in:
Matt Constable
2021-01-14 17:37:22 +00:00
committed by GitHub
parent dee3c01629
commit 994540d97f
4 changed files with 49 additions and 2 deletions

View 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)
{
}
}
}

View File

@ -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);