| File: src\roslyn\src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\Formatting\Engine\ChainedFormattingRules.cs | Web Access |
| Project: src\roslyn\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces) |
// 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.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Reflection; using Microsoft.CodeAnalysis.Formatting.Rules; using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Formatting; internal sealed class ChainedFormattingRules { private static readonly ConcurrentDictionary<(Type type, string name), Type?> s_typeImplementingMethod = []; private readonly ImmutableArray<AbstractFormattingRule> _formattingRules; private readonly SyntaxFormattingOptions _options; private readonly ImmutableArray<AbstractFormattingRule> _addSuppressOperationsRules; private readonly ImmutableArray<AbstractFormattingRule> _addAnchorIndentationOperationsRules; private readonly ImmutableArray<AbstractFormattingRule> _addIndentBlockOperationsRules; private readonly ImmutableArray<AbstractFormattingRule> _addAlignTokensOperationsRules; private readonly ImmutableArray<AbstractFormattingRule> _getAdjustNewLinesOperationRules; private readonly ImmutableArray<AbstractFormattingRule> _getAdjustSpacesOperationRules; public ChainedFormattingRules(IEnumerable<AbstractFormattingRule> formattingRules, SyntaxFormattingOptions options) { Contract.ThrowIfNull(formattingRules); _formattingRules = formattingRules.SelectAsArray(rule => rule.WithOptions(options)); _options = options; _addSuppressOperationsRules = FilterToRulesImplementingMethod(_formattingRules, nameof(AbstractFormattingRule.AddSuppressOperations)); _addAnchorIndentationOperationsRules = FilterToRulesImplementingMethod(_formattingRules, nameof(AbstractFormattingRule.AddAnchorIndentationOperations)); _addIndentBlockOperationsRules = FilterToRulesImplementingMethod(_formattingRules, nameof(AbstractFormattingRule.AddIndentBlockOperations)); _addAlignTokensOperationsRules = FilterToRulesImplementingMethod(_formattingRules, nameof(AbstractFormattingRule.AddAlignTokensOperations)); _getAdjustNewLinesOperationRules = FilterToRulesImplementingMethod(_formattingRules, nameof(AbstractFormattingRule.GetAdjustNewLinesOperation)); _getAdjustSpacesOperationRules = FilterToRulesImplementingMethod(_formattingRules, nameof(AbstractFormattingRule.GetAdjustSpacesOperation)); } public void AddSuppressOperations(ArrayBuilder<SuppressOperation> list, SyntaxNode currentNode) { var action = new NextSuppressOperationAction(_addSuppressOperationsRules, index: 0, currentNode, list); action.Invoke(); } public void AddAnchorIndentationOperations(List<AnchorIndentationOperation> list, SyntaxNode currentNode) { var action = new NextAnchorIndentationOperationAction(_addAnchorIndentationOperationsRules, index: 0, currentNode, list); action.Invoke(); } public void AddIndentBlockOperations(List<IndentBlockOperation> list, SyntaxNode currentNode) { var action = new NextIndentBlockOperationAction(_addIndentBlockOperationsRules, index: 0, currentNode, list); action.Invoke(); } public void AddAlignTokensOperations(List<AlignTokensOperation> list, SyntaxNode currentNode) { var action = new NextAlignTokensOperationAction(_addAlignTokensOperationsRules, index: 0, currentNode, list); action.Invoke(); } public AdjustNewLinesOperation? GetAdjustNewLinesOperation(SyntaxToken previousToken, SyntaxToken currentToken) { var action = new NextGetAdjustNewLinesOperation(_getAdjustNewLinesOperationRules, index: 0); return action.Invoke(in previousToken, in currentToken); } public AdjustSpacesOperation? GetAdjustSpacesOperation(SyntaxToken previousToken, SyntaxToken currentToken) { var action = new NextGetAdjustSpacesOperation(_getAdjustSpacesOperationRules, index: 0); return action.Invoke(in previousToken, in currentToken); } private static ImmutableArray<AbstractFormattingRule> FilterToRulesImplementingMethod(ImmutableArray<AbstractFormattingRule> rules, string name) { return rules.WhereAsArray(rule => { var type = GetTypeImplementingMethod(rule, name); if (type == typeof(AbstractFormattingRule)) return false; if (type == typeof(CompatAbstractFormattingRule)) { type = GetTypeImplementingMethod(rule, name + "Slow"); if (type == typeof(CompatAbstractFormattingRule)) return false; } return true; }); } private static Type? GetTypeImplementingMethod(object obj, string name) { return s_typeImplementingMethod.GetOrAdd( (obj.GetType(), name), key => key.type.GetRuntimeMethods().FirstOrDefault(method => method.Name == key.name)?.DeclaringType); } }