File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\Formatting\AbstractSyntaxFormatting.cs
Web Access
Project: src\src\CodeStyle\Core\Analyzers\Microsoft.CodeAnalysis.CodeStyle.csproj (Microsoft.CodeAnalysis.CodeStyle)
// 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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Formatting.Rules;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared;
using Microsoft.CodeAnalysis.Shared.Collections;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.CodeAnalysis.Formatting;
 
internal abstract class AbstractSyntaxFormatting : ISyntaxFormatting
{
    private static readonly Func<TextSpan, bool> s_notEmpty = s => !s.IsEmpty;
 
    public abstract SyntaxFormattingOptions DefaultOptions { get; }
    public abstract SyntaxFormattingOptions GetFormattingOptions(IOptionsReader options);
 
    public abstract ImmutableArray<AbstractFormattingRule> GetDefaultFormattingRules();
 
    protected abstract IFormattingResult CreateAggregatedFormattingResult(SyntaxNode node, IList<AbstractFormattingResult> results, TextSpanMutableIntervalTree? formattingSpans = null);
 
    protected abstract AbstractFormattingResult Format(SyntaxNode node, SyntaxFormattingOptions options, ImmutableArray<AbstractFormattingRule> rules, SyntaxToken startToken, SyntaxToken endToken, CancellationToken cancellationToken);
 
    public IFormattingResult GetFormattingResult(SyntaxNode node, IEnumerable<TextSpan>? spans, SyntaxFormattingOptions options, ImmutableArray<AbstractFormattingRule> rules, CancellationToken cancellationToken)
    {
        IReadOnlyList<TextSpan> spansToFormat;
 
        if (spans == null)
        {
            spansToFormat = node.FullSpan.IsEmpty ? [] : [node.FullSpan];
        }
        else
        {
            spansToFormat = new NormalizedTextSpanCollection(spans.Where(s_notEmpty));
        }
 
        if (spansToFormat.Count == 0)
        {
            return CreateAggregatedFormattingResult(node, results: []);
        }
 
        if (rules.IsDefault)
            rules = GetDefaultFormattingRules();
 
        List<AbstractFormattingResult>? results = null;
        foreach (var (startToken, endToken) in node.ConvertToTokenPairs(spansToFormat))
        {
            if (node.IsInvalidTokenRange(startToken, endToken))
            {
                continue;
            }
 
            results ??= [];
            results.Add(Format(node, options, rules, startToken, endToken, cancellationToken));
        }
 
        // quick simple case check
        if (results == null)
        {
            return CreateAggregatedFormattingResult(node, results: []);
        }
 
        if (results.Count == 1)
        {
            return results[0];
        }
 
        // more expensive case
        return CreateAggregatedFormattingResult(node, results);
    }
}