File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\CSharp\Formatting\CSharpFormattingOptions2.cs
Web Access
Project: src\src\Workspaces\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Workspaces.csproj (Microsoft.CodeAnalysis.CSharp.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.Collections.Immutable;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Formatting;
 
#if CODE_STYLE
using CSharpWorkspaceResources = Microsoft.CodeAnalysis.CSharp.CSharpCodeStyleResources;
#endif
 
namespace Microsoft.CodeAnalysis.CSharp.Formatting;
 
internal static partial class CSharpFormattingOptions2
{
    private const string PublicFeatureName = "CSharpFormattingOptions";
 
    private static readonly ImmutableArray<IOption2>.Builder s_editorConfigOptionsBuilder = ImmutableArray.CreateBuilder<IOption2>();
 
    // Maps to store mapping between special option kinds and the corresponding editor config string representations.
    #region Editor Config maps
    private static readonly BidirectionalMap<string, SpacePlacementWithinParentheses> s_spacingWithinParenthesisOptionsEditorConfigMap =
        new(
        [
            KeyValuePairUtil.Create("expressions", SpacePlacementWithinParentheses.Expressions),
            KeyValuePairUtil.Create("type_casts", SpacePlacementWithinParentheses.TypeCasts),
            KeyValuePairUtil.Create("control_flow_statements", SpacePlacementWithinParentheses.ControlFlowStatements),
        ]);
    private static readonly BidirectionalMap<string, BinaryOperatorSpacingOptions> s_binaryOperatorSpacingOptionsEditorConfigMap =
        new(
        [
            KeyValuePairUtil.Create("ignore", BinaryOperatorSpacingOptions.Ignore),
            KeyValuePairUtil.Create("none", BinaryOperatorSpacingOptions.Remove),
            KeyValuePairUtil.Create("before_and_after", BinaryOperatorSpacingOptions.Single),
        ]);
    private static readonly BidirectionalMap<string, LabelPositionOptions> s_labelPositionOptionsEditorConfigMap =
        new(
        [
            KeyValuePairUtil.Create("flush_left", LabelPositionOptions.LeftMost),
            KeyValuePairUtil.Create("no_change", LabelPositionOptions.NoIndent),
            KeyValuePairUtil.Create("one_less_than_current", LabelPositionOptions.OneLess),
        ]);
    private static readonly BidirectionalMap<string, NewLineBeforeOpenBracePlacement> s_legacyNewLineOptionsEditorConfigMap =
        new(
        [
            KeyValuePairUtil.Create("object_collection_array_initalizers", NewLineBeforeOpenBracePlacement.ObjectCollectionArrayInitializers),
        ]);
    private static readonly BidirectionalMap<string, NewLineBeforeOpenBracePlacement> s_newLineOptionsEditorConfigMap =
        new(
        [
            KeyValuePairUtil.Create("all", NewLineBeforeOpenBracePlacement.All),
            KeyValuePairUtil.Create("accessors", NewLineBeforeOpenBracePlacement.Accessors),
            KeyValuePairUtil.Create("types", NewLineBeforeOpenBracePlacement.Types),
            KeyValuePairUtil.Create("methods", NewLineBeforeOpenBracePlacement.Methods),
            KeyValuePairUtil.Create("properties", NewLineBeforeOpenBracePlacement.Properties),
            KeyValuePairUtil.Create("anonymous_methods", NewLineBeforeOpenBracePlacement.AnonymousMethods),
            KeyValuePairUtil.Create("control_blocks", NewLineBeforeOpenBracePlacement.ControlBlocks),
            KeyValuePairUtil.Create("anonymous_types", NewLineBeforeOpenBracePlacement.AnonymousTypes),
            KeyValuePairUtil.Create("object_collection_array_initializers", NewLineBeforeOpenBracePlacement.ObjectCollectionArrayInitializers),
            KeyValuePairUtil.Create("lambdas", NewLineBeforeOpenBracePlacement.LambdaExpressionBody),
        ]);
    #endregion
 
    private static Option2<T> CreateOption<T>(OptionGroup group, string name, T defaultValue, EditorConfigValueSerializer<T>? serializer = null)
    {
        var option = new Option2<T>(name, defaultValue, group, LanguageNames.CSharp, isEditorConfigOption: true, serializer: serializer);
        s_editorConfigOptionsBuilder.Add(option);
        return option;
    }
 
    public static Option2<bool> SpacingAfterMethodDeclarationName { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_between_method_declaration_name_and_open_parenthesis",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.AfterMethodDeclarationName))
        .WithPublicOption(PublicFeatureName, "SpacingAfterMethodDeclarationName");
 
    public static Option2<bool> SpaceWithinMethodDeclarationParenthesis { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_between_method_declaration_parameter_list_parentheses",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.WithinMethodDeclarationParenthesis))
        .WithPublicOption(PublicFeatureName, "SpaceWithinMethodDeclarationParenthesis");
 
    public static Option2<bool> SpaceBetweenEmptyMethodDeclarationParentheses { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_between_method_declaration_empty_parameter_list_parentheses",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.BetweenEmptyMethodDeclarationParentheses))
        .WithPublicOption(PublicFeatureName, "SpaceBetweenEmptyMethodDeclarationParentheses");
 
    public static Option2<bool> SpaceAfterMethodCallName { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_between_method_call_name_and_opening_parenthesis",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.AfterMethodCallName))
        .WithPublicOption(PublicFeatureName, "SpaceAfterMethodCallName");
 
    public static Option2<bool> SpaceWithinMethodCallParentheses { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_between_method_call_parameter_list_parentheses",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.WithinMethodCallParentheses))
        .WithPublicOption(PublicFeatureName, "SpaceWithinMethodCallParentheses");
 
    public static Option2<bool> SpaceBetweenEmptyMethodCallParentheses { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_between_method_call_empty_parameter_list_parentheses",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.BetweenEmptyMethodCallParentheses))
        .WithPublicOption(PublicFeatureName, "SpaceBetweenEmptyMethodCallParentheses");
 
    public static Option2<bool> SpaceAfterControlFlowStatementKeyword { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_after_keywords_in_control_flow_statements",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.AfterControlFlowStatementKeyword))
        .WithPublicOption(PublicFeatureName, "SpaceAfterControlFlowStatementKeyword");
 
    public static Option2<SpacePlacementWithinParentheses> SpaceBetweenParentheses { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing,
        name: "csharp_space_between_parentheses",
        CSharpSyntaxFormattingOptions.SpacingDefault.ToSpacingWithinParentheses(),
        new EditorConfigValueSerializer<SpacePlacementWithinParentheses>(
            parseValue: list => ParseSpacingWithinParenthesesList(list),
            serializeValue: ToEditorConfigValue));
 
    public static Option2<bool> SpaceAfterCast { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_after_cast",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.AfterCast))
        .WithPublicOption(PublicFeatureName, "SpaceAfterCast");
 
    public static Option2<bool> SpacesIgnoreAroundVariableDeclaration { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_around_declaration_statements",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.IgnoreAroundVariableDeclaration),
        new EditorConfigValueSerializer<bool>(
            s => DetermineIfIgnoreSpacesAroundVariableDeclarationIsSet(s),
            v => v ? "ignore" : "false"))
        .WithPublicOption(PublicFeatureName, "SpacesIgnoreAroundVariableDeclaration");
 
    public static Option2<bool> SpaceBeforeOpenSquareBracket { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_before_open_square_brackets",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.BeforeOpenSquareBracket))
        .WithPublicOption(PublicFeatureName, "SpaceBeforeOpenSquareBracket");
 
    public static Option2<bool> SpaceBetweenEmptySquareBrackets { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_between_empty_square_brackets",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.BetweenEmptySquareBrackets))
        .WithPublicOption(PublicFeatureName, "SpaceBetweenEmptySquareBrackets");
 
    public static Option2<bool> SpaceWithinSquareBrackets { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_between_square_brackets",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.WithinSquareBrackets))
        .WithPublicOption(PublicFeatureName, "SpaceWithinSquareBrackets");
 
    public static Option2<bool> SpaceAfterColonInBaseTypeDeclaration { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_after_colon_in_inheritance_clause",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.AfterColonInBaseTypeDeclaration))
        .WithPublicOption(PublicFeatureName, "SpaceAfterColonInBaseTypeDeclaration");
 
    public static Option2<bool> SpaceAfterComma { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_after_comma",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.AfterComma))
        .WithPublicOption(PublicFeatureName, "SpaceAfterComma");
 
    public static Option2<bool> SpaceAfterDot { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_after_dot",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.AfterDot))
        .WithPublicOption(PublicFeatureName, "SpaceAfterDot");
 
    public static Option2<bool> SpaceAfterSemicolonsInForStatement { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_after_semicolon_in_for_statement",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.AfterSemicolonsInForStatement))
        .WithPublicOption(PublicFeatureName, "SpaceAfterSemicolonsInForStatement");
 
    public static Option2<bool> SpaceBeforeColonInBaseTypeDeclaration { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_before_colon_in_inheritance_clause",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.BeforeColonInBaseTypeDeclaration))
        .WithPublicOption(PublicFeatureName, "SpaceBeforeColonInBaseTypeDeclaration");
 
    public static Option2<bool> SpaceBeforeComma { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_before_comma",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.BeforeComma))
        .WithPublicOption(PublicFeatureName, "SpaceBeforeComma");
 
    public static Option2<bool> SpaceBeforeDot { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_before_dot",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.BeforeDot))
        .WithPublicOption(PublicFeatureName, "SpaceBeforeDot");
 
    public static Option2<bool> SpaceBeforeSemicolonsInForStatement { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_before_semicolon_in_for_statement",
        CSharpSyntaxFormattingOptions.SpacingDefault.HasFlag(SpacePlacement.BeforeSemicolonsInForStatement))
        .WithPublicOption(PublicFeatureName, "SpaceBeforeSemicolonsInForStatement");
 
    public static Option2<BinaryOperatorSpacingOptions> SpacingAroundBinaryOperator { get; } = CreateOption(
        CSharpFormattingOptionGroups.Spacing, "csharp_space_around_binary_operators",
        CSharpSyntaxFormattingOptions.Default.SpacingAroundBinaryOperator,
        new EditorConfigValueSerializer<BinaryOperatorSpacingOptions>(
            s => ParseEditorConfigSpacingAroundBinaryOperator(s),
            GetSpacingAroundBinaryOperatorEditorConfigString))
        .WithPublicOption(PublicFeatureName, "SpacingAroundBinaryOperator");
 
    public static Option2<bool> IndentBraces { get; } = CreateOption(
        CSharpFormattingOptionGroups.Indentation, "csharp_indent_braces",
        CSharpSyntaxFormattingOptions.IndentationDefault.HasFlag(IndentationPlacement.Braces))
        .WithPublicOption(PublicFeatureName, "IndentBraces");
 
    public static Option2<bool> IndentBlock { get; } = CreateOption(
        CSharpFormattingOptionGroups.Indentation, "csharp_indent_block_contents",
        CSharpSyntaxFormattingOptions.IndentationDefault.HasFlag(IndentationPlacement.BlockContents))
        .WithPublicOption(PublicFeatureName, "IndentBlock");
 
    public static Option2<bool> IndentSwitchSection { get; } = CreateOption(
        CSharpFormattingOptionGroups.Indentation, "csharp_indent_switch_labels",
        CSharpSyntaxFormattingOptions.IndentationDefault.HasFlag(IndentationPlacement.SwitchSection))
        .WithPublicOption(PublicFeatureName, "IndentSwitchSection");
 
    public static Option2<bool> IndentSwitchCaseSection { get; } = CreateOption(
        CSharpFormattingOptionGroups.Indentation, "csharp_indent_case_contents",
        CSharpSyntaxFormattingOptions.IndentationDefault.HasFlag(IndentationPlacement.SwitchSection))
        .WithPublicOption(PublicFeatureName, "IndentSwitchCaseSection");
 
    public static Option2<bool> IndentSwitchCaseSectionWhenBlock { get; } = CreateOption(
        CSharpFormattingOptionGroups.Indentation, "csharp_indent_case_contents_when_block",
        CSharpSyntaxFormattingOptions.IndentationDefault.HasFlag(IndentationPlacement.SwitchCaseContentsWhenBlock))
        .WithPublicOption(PublicFeatureName, "IndentSwitchCaseSectionWhenBlock");
 
    public static Option2<LabelPositionOptions> LabelPositioning { get; } = CreateOption(
        CSharpFormattingOptionGroups.Indentation, "csharp_indent_labels",
        CSharpSyntaxFormattingOptions.Default.LabelPositioning,
        new EditorConfigValueSerializer<LabelPositionOptions>(
            s => ParseEditorConfigLabelPositioning(s),
            GetLabelPositionOptionEditorConfigString))
        .WithPublicOption(PublicFeatureName, "LabelPositioning");
 
    public static Option2<bool> WrappingPreserveSingleLine { get; } = CreateOption(
        CSharpFormattingOptionGroups.Wrapping, "csharp_preserve_single_line_blocks",
        CSharpSyntaxFormattingOptions.Default.WrappingPreserveSingleLine)
        .WithPublicOption(PublicFeatureName, "WrappingPreserveSingleLine");
 
    public static Option2<bool> WrappingKeepStatementsOnSingleLine { get; } = CreateOption(
        CSharpFormattingOptionGroups.Wrapping, "csharp_preserve_single_line_statements",
        CSharpSyntaxFormattingOptions.Default.WrappingKeepStatementsOnSingleLine)
        .WithPublicOption(PublicFeatureName, "WrappingKeepStatementsOnSingleLine");
 
    public static Option2<NewLineBeforeOpenBracePlacement> NewLineBeforeOpenBrace { get; } = CreateOption(
        FormattingOptionGroups.NewLine,
        name: "csharp_new_line_before_open_brace",
        CSharpSyntaxFormattingOptions.NewLinesDefault.ToNewLineBeforeOpenBracePlacement(),
        new EditorConfigValueSerializer<NewLineBeforeOpenBracePlacement>(
            parseValue: list => ParseNewLineBeforeOpenBracePlacementList(list),
            serializeValue: ToEditorConfigValue));
 
    public static Option2<bool> NewLineForElse { get; } = CreateOption(
        FormattingOptionGroups.NewLine, "csharp_new_line_before_else",
        CSharpSyntaxFormattingOptions.NewLinesDefault.HasFlag(NewLinePlacement.BeforeElse))
        .WithPublicOption(PublicFeatureName, "NewLineForElse");
 
    public static Option2<bool> NewLineForCatch { get; } = CreateOption(
        FormattingOptionGroups.NewLine, "csharp_new_line_before_catch",
        CSharpSyntaxFormattingOptions.NewLinesDefault.HasFlag(NewLinePlacement.BeforeCatch))
        .WithPublicOption(PublicFeatureName, "NewLineForCatch");
 
    public static Option2<bool> NewLineForFinally { get; } = CreateOption(
        FormattingOptionGroups.NewLine, "csharp_new_line_before_finally",
        CSharpSyntaxFormattingOptions.NewLinesDefault.HasFlag(NewLinePlacement.BeforeFinally))
        .WithPublicOption(PublicFeatureName, "NewLineForFinally");
 
    public static Option2<bool> NewLineForMembersInObjectInit { get; } = CreateOption(
        FormattingOptionGroups.NewLine, "csharp_new_line_before_members_in_object_initializers",
        CSharpSyntaxFormattingOptions.NewLinesDefault.HasFlag(NewLinePlacement.BeforeMembersInObjectInitializers))
        .WithPublicOption(PublicFeatureName, "NewLineForMembersInObjectInit");
 
    public static Option2<bool> NewLineForMembersInAnonymousTypes { get; } = CreateOption(
        FormattingOptionGroups.NewLine, "csharp_new_line_before_members_in_anonymous_types",
        CSharpSyntaxFormattingOptions.NewLinesDefault.HasFlag(NewLinePlacement.BeforeMembersInAnonymousTypes))
        .WithPublicOption(PublicFeatureName, "NewLineForMembersInAnonymousTypes");
 
    public static Option2<bool> NewLineForClausesInQuery { get; } = CreateOption(
        FormattingOptionGroups.NewLine, "csharp_new_line_between_query_expression_clauses",
        CSharpSyntaxFormattingOptions.NewLinesDefault.HasFlag(NewLinePlacement.BetweenQueryExpressionClauses))
        .WithPublicOption(PublicFeatureName, "NewLineForClausesInQuery");
 
    /// <summary>
    /// Internal option -- not exposed to editorconfig tooling via <see cref="EditorConfigOptions"/>.
    /// </summary>
    public static readonly Option2<int> CollectionExpressionWrappingLength = new(
        $"csharp_unsupported_collection_expression_wrapping_length",
        defaultValue: CSharpSyntaxFormattingOptions.Default.CollectionExpressionWrappingLength,
        languageName: LanguageNames.CSharp,
        isEditorConfigOption: true);
 
    /// <summary>
    /// Options that we expect the user to set in editorconfig.
    /// </summary>
    internal static readonly ImmutableArray<IOption2> EditorConfigOptions = s_editorConfigOptionsBuilder.ToImmutable();
 
    /// <summary>
    /// Options that can be set via editorconfig but we do not provide tooling support.
    /// </summary>
    internal static readonly ImmutableArray<IOption2> UndocumentedOptions = [CollectionExpressionWrappingLength];
}
 
#if CODE_STYLE
internal enum LabelPositionOptions
#else
public enum LabelPositionOptions
#endif
{
    /// Placed in the Zeroth column of the text editor
    LeftMost = 0,
 
    /// Placed at one less indent to the current context
    OneLess = 1,
 
    /// Placed at the same indent as the current context
    NoIndent = 2
}
 
#if CODE_STYLE
internal enum BinaryOperatorSpacingOptions
#else
public enum BinaryOperatorSpacingOptions
#endif
{
    /// Single Spacing
    Single = 0,
 
    /// Ignore Formatting
    Ignore = 1,
 
    /// Remove Spacing
    Remove = 2
}
 
internal static class CSharpFormattingOptionGroups
{
    public static readonly OptionGroup Indentation = new("csharp_indentation", CSharpWorkspaceResources.Indentation_preferences, priority: 3, parent: FormattingOptionGroups.FormattingOptionGroup);
    public static readonly OptionGroup Spacing = new("csharp_spacing", CSharpWorkspaceResources.Space_preferences, priority: 4, parent: FormattingOptionGroups.FormattingOptionGroup);
    public static readonly OptionGroup Wrapping = new("csharp_wrapping", CSharpWorkspaceResources.Wrapping_preferences, priority: 5, parent: FormattingOptionGroups.FormattingOptionGroup);
}