File: Infrastructure\EmbeddedSyntax\EmbeddedSyntaxToken.cs
Web Access
Project: src\src\Framework\AspNetCoreAnalyzers\src\Analyzers\Microsoft.AspNetCore.App.Analyzers.csproj (Microsoft.AspNetCore.App.Analyzers)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Immutable;
using System.Diagnostics;
using System.Text;
using Microsoft.AspNetCore.Analyzers.Infrastructure.VirtualChars;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.AspNetCore.Analyzers.Infrastructure.EmbeddedSyntax;
 
internal struct EmbeddedSyntaxToken<TSyntaxKind> where TSyntaxKind : struct
{
    public readonly TSyntaxKind Kind;
    public readonly VirtualCharSequence VirtualChars;
    internal readonly ImmutableArray<EmbeddedDiagnostic> Diagnostics;
 
    /// <summary>
    /// Returns the value of the token. For example, if the token represents an integer capture,
    /// then this property would return the actual integer.
    /// </summary>
    public readonly object? Value;
 
    public EmbeddedSyntaxToken(
        TSyntaxKind kind,
        VirtualCharSequence virtualChars,
        ImmutableArray<EmbeddedDiagnostic> diagnostics, object? value)
    {
        Debug.Assert(!diagnostics.IsDefault);
        Kind = kind;
        VirtualChars = virtualChars;
        Diagnostics = diagnostics;
        Value = value;
    }
 
    public bool IsMissing => VirtualChars.Length == 0;
 
    public EmbeddedSyntaxToken<TSyntaxKind> AddDiagnosticIfNone(EmbeddedDiagnostic diagnostic)
        => Diagnostics.Length > 0 ? this : WithDiagnostics(ImmutableArray.Create(diagnostic));
 
    public EmbeddedSyntaxToken<TSyntaxKind> WithDiagnostics(ImmutableArray<EmbeddedDiagnostic> diagnostics)
        => With(diagnostics: diagnostics);
 
    public EmbeddedSyntaxToken<TSyntaxKind> With(
        Optional<TSyntaxKind> kind = default,
        Optional<VirtualCharSequence> virtualChars = default,
        Optional<ImmutableArray<EmbeddedDiagnostic>> diagnostics = default,
        Optional<object> value = default)
    {
        return new EmbeddedSyntaxToken<TSyntaxKind>(
            kind.HasValue ? kind.Value : Kind,
            virtualChars.HasValue ? virtualChars.Value : VirtualChars,
            diagnostics.HasValue ? diagnostics.Value : Diagnostics,
            value.HasValue ? value.Value : Value);
    }
 
    public TextSpan GetSpan()
        => EmbeddedSyntaxHelpers.GetSpan(VirtualChars);
 
    public TextSpan? GetFullSpan()
    {
        if (VirtualChars.Length == 0)
        {
            return null;
        }
 
        var start = VirtualChars.Length == 0 ? int.MaxValue : VirtualChars[0].Span.Start;
        var end = VirtualChars.Length == 0 ? int.MinValue : VirtualChars[VirtualChars.Length - 1].Span.End;
 
        return TextSpan.FromBounds(start, end);
    }
 
    public override string ToString()
    {
        var sb = new StringBuilder();
        WriteTo(sb);
        return sb.ToString();
    }
 
    /// <summary>
    /// Writes the token to a stringbuilder.
    /// </summary>
    public void WriteTo(StringBuilder sb)
    {
        sb.Append(VirtualChars.CreateString());
    }
}