File: StringIndentation\IStringIndentationService.cs
Web Access
Project: src\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.CodeAnalysis.StringIndentation;
 
internal interface IStringIndentationService : ILanguageService
{
    Task<ImmutableArray<StringIndentationRegion>> GetStringIndentationRegionsAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken);
}
 
internal readonly struct StringIndentationRegion(TextSpan indentSpan, ImmutableArray<TextSpan> holeSpans = default)
{
    /// <summary>
    /// The entire span of the indent region.  Given code like:
    /// 
    /// <code>
    /// var x = """
    ///         x
    ///         y
    ///         """;
    /// </code>
    /// 
    /// The span will be the region between the ^'s in:
    /// 
    /// <code>
    /// ^var x = """
    ///         x
    ///         y
    ///         ^""";
    /// </code>
    /// 
    /// The span must be on the start and end lines of the string literal as those are the only lines with content
    /// known to exist.  In other words, the lines with content on them may be entire empty (or still shorter than
    /// the indent column), so there's no actual position to associate the span with.
    /// 
    /// The start of the span should be the start of the line that the string literal starts on.  The end of the
    /// span should be at the start of the ending quotes of the literal.
    /// 
    /// The tagger can then use this span to draw a line like so:
    /// 
    /// <code>
    /// var x = """
    ///        |x
    ///        |y
    ///         """;
    /// </code>
    /// </summary>
    public readonly TextSpan IndentSpan = indentSpan;
 
    /// <summary>
    /// Regions of the literal that count as 'code holes' and which the lines of the tagger should not draw through.
    /// For example, given code like:
    /// 
    /// <code>
    /// var x = $"""
    ///         x
    ///         {
    ///             1 + 1
    ///         } xcont
    ///         y
    ///         {
    ///             2 + 2
    ///         } ycont
    ///         z
    ///         """;
    /// </code>
    /// 
    /// Then there will be two holes demarcated by the ^'s in the following:
    /// 
    /// <code>
    /// var x = $"""
    ///         x
    ///         ^{
    ///             1 + 1
    ///         }^ xcont
    ///         y
    ///         ^{
    ///             2 + 2
    ///         }^ ycont
    ///         z
    ///         """;
    /// </code>
    /// 
    /// If the line draw were to intersect one of these spans it will not be drawn, causing the following to be
    /// presented:
    /// 
    /// <code>
    /// var x = $"""
    ///        |x
    ///        |{
    ///             1 + 1
    ///         } xcont
    ///        |y
    ///        |{
    ///             2 + 2
    ///         } ycont
    ///        |z
    ///         """;
    /// </code>
    /// 
    /// </summary>
    public readonly ImmutableArray<TextSpan> OrderedHoleSpans = holeSpans.NullToEmpty().Sort();
}