File: Options\OptionsTestHelpers.cs
Web Access
Project: src\src\Workspaces\CoreTestUtilities\Microsoft.CodeAnalysis.Workspaces.Test.Utilities.csproj (Microsoft.CodeAnalysis.Workspaces.Test.Utilities)
// 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.
 
#pragma warning disable RS0030 // Do not used banned APIs
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Formatting;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.NamingStyles;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.UnitTests
{
    internal static class OptionsTestHelpers
    {
        public static readonly Option<bool> CustomPublicOption = new Option<bool>("My Feature", "My Option", defaultValue: true);
 
        // all public options and their non-default values:
        public static readonly ImmutableArray<(IOption, object)> PublicCustomOptionsWithNonDefaultValues = ImmutableArray.Create<(IOption, object)>(
            (CustomPublicOption, false));
 
        public static readonly ImmutableArray<(IOption, object)> PublicAutoFormattingOptionsWithNonDefaultValues = ImmutableArray.Create<(IOption, object)>(
            (FormattingOptions.SmartIndent, FormattingOptions.IndentStyle.Block));
 
        public static readonly ImmutableArray<(IOption, object)> PublicFormattingOptionsWithNonDefaultValues = ImmutableArray.Create<(IOption, object)>(
            (FormattingOptions.UseTabs, true),
            (FormattingOptions.TabSize, 5),
            (FormattingOptions.IndentationSize, 7),
            (FormattingOptions.NewLine, "\r"),
            (CSharpFormattingOptions.IndentBlock, false),
            (CSharpFormattingOptions.IndentBraces, true),
            (CSharpFormattingOptions.IndentSwitchCaseSection, false),
            (CSharpFormattingOptions.IndentSwitchCaseSectionWhenBlock, false),
            (CSharpFormattingOptions.IndentSwitchSection, false),
            (CSharpFormattingOptions.LabelPositioning, LabelPositionOptions.LeftMost),
            (CSharpFormattingOptions.NewLineForCatch, false),
            (CSharpFormattingOptions.NewLineForClausesInQuery, false),
            (CSharpFormattingOptions.NewLineForElse, false),
            (CSharpFormattingOptions.NewLineForFinally, false),
            (CSharpFormattingOptions.NewLineForMembersInAnonymousTypes, false),
            (CSharpFormattingOptions.NewLineForMembersInObjectInit, false),
            (CSharpFormattingOptions.NewLinesForBracesInAccessors, false),
            (CSharpFormattingOptions.NewLinesForBracesInAnonymousMethods, false),
            (CSharpFormattingOptions.NewLinesForBracesInAnonymousTypes, false),
            (CSharpFormattingOptions.NewLinesForBracesInControlBlocks, false),
            (CSharpFormattingOptions.NewLinesForBracesInLambdaExpressionBody, false),
            (CSharpFormattingOptions.NewLinesForBracesInMethods, false),
            (CSharpFormattingOptions.NewLinesForBracesInObjectCollectionArrayInitializers, false),
            (CSharpFormattingOptions.NewLinesForBracesInProperties, false),
            (CSharpFormattingOptions.NewLinesForBracesInTypes, false),
            (CSharpFormattingOptions.SpaceAfterCast, true),
            (CSharpFormattingOptions.SpaceAfterColonInBaseTypeDeclaration, false),
            (CSharpFormattingOptions.SpaceAfterComma, false),
            (CSharpFormattingOptions.SpaceAfterControlFlowStatementKeyword, false),
            (CSharpFormattingOptions.SpaceAfterDot, true),
            (CSharpFormattingOptions.SpaceAfterMethodCallName, true),
            (CSharpFormattingOptions.SpaceAfterSemicolonsInForStatement, false),
            (CSharpFormattingOptions.SpaceBeforeColonInBaseTypeDeclaration, false),
            (CSharpFormattingOptions.SpaceBeforeComma, true),
            (CSharpFormattingOptions.SpaceBeforeDot, true),
            (CSharpFormattingOptions.SpaceBeforeOpenSquareBracket, true),
            (CSharpFormattingOptions.SpaceBeforeSemicolonsInForStatement, true),
            (CSharpFormattingOptions.SpaceBetweenEmptyMethodCallParentheses, true),
            (CSharpFormattingOptions.SpaceBetweenEmptyMethodDeclarationParentheses, true),
            (CSharpFormattingOptions.SpaceBetweenEmptySquareBrackets, true),
            (CSharpFormattingOptions.SpacesIgnoreAroundVariableDeclaration, true),
            (CSharpFormattingOptions.SpaceWithinCastParentheses, true),
            (CSharpFormattingOptions.SpaceWithinExpressionParentheses, true),
            (CSharpFormattingOptions.SpaceWithinMethodCallParentheses, true),
            (CSharpFormattingOptions.SpaceWithinMethodDeclarationParenthesis, true),
            (CSharpFormattingOptions.SpaceWithinOtherParentheses, true),
            (CSharpFormattingOptions.SpaceWithinSquareBrackets, true),
            (CSharpFormattingOptions.SpacingAfterMethodDeclarationName, true),
            (CSharpFormattingOptions.SpacingAroundBinaryOperator, BinaryOperatorSpacingOptions.Remove),
            (CSharpFormattingOptions.WrappingKeepStatementsOnSingleLine, false),
            (CSharpFormattingOptions.WrappingPreserveSingleLine, false));
 
        public static readonly ImmutableArray<(IOption, object)> PublicCodeStyleOptionsWithNonDefaultValues = ImmutableArray.Create<(IOption, object)>(
            (CodeStyleOptions.QualifyFieldAccess, new CodeStyleOption<bool>(true, NotificationOption.Suggestion)),
            (CodeStyleOptions.QualifyPropertyAccess, new CodeStyleOption<bool>(true, NotificationOption.Suggestion)),
            (CodeStyleOptions.QualifyMethodAccess, new CodeStyleOption<bool>(true, NotificationOption.Suggestion)),
            (CodeStyleOptions.QualifyEventAccess, new CodeStyleOption<bool>(true, NotificationOption.Suggestion)),
            (CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, new CodeStyleOption<bool>(false, NotificationOption.Suggestion)),
            (CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, new CodeStyleOption<bool>(false, NotificationOption.Suggestion)));
 
        public static readonly IEnumerable<(IOption, object)> AllPublicOptionsWithNonDefaultValues =
            PublicCustomOptionsWithNonDefaultValues
            .Concat(PublicAutoFormattingOptionsWithNonDefaultValues)
            .Concat(PublicFormattingOptionsWithNonDefaultValues)
            .Concat(PublicCodeStyleOptionsWithNonDefaultValues);
 
        public static OptionSet GetOptionSetWithChangedOptions(OptionSet options, IEnumerable<(IOption, object)> optionsWithNonDefaultValues)
        {
            var updatedOptions = options;
            foreach (var (option, newValue) in optionsWithNonDefaultValues)
            {
                foreach (var language in GetApplicableLanguages(option))
                {
                    updatedOptions = updatedOptions.WithChangedOption(new OptionKey(option, language), newValue);
                }
            }
 
            return updatedOptions;
        }
 
        public static IEnumerable<string?> GetApplicableLanguages(IOption option)
            => option.IsPerLanguage ? [LanguageNames.CSharp, LanguageNames.VisualBasic] : [null];
 
        public static object? GetDifferentValue(Type type, object? value)
            => value switch
            {
                _ when type == typeof(bool) => !(bool)value!,
                _ when type == typeof(string) => (string?)value == "X" ? "Y" : "X",
                _ when type == typeof(int) => (int)value! == 0 ? 1 : 0,
                _ when type == typeof(long) => (long)value! == 0 ? 1L : 0L,
                _ when type.IsEnum => GetDifferentEnumValue(type, value!),
                _ when Nullable.GetUnderlyingType(type) is { IsEnum: true } underlying => value is null ? Enum.ToObject(underlying, 1) : null,
                ICodeStyleOption codeStyle => codeStyle
                    .WithValue(GetDifferentValue(codeStyle.GetType().GetGenericArguments()[0], codeStyle.Value!)!)
                    .WithNotification((codeStyle.Notification == NotificationOption2.Error) ? NotificationOption2.Warning : NotificationOption2.Error),
                ICodeStyleOption2 codeStyle => codeStyle
                    .WithValue(GetDifferentValue(codeStyle.GetType().GetGenericArguments()[0], codeStyle.Value!)!)
                    .WithNotification((codeStyle.Notification == NotificationOption2.Error) ? NotificationOption2.Warning : NotificationOption2.Error),
                NamingStylePreferences namingPreference => namingPreference.IsEmpty ? NamingStylePreferences.Default : NamingStylePreferences.Empty,
                _ when type == typeof(bool?) => value is null ? true : null,
                _ when type == typeof(int?) => value is null ? 1 : null,
                _ when type == typeof(long?) => value is null ? 1L : null,
                ImmutableArray<bool> array => array.IsEmpty ? ImmutableArray.Create(true) : [],
                ImmutableArray<string> array => array is ["X"] ? ImmutableArray.Create("X", "Y") : ImmutableArray.Create("X"),
                ImmutableArray<int> array => array.IsEmpty ? ImmutableArray.Create(1) : [],
                ImmutableArray<long> array => array.IsEmpty ? ImmutableArray.Create(1L) : [],
 
                // Hit when a new option is introduced that uses type not handled above:
                _ => throw ExceptionUtilities.UnexpectedValue(type)
            };
 
        private static object GetDifferentEnumValue(Type type, object defaultValue)
        {
            var zero = Enum.ToObject(type, 0);
            return defaultValue.Equals(zero) ? Enum.ToObject(type, 1) : zero;
        }
 
        public static NamingStylePreferences GetNonDefaultNamingStylePreference()
        {
            var symbolSpecification = new SymbolSpecification(
                Guid.NewGuid(),
                "Name",
                ImmutableArray.Create(new SymbolSpecification.SymbolKindOrTypeKind(TypeKind.Class)),
                accessibilityList: default,
                modifiers: default);
 
            var namingStyle = new NamingStyle(
                Guid.NewGuid(),
                capitalizationScheme: Capitalization.PascalCase,
                name: "Name",
                prefix: "",
                suffix: "",
                wordSeparator: "");
 
            var namingRule = new SerializableNamingRule()
            {
                SymbolSpecificationID = symbolSpecification.ID,
                NamingStyleID = namingStyle.ID,
                EnforcementLevel = ReportDiagnostic.Error
            };
 
            return new NamingStylePreferences(
                ImmutableArray.Create(symbolSpecification),
                ImmutableArray.Create(namingStyle),
                ImmutableArray.Create(namingRule));
        }
    }
}