|
// 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.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Simplification;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeStyle
{
internal static class CodeStyleOptions2
{
private const string PublicFeatureName = "CodeStyleOptions";
private static readonly ImmutableArray<IOption2>.Builder s_allOptionsBuilder = ImmutableArray.CreateBuilder<IOption2>();
private static PerLanguageOption2<CodeStyleOption2<T>> CreatePerLanguageOption<T>(
OptionGroup group, string name, CodeStyleOption2<T> defaultValue, Func<CodeStyleOption2<T>, EditorConfigValueSerializer<CodeStyleOption2<T>>>? serializerFactory = null)
=> s_allOptionsBuilder.CreatePerLanguageEditorConfigOption(name, defaultValue, group, serializerFactory);
private static Option2<CodeStyleOption2<T>> CreateOption<T>(
OptionGroup group, string name, CodeStyleOption2<T> defaultValue, Func<CodeStyleOption2<T>, EditorConfigValueSerializer<CodeStyleOption2<T>>>? serializerFactory = null)
=> s_allOptionsBuilder.CreateEditorConfigOption(name, defaultValue, group, languageName: null, serializerFactory);
private static Option2<T> CreateOption<T>(
OptionGroup group, string name, T defaultValue, EditorConfigValueSerializer<T>? serializer = null)
=> s_allOptionsBuilder.CreateEditorConfigOption(name, defaultValue, group, serializer);
private static PerLanguageOption2<CodeStyleOption2<bool>> CreateQualifyAccessOption(string name)
=> CreatePerLanguageOption(CodeStyleOptionGroups.ThisOrMe, name, defaultValue: SimplifierOptions.DefaultQualifyAccess);
/// <summary>
/// This option says if we should simplify away the <see langword="this"/>. or <see langword="Me"/>. in field access expressions.
/// </summary>
public static readonly PerLanguageOption2<CodeStyleOption2<bool>> QualifyFieldAccess = CreateQualifyAccessOption(
"dotnet_style_qualification_for_field")
.WithPublicOption(PublicFeatureName, "QualifyFieldAccess");
/// <summary>
/// This option says if we should simplify away the <see langword="this"/>. or <see langword="Me"/>. in property access expressions.
/// </summary>
public static readonly PerLanguageOption2<CodeStyleOption2<bool>> QualifyPropertyAccess = CreateQualifyAccessOption(
"dotnet_style_qualification_for_property")
.WithPublicOption(PublicFeatureName, "QualifyPropertyAccess");
/// <summary>
/// This option says if we should simplify away the <see langword="this"/>. or <see langword="Me"/>. in method access expressions.
/// </summary>
public static readonly PerLanguageOption2<CodeStyleOption2<bool>> QualifyMethodAccess = CreateQualifyAccessOption(
"dotnet_style_qualification_for_method")
.WithPublicOption(PublicFeatureName, "QualifyMethodAccess");
/// <summary>
/// This option says if we should simplify away the <see langword="this"/>. or <see langword="Me"/>. in event access expressions.
/// </summary>
public static readonly PerLanguageOption2<CodeStyleOption2<bool>> QualifyEventAccess = CreateQualifyAccessOption(
"dotnet_style_qualification_for_event")
.WithPublicOption(PublicFeatureName, "QualifyEventAccess");
/// <summary>
/// This option says if we should prefer keyword for Intrinsic Predefined Types in Declarations
/// </summary>
public static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferIntrinsicPredefinedTypeKeywordInDeclaration = CreatePerLanguageOption(
CodeStyleOptionGroups.PredefinedTypeNameUsage,
defaultValue: SimplifierOptions.CommonDefaults.PreferPredefinedTypeKeywordInDeclaration,
name: "dotnet_style_predefined_type_for_locals_parameters_members")
.WithPublicOption(PublicFeatureName, "PreferIntrinsicPredefinedTypeKeywordInDeclaration");
/// <summary>
/// This option says if we should prefer keyword for Intrinsic Predefined Types in Member Access Expression
/// </summary>
public static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferIntrinsicPredefinedTypeKeywordInMemberAccess = CreatePerLanguageOption(
CodeStyleOptionGroups.PredefinedTypeNameUsage,
defaultValue: SimplifierOptions.CommonDefaults.PreferPredefinedTypeKeywordInMemberAccess,
name: "dotnet_style_predefined_type_for_member_access")
.WithPublicOption(PublicFeatureName, "PreferIntrinsicPredefinedTypeKeywordInMemberAccess");
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferObjectInitializer = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_object_initializer",
IdeCodeStyleOptions.CommonDefaults.PreferObjectInitializer);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferCollectionInitializer = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_collection_initializer",
IdeCodeStyleOptions.CommonDefaults.PreferCollectionInitializer);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferSimplifiedBooleanExpressions = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_simplified_boolean_expressions",
IdeCodeStyleOptions.CommonDefaults.PreferSimplifiedBooleanExpressions);
internal static readonly Option2<OperatorPlacementWhenWrappingPreference> OperatorPlacementWhenWrapping = CreateOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_operator_placement_when_wrapping",
IdeCodeStyleOptions.CommonDefaults.OperatorPlacementWhenWrapping,
serializer: new(
parseValue: str => OperatorPlacementUtilities.Parse(str, IdeCodeStyleOptions.CommonDefaults.OperatorPlacementWhenWrapping),
serializeValue: OperatorPlacementUtilities.GetEditorConfigString));
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferCoalesceExpression = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_coalesce_expression",
IdeCodeStyleOptions.CommonDefaults.PreferCoalesceExpression);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferNullPropagation = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_null_propagation",
IdeCodeStyleOptions.CommonDefaults.PreferNullPropagation);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferExplicitTupleNames = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_explicit_tuple_names",
IdeCodeStyleOptions.CommonDefaults.PreferExplicitTupleNames);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferAutoProperties = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_auto_properties",
IdeCodeStyleOptions.CommonDefaults.PreferAutoProperties);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferInferredTupleNames = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_inferred_tuple_names",
IdeCodeStyleOptions.CommonDefaults.PreferInferredTupleNames);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferInferredAnonymousTypeMemberNames = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_inferred_anonymous_type_member_names",
IdeCodeStyleOptions.CommonDefaults.PreferInferredAnonymousTypeMemberNames);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferIsNullCheckOverReferenceEqualityMethod = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_is_null_check_over_reference_equality_method",
IdeCodeStyleOptions.CommonDefaults.PreferIsNullCheckOverReferenceEqualityMethod);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferConditionalExpressionOverAssignment = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_conditional_expression_over_assignment",
IdeCodeStyleOptions.CommonDefaults.PreferConditionalExpressionOverAssignment);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferConditionalExpressionOverReturn = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_conditional_expression_over_return",
IdeCodeStyleOptions.CommonDefaults.PreferConditionalExpressionOverReturn);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferCompoundAssignment = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_compound_assignment",
IdeCodeStyleOptions.CommonDefaults.PreferCompoundAssignment);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferSimplifiedInterpolation = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_simplified_interpolation",
IdeCodeStyleOptions.CommonDefaults.PreferSimplifiedInterpolation);
private static readonly BidirectionalMap<string, UnusedParametersPreference> s_unusedParametersPreferenceMap =
new(new[]
{
KeyValuePairUtil.Create("non_public", UnusedParametersPreference.NonPublicMethods),
KeyValuePairUtil.Create("all", UnusedParametersPreference.AllMethods),
});
internal static readonly PerLanguageOption2<CodeStyleOption2<UnusedParametersPreference>> UnusedParameters = CreatePerLanguageOption(
CodeStyleOptionGroups.Parameter,
"dotnet_code_quality_unused_parameters",
IdeCodeStyleOptions.CommonDefaults.UnusedParameters,
defaultValue => new(
parseValue: str =>
{
if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification(str, defaultValue.Notification, out var value, out var notification))
{
return new CodeStyleOption2<UnusedParametersPreference>(s_unusedParametersPreferenceMap.GetValueOrDefault(value), notification);
}
return defaultValue;
},
serializeValue: option =>
{
Debug.Assert(s_unusedParametersPreferenceMap.ContainsValue(option.Value));
var value = s_unusedParametersPreferenceMap.GetKeyOrDefault(option.Value) ?? s_unusedParametersPreferenceMap.GetKeyOrDefault(defaultValue.Value);
return $"{value}{CodeStyleHelpers.GetEditorConfigStringNotificationPart(option, defaultValue)}";
}));
private static readonly BidirectionalMap<string, AccessibilityModifiersRequired> s_accessibilityModifiersRequiredMap =
new(new[]
{
KeyValuePairUtil.Create("never", CodeStyle.AccessibilityModifiersRequired.Never),
KeyValuePairUtil.Create("always", CodeStyle.AccessibilityModifiersRequired.Always),
KeyValuePairUtil.Create("for_non_interface_members", CodeStyle.AccessibilityModifiersRequired.ForNonInterfaceMembers),
KeyValuePairUtil.Create("omit_if_default", CodeStyle.AccessibilityModifiersRequired.OmitIfDefault),
});
internal static readonly PerLanguageOption2<CodeStyleOption2<AccessibilityModifiersRequired>> AccessibilityModifiersRequired = CreatePerLanguageOption(
CodeStyleOptionGroups.Modifier, "dotnet_style_require_accessibility_modifiers",
IdeCodeStyleOptions.CommonDefaults.AccessibilityModifiersRequired,
defaultValue => new(
parseValue: str =>
{
if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification(str, defaultValue.Notification, out var value, out var notificationOpt))
{
Debug.Assert(s_accessibilityModifiersRequiredMap.ContainsKey(value));
return new CodeStyleOption2<AccessibilityModifiersRequired>(s_accessibilityModifiersRequiredMap.GetValueOrDefault(value), notificationOpt);
}
return defaultValue;
},
serializeValue: option =>
{
Debug.Assert(s_accessibilityModifiersRequiredMap.ContainsValue(option.Value));
return $"{s_accessibilityModifiersRequiredMap.GetKeyOrDefault(option.Value)}{CodeStyleHelpers.GetEditorConfigStringNotificationPart(option, defaultValue)}";
}));
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferReadonly = CreatePerLanguageOption(
CodeStyleOptionGroups.Field,
"dotnet_style_readonly_field",
IdeCodeStyleOptions.CommonDefaults.PreferReadonly);
internal static readonly Option2<string> FileHeaderTemplate = CreateOption(
CodeStyleOptionGroups.Usings,
"file_header_template",
DocumentFormattingOptions.Default.FileHeaderTemplate,
EditorConfigValueSerializer.String(emptyStringRepresentation: "unset"));
internal static readonly Option2<string> RemoveUnnecessarySuppressionExclusions = CreateOption(
CodeStyleOptionGroups.Suppressions,
"dotnet_remove_unnecessary_suppression_exclusions",
IdeCodeStyleOptions.CommonDefaults.RemoveUnnecessarySuppressionExclusions,
EditorConfigValueSerializer.String(emptyStringRepresentation: "none"));
private static readonly BidirectionalMap<string, ParenthesesPreference> s_parenthesesPreferenceMap =
new(new[]
{
KeyValuePairUtil.Create("always_for_clarity", ParenthesesPreference.AlwaysForClarity),
KeyValuePairUtil.Create("never_if_unnecessary", ParenthesesPreference.NeverIfUnnecessary),
});
private static PerLanguageOption2<CodeStyleOption2<ParenthesesPreference>> CreateParenthesesOption(CodeStyleOption2<ParenthesesPreference> defaultValue, string name)
=> CreatePerLanguageOption(
CodeStyleOptionGroups.Parentheses,
name,
defaultValue,
defaultValue => new(
parseValue: str =>
{
if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification(str, defaultValue.Notification, out var value, out var notification))
{
Debug.Assert(s_parenthesesPreferenceMap.ContainsKey(value));
return new CodeStyleOption2<ParenthesesPreference>(s_parenthesesPreferenceMap.GetValueOrDefault(value), notification);
}
return defaultValue;
},
serializeValue: option =>
{
Debug.Assert(s_parenthesesPreferenceMap.ContainsValue(option.Value));
var value = s_parenthesesPreferenceMap.GetKeyOrDefault(option.Value) ?? s_parenthesesPreferenceMap.GetKeyOrDefault(ParenthesesPreference.AlwaysForClarity);
return $"{value}{CodeStyleHelpers.GetEditorConfigStringNotificationPart(option, defaultValue)}";
}));
internal static readonly PerLanguageOption2<CodeStyleOption2<ParenthesesPreference>> ArithmeticBinaryParentheses =
CreateParenthesesOption(
IdeCodeStyleOptions.CommonDefaults.ArithmeticBinaryParentheses,
"dotnet_style_parentheses_in_arithmetic_binary_operators");
internal static readonly PerLanguageOption2<CodeStyleOption2<ParenthesesPreference>> OtherBinaryParentheses =
CreateParenthesesOption(
IdeCodeStyleOptions.CommonDefaults.OtherBinaryParentheses,
"dotnet_style_parentheses_in_other_binary_operators");
internal static readonly PerLanguageOption2<CodeStyleOption2<ParenthesesPreference>> RelationalBinaryParentheses =
CreateParenthesesOption(
IdeCodeStyleOptions.CommonDefaults.RelationalBinaryParentheses,
"dotnet_style_parentheses_in_relational_binary_operators");
internal static readonly PerLanguageOption2<CodeStyleOption2<ParenthesesPreference>> OtherParentheses =
CreateParenthesesOption(
IdeCodeStyleOptions.CommonDefaults.OtherParentheses,
"dotnet_style_parentheses_in_other_operators");
private static readonly BidirectionalMap<string, ForEachExplicitCastInSourcePreference> s_forEachExplicitCastInSourcePreferencePreferenceMap =
new(new[]
{
KeyValuePairUtil.Create("always", ForEachExplicitCastInSourcePreference.Always),
KeyValuePairUtil.Create("when_strongly_typed", ForEachExplicitCastInSourcePreference.WhenStronglyTyped),
});
internal static readonly Option2<CodeStyleOption2<ForEachExplicitCastInSourcePreference>> ForEachExplicitCastInSource = CreateOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_prefer_foreach_explicit_cast_in_source",
IdeCodeStyleOptions.CommonDefaults.ForEachExplicitCastInSource,
defaultValue => new(
parseValue: str =>
{
if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification(str, defaultValue.Notification, out var value, out var notification))
{
Debug.Assert(s_forEachExplicitCastInSourcePreferencePreferenceMap.ContainsKey(value));
return new CodeStyleOption2<ForEachExplicitCastInSourcePreference>(
s_forEachExplicitCastInSourcePreferencePreferenceMap.GetValueOrDefault(value), notification);
}
return defaultValue;
},
serializeValue: option =>
{
Debug.Assert(s_forEachExplicitCastInSourcePreferencePreferenceMap.ContainsValue(option.Value));
var value = s_forEachExplicitCastInSourcePreferencePreferenceMap.GetKeyOrDefault(option.Value) ??
s_forEachExplicitCastInSourcePreferencePreferenceMap.GetKeyOrDefault(defaultValue.Value);
return $"{value}{CodeStyleHelpers.GetEditorConfigStringNotificationPart(option, defaultValue)}";
}));
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferSystemHashCode = new(
"dotnet_prefer_system_hash_code",
IdeAnalyzerOptions.CommonDefault.PreferSystemHashCode,
group: CodeStyleOptionGroups.ExpressionLevelPreferences);
public static readonly PerLanguageOption2<CodeStyleOption2<bool>> PreferNamespaceAndFolderMatchStructure = CreatePerLanguageOption(
CodeStyleOptionGroups.ExpressionLevelPreferences,
"dotnet_style_namespace_match_folder",
IdeCodeStyleOptions.CommonDefaults.PreferNamespaceAndFolderMatchStructure);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> AllowMultipleBlankLines = CreatePerLanguageOption(
CodeStyleOptionGroups.NewLinePreferences,
"dotnet_style_allow_multiple_blank_lines_experimental",
IdeCodeStyleOptions.CommonDefaults.AllowMultipleBlankLines);
internal static readonly PerLanguageOption2<CodeStyleOption2<bool>> AllowStatementImmediatelyAfterBlock = CreatePerLanguageOption(
CodeStyleOptionGroups.NewLinePreferences,
"dotnet_style_allow_statement_immediately_after_block_experimental",
IdeCodeStyleOptions.CommonDefaults.AllowStatementImmediatelyAfterBlock);
internal static readonly ImmutableArray<IOption2> AllOptions = s_allOptionsBuilder.ToImmutable();
}
internal static class CodeStyleOptionGroups
{
public static readonly OptionGroup CodeStyle = new(name: "code_style", description: "", priority: 1);
public static readonly OptionGroup Usings = new("usings", description: CompilerExtensionsResources.Organize_usings, priority: 1, parent: CodeStyle);
public static readonly OptionGroup ThisOrMe = new("this_or_me", description: CompilerExtensionsResources.this_dot_and_Me_dot_preferences, priority: 2, parent: CodeStyle);
public static readonly OptionGroup PredefinedTypeNameUsage = new("predefined_type_name_usage", description: CompilerExtensionsResources.Language_keywords_vs_BCL_types_preferences, priority: 3, parent: CodeStyle);
public static readonly OptionGroup Parentheses = new("parentheses", description: CompilerExtensionsResources.Parentheses_preferences, priority: 4, parent: CodeStyle);
public static readonly OptionGroup Modifier = new("modifier", description: CompilerExtensionsResources.Modifier_preferences, priority: 5, parent: CodeStyle);
public static readonly OptionGroup ExpressionLevelPreferences = new("expression_level_preferences", description: CompilerExtensionsResources.Expression_level_preferences, priority: 7, parent: CodeStyle);
public static readonly OptionGroup Field = new("field", description: CompilerExtensionsResources.Field_preferences, priority: 8, parent: CodeStyle);
public static readonly OptionGroup Parameter = new("parameter", description: CompilerExtensionsResources.Parameter_preferences, priority: 9, parent: CodeStyle);
public static readonly OptionGroup Suppressions = new("suppressions", description: CompilerExtensionsResources.Suppression_preferences, priority: 10, parent: CodeStyle);
public static readonly OptionGroup NewLinePreferences = new("new_line_preferences", description: CompilerExtensionsResources.New_line_preferences, priority: 11, parent: CodeStyle);
}
}
|