File: Symbol.cs
Web Access
Project: src\src\command-line-api\src\System.CommandLine\System.CommandLine.csproj (System.CommandLine)
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.CommandLine.Completions;
using System.Diagnostics;

namespace System.CommandLine
{
    /// <summary>
    /// Defines a named symbol that resides in a hierarchy with parent and child symbols.
    /// </summary>
    public abstract class Symbol
    {
        private protected Symbol(string name, bool allowWhitespace = false)
        {
            Name = ThrowIfEmptyOrWithWhitespaces(name, nameof(name), allowWhitespace);
        }

        /// <summary>
        /// Gets or sets the description of the symbol.
        /// </summary>
        public string? Description { get; set; }

        /// <summary>
        /// Gets the name of the symbol.
        /// </summary>
        public string Name { get; }

        /// <summary>
        /// Represents the first parent node.
        /// </summary>
        internal SymbolNode? FirstParent { get; private set; }

        internal void AddParent(Symbol symbol)
        {
            if (FirstParent == null)
            {
                FirstParent = new SymbolNode(symbol);
            }
            else
            {
                SymbolNode current = FirstParent;
                while (current.Next is not null)
                {
                    current = current.Next;
                }
                current.Next = new SymbolNode(symbol);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the symbol is hidden.
        /// </summary>
        public bool Hidden { get; set; }

        /// <summary>
        /// Gets the parent symbols.
        /// </summary>
        public IEnumerable<Symbol> Parents
        {
            get
            {
                SymbolNode? parent = FirstParent;
                while (parent is not null)
                {
                    yield return parent.Symbol;
                    parent = parent.Next;
                }
            }
        }

        /// <summary>
        /// Gets completions for the symbol.
        /// </summary>
        public abstract IEnumerable<CompletionItem> GetCompletions(CompletionContext context);

        /// <inheritdoc/>
        public override string ToString() => $"{GetType().Name}: {Name}";

        [DebuggerStepThrough]
        internal static string ThrowIfEmptyOrWithWhitespaces(string value, string paramName, bool canContainWhitespaces = false)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                throw new ArgumentException("Names and aliases cannot be null, empty, or consist entirely of whitespace.");
            }

            if (!canContainWhitespaces)
            {
                for (var i = 0; i < value.Length; i++)
                {
                    if (char.IsWhiteSpace(value[i]))
                    {
                        throw new ArgumentException($"Names and aliases cannot contain whitespace: \"{value}\"", paramName);
                    }
                }
            }

            return value;
        }
    }
}