File: Infrastructure\VirtualChars\IVirtualCharService.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 Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.AspNetCore.Analyzers.Infrastructure.VirtualChars;
 
/// <summary>
/// Helper service that takes the raw text of a string token and produces the individual
/// characters that raw string token represents (i.e. with escapes collapsed).  The difference
/// between this and the result from token.ValueText is that for each collapsed character
/// returned the original span of text in the original token can be found.  i.e. if you had the
/// following in C#:
///
/// "G\u006fo"
///
/// Then you'd get back:
///
/// 'G' -> [0, 1) 'o' -> [1, 7) 'o' -> [7, 1)
///
/// This allows for embedded language processing that can refer back to the users' original code
/// instead of the escaped value we're processing.
/// </summary>
internal interface IVirtualCharService
{
    /// <summary>
    /// <para>
    /// Takes in a string token and return the <see cref="VirtualChar"/>s corresponding to each
    /// char of the tokens <see cref="SyntaxToken.ValueText"/>.  In other words, for each char
    /// in ValueText there will be a VirtualChar in the resultant array.  Each VirtualChar will
    /// specify what char the language considers them to represent, as well as the span of text
    /// in the original <see cref="SourceText"/> that the language created that char from. 
    /// </para>
    /// <para>
    /// For most chars this will be a single character span.  i.e. 'c' -> 'c'.  However, for
    /// escapes this may be a multi character span.  i.e. 'c' -> '\u0063'
    /// </para>
    /// <para>
    /// If the token is not a string literal token, or the string literal has any diagnostics on
    /// it, then <see langword="default"/> will be returned.   Additionally, because a
    /// VirtualChar can only represent a single char, while some escape sequences represent
    /// multiple chars, <see langword="default"/> will also be returned in those cases. All
    /// these cases could be relaxed in the future.  But they greatly simplify the
    /// implementation.
    /// </para>
    /// <para>
    /// If this function succeeds, certain invariants will hold.  First, each character in the
    /// sequence of characters in <paramref name="token"/>.ValueText will become a single
    /// VirtualChar in the result array with a matching <see cref="VirtualChar.Rune"/> property.
    /// Similarly, each VirtualChar's <see cref="VirtualChar.Span"/> will abut each other, and
    /// the union of all of them will cover the span of the token's <see
    /// cref="SyntaxToken.Text"/>
    /// *not* including the start and quotes.
    /// </para>
    /// <para>
    /// In essence the VirtualChar array acts as the information explaining how the <see
    /// cref="SyntaxToken.Text"/> of the token between the quotes maps to each character in the
    /// token's <see cref="SyntaxToken.ValueText"/>.
    /// </para>
    /// </summary>
    VirtualCharSequence TryConvertToVirtualChars(SyntaxToken token);
 
    /// <summary>
    /// Produces the appropriate escape version of <paramref name="ch"/> to be placed in a
    /// normal string literal.  For example if <paramref name="ch"/> is the <c>tab</c>
    /// character, then this would produce <c>t</c> as <c>\t</c> is what would go into a string
    /// literal.
    /// </summary>
    bool TryGetEscapeCharacter(VirtualChar ch, out char escapeChar);
}