File: Formatting\Indentation\CSharpFormatterTestsBase.cs
Web Access
Project: src\src\EditorFeatures\CSharpTest\Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests)
// 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.
 
#nullable disable
 
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Formatting;
using Microsoft.CodeAnalysis.CSharp.Indentation;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Formatting.Rules;
using Microsoft.CodeAnalysis.Indentation;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Text;
using Xunit;
using Xunit.Abstractions;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Formatting.Indentation;
 
[UseExportProvider]
public class CSharpFormatterTestsBase : CSharpFormattingEngineTestBase
{
    private static readonly TestComposition s_composition = EditorTestCompositions.EditorFeatures.AddParts(typeof(TestFormattingRuleFactoryServiceFactory));
 
    public CSharpFormatterTestsBase(ITestOutputHelper output) : base(output) { }
 
    protected const string HtmlMarkup = """
        <html>
            <body>
                <%{|S1:|}%>
            </body>
        </html>
        """;
    protected const int BaseIndentationOfNugget = 8;
 
    protected static async Task<int> GetSmartTokenFormatterIndentationWorkerAsync(
        EditorTestWorkspace workspace,
        ITextBuffer buffer,
        int indentationLine,
        char ch,
        bool useTabs)
    {
        await TokenFormatWorkerAsync(workspace, buffer, indentationLine, ch, useTabs);
 
        return buffer.CurrentSnapshot.GetLineFromLineNumber(indentationLine).GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(TestEditorOptions.Instance);
    }
 
    protected static async Task<string> TokenFormatAsync(
        EditorTestWorkspace workspace,
        ITextBuffer buffer,
        int indentationLine,
        char ch,
        bool useTabs)
    {
        await TokenFormatWorkerAsync(workspace, buffer, indentationLine, ch, useTabs);
 
        return buffer.CurrentSnapshot.GetText();
    }
 
    private static async Task TokenFormatWorkerAsync(EditorTestWorkspace workspace, ITextBuffer buffer, int indentationLine, char ch, bool useTabs)
    {
        var document = buffer.CurrentSnapshot.GetRelatedDocumentsWithChanges().First();
        var documentSyntax = await ParsedDocument.CreateAsync(document, CancellationToken.None);
 
        var line = documentSyntax.Text.Lines[indentationLine];
 
        var index = line.ToString().LastIndexOf(ch);
        Assert.InRange(index, 0, int.MaxValue);
 
        // get token
        var position = line.Start + index;
        var token = documentSyntax.Root.FindToken(position);
 
        var formattingRuleProvider = workspace.Services.GetService<IHostDependentFormattingRuleFactoryService>();
 
        var rules = ImmutableArray.Create(formattingRuleProvider.CreateRule(documentSyntax, position)).AddRange(Formatter.GetDefaultFormattingRules(document));
 
        var options = new IndentationOptions(
            new CSharpSyntaxFormattingOptions
            {
                LineFormatting = new() { UseTabs = useTabs }
            });
 
        var formatter = new CSharpSmartTokenFormatter(options, rules, (CompilationUnitSyntax)documentSyntax.Root, documentSyntax.Text);
        var changes = formatter.FormatToken(token, CancellationToken.None);
 
        buffer.ApplyChanges(changes);
    }
 
    protected static async Task<int> GetSmartTokenFormatterIndentationAsync(
        string code,
        int indentationLine,
        char ch,
        bool useTabs,
        int? baseIndentation = null,
        TextSpan span = default)
    {
        // create tree service
        using var workspace = EditorTestWorkspace.CreateCSharp(code, composition: s_composition);
 
        if (baseIndentation.HasValue)
        {
            var factory = (TestFormattingRuleFactoryServiceFactory.Factory)workspace.Services.GetService<IHostDependentFormattingRuleFactoryService>();
            factory.BaseIndentation = baseIndentation.Value;
            factory.TextSpan = span;
        }
 
        var buffer = workspace.Documents.First().GetTextBuffer();
        return await GetSmartTokenFormatterIndentationWorkerAsync(workspace, buffer, indentationLine, ch, useTabs);
    }
}