提交 6692e76f 编写于 作者: M Manish Vasani

Move common Options and CodeStyle related public and internal types into the...

Move common Options and CodeStyle related public and internal types into the shared layer. The public types are renamed to end with a "2" suffix and are internal. These will be the core types that will replace the public Options types to avoid name clashes.
上级 153fec7d
......@@ -3,194 +3,56 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.CodeStyle
#endif
{
internal interface ICodeStyleOption
{
XElement ToXElement();
object Value { get; }
NotificationOption Notification { get; }
ICodeStyleOption WithValue(object value);
ICodeStyleOption WithNotification(NotificationOption notification);
}
/// <summary>
/// Represents a code style option and an associated notification option. Supports
/// being instantiated with T as a <see cref="bool"/> or an <c>enum type</c>.
///
/// CodeStyleOption also has some basic support for migration a <see cref="bool"/> option
/// forward to an <c>enum type</c> option. Specifically, if a previously serialized
/// bool-CodeStyleOption is then deserialized into an enum-CodeStyleOption then 'false'
/// values will be migrated to have the 0-value of the enum, and 'true' values will be
/// migrated to have the 1-value of the enum.
///
/// Similarly, enum-type code options will serialize out in a way that is compatible with
/// hosts that expect the value to be a boolean. Specifically, if the enum value is 0 or 1
/// then those values will write back as false/true.
/// </summary>
/// <inheritdoc cref="CodeStyleOption2{T}"/>
public class CodeStyleOption<T> : ICodeStyleOption, IEquatable<CodeStyleOption<T>>
{
private readonly CodeStyleOption2<T> _codeStyleOptionImpl;
public static CodeStyleOption<T> Default => new CodeStyleOption<T>(default, NotificationOption.Silent);
private const int SerializationVersion = 1;
private NotificationOption _notification;
internal CodeStyleOption(CodeStyleOption2<T> codeStyleOptionImpl)
{
_codeStyleOptionImpl = codeStyleOptionImpl;
}
public CodeStyleOption(T value, NotificationOption notification)
: this(new CodeStyleOption2<T>(value, notification ?? throw new ArgumentNullException(nameof(notification))))
{
Value = value;
_notification = notification ?? throw new ArgumentNullException(nameof(notification));
}
public T Value { get; set; }
public T Value
{
get => _codeStyleOptionImpl.Value;
set => _codeStyleOptionImpl.Value = value;
}
object ICodeStyleOption.Value => this.Value;
NotificationOption2 ICodeStyleOption.Notification => _codeStyleOptionImpl.Notification;
ICodeStyleOption ICodeStyleOption.WithValue(object value) => new CodeStyleOption<T>((T)value, Notification);
ICodeStyleOption ICodeStyleOption.WithNotification(NotificationOption notification) => new CodeStyleOption<T>(Value, notification);
private int EnumValueAsInt32 => (int)(object)Value;
ICodeStyleOption ICodeStyleOption.WithNotification(NotificationOption2 notification) => new CodeStyleOption<T>(Value, notification);
public NotificationOption Notification
{
get => _notification;
set => _notification = value ?? throw new ArgumentNullException(nameof(value));
get => _codeStyleOptionImpl.Notification;
set => _codeStyleOptionImpl.Notification = value ?? throw new ArgumentNullException(nameof(value));
}
public XElement ToXElement() =>
new XElement(nameof(CodeStyleOption<T>), // `nameof()` returns just "CodeStyleOption"
new XAttribute(nameof(SerializationVersion), SerializationVersion),
new XAttribute("Type", GetTypeNameForSerialization()),
new XAttribute(nameof(Value), GetValueForSerialization()),
new XAttribute(nameof(DiagnosticSeverity), Notification.Severity.ToDiagnosticSeverity() ?? DiagnosticSeverity.Hidden));
private object GetValueForSerialization()
{
if (typeof(T) == typeof(string))
{
return Value;
}
else if (typeof(T) == typeof(bool))
{
return Value;
}
else if (IsZeroOrOneValueOfEnum())
{
return EnumValueAsInt32 == 1;
}
else
{
return EnumValueAsInt32;
}
}
private string GetTypeNameForSerialization()
{
if (typeof(T) == typeof(string))
{
return nameof(String);
}
if (typeof(T) == typeof(bool) || IsZeroOrOneValueOfEnum())
{
return nameof(Boolean);
}
else
{
return nameof(Int32);
}
}
private bool IsZeroOrOneValueOfEnum()
{
var intVal = EnumValueAsInt32;
return intVal == 0 || intVal == 1;
}
public XElement ToXElement() => _codeStyleOptionImpl.ToXElement();
public static CodeStyleOption<T> FromXElement(XElement element)
{
var typeAttribute = element.Attribute("Type");
var valueAttribute = element.Attribute(nameof(Value));
var severityAttribute = element.Attribute(nameof(DiagnosticSeverity));
var version = (int)element.Attribute(nameof(SerializationVersion));
if (typeAttribute == null || valueAttribute == null || severityAttribute == null)
{
// data from storage is corrupt, or nothing has been stored yet.
return Default;
}
if (version != SerializationVersion)
{
return Default;
}
var parser = GetParser(typeAttribute.Value);
var value = parser(valueAttribute.Value);
var severity = (DiagnosticSeverity)Enum.Parse(typeof(DiagnosticSeverity), severityAttribute.Value);
return new CodeStyleOption<T>(value, severity switch
{
DiagnosticSeverity.Hidden => NotificationOption.Silent,
DiagnosticSeverity.Info => NotificationOption.Suggestion,
DiagnosticSeverity.Warning => NotificationOption.Warning,
DiagnosticSeverity.Error => NotificationOption.Error,
_ => throw new ArgumentException(nameof(element)),
});
}
private static Func<string, T> GetParser(string type)
=> type switch
{
nameof(Boolean) =>
// Try to map a boolean value. Either map it to true/false if we're a
// CodeStyleOption<bool> or map it to the 0 or 1 value for an enum if we're
// a CodeStyleOption<SomeEnumType>.
(Func<string, T>)(v => Convert(bool.Parse(v))),
nameof(Int32) => v => Convert(int.Parse(v)),
nameof(String) => v => (T)(object)v,
_ => throw new ArgumentException(nameof(type)),
};
private static T Convert(bool b)
{
// If we had a bool and we wanted a bool, then just return this value.
if (typeof(T) == typeof(bool))
{
return (T)(object)b;
}
// Map booleans to the 1/0 value of the enum.
return b ? (T)(object)1 : (T)(object)0;
}
private static T Convert(int i)
{
// We got an int, but we wanted a bool. Map 0 to false, 1 to true, and anything else to default.
if (typeof(T) == typeof(bool))
{
return (T)(object)(i == 1);
}
// If had an int and we wanted an enum, then just return this value.
return (T)(object)(i);
}
=> new CodeStyleOption<T>(CodeStyleOption2<T>.FromXElement(element));
public bool Equals(CodeStyleOption<T> other)
=> EqualityComparer<T>.Default.Equals(Value, other.Value) &&
Notification == other.Notification;
=> _codeStyleOptionImpl.Equals(other?._codeStyleOptionImpl);
public override bool Equals(object obj)
=> obj is CodeStyleOption<T> option &&
Equals(option);
public override int GetHashCode()
=> unchecked((Notification.GetHashCode() * (int)0xA5555529) + Value.GetHashCode());
=> _codeStyleOptionImpl.GetHashCode();
}
}
......@@ -17,6 +17,6 @@ public CodeStyleOptionsProvider()
{
}
public ImmutableArray<IOption> Options { get; } = CodeStyleOptions.AllOptions;
public ImmutableArray<IOption> Options { get; } = CodeStyleOptions2.AllOptions.As<IOption>();
}
}
......@@ -9,28 +9,23 @@
using WorkspacesResources = Microsoft.CodeAnalysis.CodeStyleResources;
#endif
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.CodeStyle
#endif
{
/// <summary>
/// Offers different notification styles for enforcing
/// a code style. Under the hood, it simply maps to <see cref="DiagnosticSeverity"/>
/// </summary>
/// <remarks>
/// This also supports various properties for databinding.
/// </remarks>
/// <completionlist cref="NotificationOption"/>
/// <inheritdoc cref="NotificationOption2"/>
public class NotificationOption
{
public string Name { get; set; }
private readonly NotificationOption2 _notificationOptionImpl;
public string Name
{
get => _notificationOptionImpl.Name;
set => _notificationOptionImpl.Name = value;
}
public ReportDiagnostic Severity
{
get;
set;
get => _notificationOptionImpl.Severity;
set => _notificationOptionImpl.Severity = value;
}
[Obsolete("Use " + nameof(Severity) + " instead.")]
......@@ -40,18 +35,17 @@ public DiagnosticSeverity Value
set => Severity = value.ToReportDiagnostic();
}
public static readonly NotificationOption None = new NotificationOption(WorkspacesResources.None, ReportDiagnostic.Suppress);
public static readonly NotificationOption Silent = new NotificationOption(WorkspacesResources.Refactoring_Only, ReportDiagnostic.Hidden);
public static readonly NotificationOption Suggestion = new NotificationOption(WorkspacesResources.Suggestion, ReportDiagnostic.Info);
public static readonly NotificationOption Warning = new NotificationOption(WorkspacesResources.Warning, ReportDiagnostic.Warn);
public static readonly NotificationOption Error = new NotificationOption(WorkspacesResources.Error, ReportDiagnostic.Error);
public static readonly NotificationOption None = new NotificationOption(NotificationOption2.None);
public static readonly NotificationOption Silent = new NotificationOption(NotificationOption2.Silent);
public static readonly NotificationOption Suggestion = new NotificationOption(NotificationOption2.Suggestion);
public static readonly NotificationOption Warning = new NotificationOption(NotificationOption2.Warning);
public static readonly NotificationOption Error = new NotificationOption(NotificationOption2.Error);
private NotificationOption(string name, ReportDiagnostic severity)
private NotificationOption(NotificationOption2 notificationOptionImpl)
{
Name = name;
Severity = severity;
_notificationOptionImpl = notificationOptionImpl;
}
public override string ToString() => Name;
public override string ToString() => _notificationOptionImpl.ToString();
}
}
......@@ -4,20 +4,16 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Simplification;
namespace Microsoft.CodeAnalysis.Options
{
internal static class EditorConfigFileGenerator
internal static partial class EditorConfigFileGenerator
{
public static string Generate(
ImmutableArray<(string feature, ImmutableArray<IOption> options)> groupedOptions,
......@@ -90,119 +86,5 @@ string GetEditorConfigString(IOption option, IEditorConfigStorageLocation2 edito
return editorConfigString;
}
}
public static void AppendNamingStylePreferencesToEditorConfig(NamingStylePreferences namingStylePreferences, string language, StringBuilder editorconfig)
{
editorconfig.AppendLine($"#### {WorkspacesResources.Naming_styles} ####");
var serializedNameMap = AssignNamesToNamingStyleElements(namingStylePreferences);
var ruleNameMap = AssignNamesToNamingStyleRules(namingStylePreferences, serializedNameMap);
var referencedElements = new HashSet<Guid>();
editorconfig.AppendLine();
editorconfig.AppendLine($"# {WorkspacesResources.Naming_rules}");
foreach (var namingRule in namingStylePreferences.NamingRules)
{
referencedElements.Add(namingRule.SymbolSpecificationID);
referencedElements.Add(namingRule.NamingStyleID);
editorconfig.AppendLine();
editorconfig.AppendLine($"dotnet_naming_rule.{ruleNameMap[namingRule]}.severity = {namingRule.EnforcementLevel.ToNotificationOption(defaultSeverity: DiagnosticSeverity.Hidden).ToEditorConfigString()}");
editorconfig.AppendLine($"dotnet_naming_rule.{ruleNameMap[namingRule]}.symbols = {serializedNameMap[namingRule.SymbolSpecificationID]}");
editorconfig.AppendLine($"dotnet_naming_rule.{ruleNameMap[namingRule]}.style = {serializedNameMap[namingRule.NamingStyleID]}");
}
editorconfig.AppendLine();
editorconfig.AppendLine($"# {WorkspacesResources.Symbol_specifications}");
foreach (var symbolSpecification in namingStylePreferences.SymbolSpecifications)
{
if (!referencedElements.Contains(symbolSpecification.ID))
{
continue;
}
editorconfig.AppendLine();
editorconfig.AppendLine($"dotnet_naming_symbols.{serializedNameMap[symbolSpecification.ID]}.applicable_kinds = {symbolSpecification.ApplicableSymbolKindList.ToEditorConfigString()}");
editorconfig.AppendLine($"dotnet_naming_symbols.{serializedNameMap[symbolSpecification.ID]}.applicable_accessibilities = {symbolSpecification.ApplicableAccessibilityList.ToEditorConfigString(language)}");
editorconfig.AppendLine($"dotnet_naming_symbols.{serializedNameMap[symbolSpecification.ID]}.required_modifiers = {symbolSpecification.RequiredModifierList.ToEditorConfigString(language)}");
}
editorconfig.AppendLine();
editorconfig.AppendLine($"# {WorkspacesResources.Naming_styles}");
foreach (var namingStyle in namingStylePreferences.NamingStyles)
{
if (!referencedElements.Contains(namingStyle.ID))
{
continue;
}
editorconfig.AppendLine();
editorconfig.AppendLine($"dotnet_naming_style.{serializedNameMap[namingStyle.ID]}.required_prefix = {namingStyle.Prefix}");
editorconfig.AppendLine($"dotnet_naming_style.{serializedNameMap[namingStyle.ID]}.required_suffix = {namingStyle.Suffix}");
editorconfig.AppendLine($"dotnet_naming_style.{serializedNameMap[namingStyle.ID]}.word_separator = {namingStyle.WordSeparator}");
editorconfig.AppendLine($"dotnet_naming_style.{serializedNameMap[namingStyle.ID]}.capitalization = {namingStyle.CapitalizationScheme.ToEditorConfigString()}");
}
}
private static ImmutableDictionary<Guid, string> AssignNamesToNamingStyleElements(NamingStylePreferences namingStylePreferences)
{
var symbolSpecificationNames = new HashSet<string>();
var builder = ImmutableDictionary.CreateBuilder<Guid, string>();
foreach (var symbolSpecification in namingStylePreferences.SymbolSpecifications)
{
var name = ToSnakeCaseName(symbolSpecification.Name);
if (!symbolSpecificationNames.Add(name))
{
name = symbolSpecification.ID.ToString("n");
}
builder.Add(symbolSpecification.ID, name);
}
var namingStyleNames = new HashSet<string>();
foreach (var namingStyle in namingStylePreferences.NamingStyles)
{
var name = ToSnakeCaseName(namingStyle.Name);
if (!namingStyleNames.Add(name))
{
name = namingStyle.ID.ToString("n");
}
builder.Add(namingStyle.ID, name);
}
return builder.ToImmutable();
static string ToSnakeCaseName(string name)
{
return new string(name
.Select(ch =>
{
if (char.IsLetterOrDigit(ch))
{
return char.ToLowerInvariant(ch);
}
else
{
return '_';
}
})
.ToArray());
}
}
private static ImmutableDictionary<SerializableNamingRule, string> AssignNamesToNamingStyleRules(NamingStylePreferences namingStylePreferences, ImmutableDictionary<Guid, string> serializedNameMap)
{
var builder = ImmutableDictionary.CreateBuilder<SerializableNamingRule, string>();
foreach (var rule in namingStylePreferences.NamingRules)
{
builder.Add(rule, $"{serializedNameMap[rule.SymbolSpecificationID]}_should_be_{serializedNameMap[rule.NamingStyleID]}");
}
return builder.ToImmutable();
}
}
}
......@@ -7,11 +7,7 @@
using System;
using System.Collections.Immutable;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
public interface IOption
{
......
......@@ -7,15 +7,7 @@
using System;
using Roslyn.Utilities;
#if CODE_STYLE
using WorkspacesResources = Microsoft.CodeAnalysis.CodeStyleResources;
#endif
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
[NonDefaultable]
public readonly struct OptionKey : IEquatable<OptionKey>
......
......@@ -4,11 +4,7 @@
#nullable enable
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
/// <summary>
/// The base type of all types that specify where options are stored.
......
......@@ -7,48 +7,39 @@
using System;
using System.Collections.Immutable;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
/// <summary>
/// Marker interface for <see cref="Option{T}"/>
/// </summary>
internal interface ILanguageSpecificOption : IOptionWithGroup
{
}
/// <summary>
/// An global option. An instance of this class can be used to access an option value from an OptionSet.
/// </summary>
public class Option<T> : ILanguageSpecificOption
public class Option<T> : ILanguageSpecificOption<T>
{
private readonly Option2<T> _optionImpl;
/// <summary>
/// Feature this option is associated with.
/// </summary>
public string Feature { get; }
public string Feature => _optionImpl.Feature;
/// <summary>
/// Optional group/sub-feature for this option.
/// </summary>
internal OptionGroup Group { get; }
internal OptionGroup Group => _optionImpl.Group;
/// <summary>
/// The name of the option.
/// </summary>
public string Name { get; }
public string Name => _optionImpl.Name;
/// <summary>
/// The default value of the option.
/// </summary>
public T DefaultValue { get; }
public T DefaultValue => _optionImpl.DefaultValue;
/// <summary>
/// The type of the option value.
/// </summary>
public Type Type => typeof(T);
public Type Type => _optionImpl.Type;
public ImmutableArray<OptionStorageLocation> StorageLocations { get; }
......@@ -70,6 +61,11 @@ public Option(string feature, string name, T defaultValue, params OptionStorageL
}
internal Option(string feature, OptionGroup group, string name, T defaultValue, params OptionStorageLocation[] storageLocations)
: this(feature, group, name, defaultValue, storageLocations.ToImmutableArray())
{
}
internal Option(string feature, OptionGroup group, string name, T defaultValue, ImmutableArray<OptionStorageLocation> storageLocations)
{
if (string.IsNullOrWhiteSpace(feature))
{
......@@ -81,23 +77,17 @@ internal Option(string feature, OptionGroup group, string name, T defaultValue,
throw new ArgumentException(nameof(name));
}
this.Feature = feature;
this.Group = group ?? throw new ArgumentNullException(nameof(group));
this.Name = name;
this.DefaultValue = defaultValue;
this.StorageLocations = storageLocations.ToImmutableArray();
_optionImpl = new Option2<T>(feature, group, name, defaultValue);
this.StorageLocations = storageLocations;
}
OptionGroup IOptionWithGroup.Group => this.Group;
object? IOption.DefaultValue => this.DefaultValue;
bool IOption.IsPerLanguage => false;
OptionGroup IOptionWithGroup.Group => this.Group;
public override string ToString()
{
return string.Format("{0} - {1}", this.Feature, this.Name);
}
public override string ToString() => _optionImpl.ToString();
public static implicit operator OptionKey(Option<T> option)
{
......
// 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.
#nullable enable
using Microsoft.CodeAnalysis.CodeStyle;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Options
{
internal static class OptionsExtensions
{
public static Option<CodeStyleOption<T>> ToPublicOption<T>(this Option2<CodeStyleOption2<T>> option)
{
RoslynDebug.Assert(option != null);
return new Option<CodeStyleOption<T>>(option.Feature, option.Group, option.Name,
option.DefaultValue, option.StorageLocations.As<OptionStorageLocation>());
}
public static PerLanguageOption<CodeStyleOption<T>> ToPublicOption<T>(this PerLanguageOption2<CodeStyleOption2<T>> option)
{
RoslynDebug.Assert(option != null);
return new PerLanguageOption<CodeStyleOption<T>>(option.Feature, option.Group, option.Name,
option.DefaultValue, option.StorageLocations.As<OptionStorageLocation>());
}
}
}
......@@ -7,49 +7,37 @@
using System;
using System.Collections.Immutable;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
/// <summary>
/// Marker interface for <see cref="PerLanguageOption{T}"/>
/// </summary>
internal interface IPerLanguageOption : IOptionWithGroup
/// <inheritdoc cref="PerLanguageOption2{T}"/>
public class PerLanguageOption<T> : IPerLanguageOption<T>
{
}
private readonly PerLanguageOption2<T> _perLanguageOptionImpl;
/// <summary>
/// An option that can be specified once per language.
/// </summary>
/// <typeparam name="T"></typeparam>
public class PerLanguageOption<T> : IPerLanguageOption
{
/// <summary>
/// Feature this option is associated with.
/// </summary>
public string Feature { get; }
public string Feature => _perLanguageOptionImpl.Feature;
/// <summary>
/// Optional group/sub-feature for this option.
/// </summary>
internal OptionGroup Group { get; }
internal OptionGroup Group => _perLanguageOptionImpl.Group;
/// <summary>
/// The name of the option.
/// </summary>
public string Name { get; }
public string Name => _perLanguageOptionImpl.Name;
/// <summary>
/// The type of the option value.
/// </summary>
public Type Type => typeof(T);
public Type Type => _perLanguageOptionImpl.Type;
/// <summary>
/// The default option value.
/// </summary>
public T DefaultValue { get; }
public T DefaultValue => _perLanguageOptionImpl.DefaultValue;
public ImmutableArray<OptionStorageLocation> StorageLocations { get; }
......@@ -64,6 +52,11 @@ public PerLanguageOption(string feature, string name, T defaultValue, params Opt
}
internal PerLanguageOption(string feature, OptionGroup group, string name, T defaultValue, params OptionStorageLocation[] storageLocations)
: this(feature, group, name, defaultValue, storageLocations.ToImmutableArray())
{
}
internal PerLanguageOption(string feature, OptionGroup group, string name, T defaultValue, ImmutableArray<OptionStorageLocation> storageLocations)
{
if (string.IsNullOrWhiteSpace(feature))
{
......@@ -75,22 +68,16 @@ internal PerLanguageOption(string feature, OptionGroup group, string name, T def
throw new ArgumentException(nameof(name));
}
this.Feature = feature;
this.Group = group ?? throw new ArgumentNullException(nameof(group));
this.Name = name;
this.DefaultValue = defaultValue;
this.StorageLocations = storageLocations.ToImmutableArray();
_perLanguageOptionImpl = new PerLanguageOption2<T>(feature, group, name, defaultValue);
StorageLocations = storageLocations;
}
OptionGroup IOptionWithGroup.Group => this.Group;
object? IOption.DefaultValue => this.DefaultValue;
bool IOption.IsPerLanguage => true;
OptionGroup IOptionWithGroup.Group => this.Group;
public override string ToString()
{
return string.Format("{0} - {1}", this.Feature, this.Name);
}
public override string ToString() => _perLanguageOptionImpl.ToString();
}
}
......@@ -7,22 +7,12 @@
using Microsoft.CodeAnalysis.CodeStyle;
using Roslyn.Utilities;
#if CODE_STYLE
using Microsoft.CodeAnalysis.Internal.Options;
#else
using Microsoft.CodeAnalysis.Options;
#endif
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.CSharp.Internal.CodeStyle
#else
namespace Microsoft.CodeAnalysis.CSharp.CodeStyle
#endif
{
internal static partial class CSharpCodeStyleOptions
{
public static CodeStyleOption<ExpressionBodyPreference> ParseExpressionBodyPreference(
string optionString, CodeStyleOption<ExpressionBodyPreference> @default)
public static CodeStyleOption2<ExpressionBodyPreference> ParseExpressionBodyPreference(
string optionString, CodeStyleOption2<ExpressionBodyPreference> @default)
{
// optionString must be similar to true:error or when_on_single_line:suggestion.
if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification(optionString,
......@@ -34,13 +24,13 @@ internal static partial class CSharpCodeStyleOptions
if (bool.TryParse(value, out var boolValue))
{
return boolValue
? new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, notificationOpt)
: new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, notificationOpt);
? new CodeStyleOption2<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, notificationOpt)
: new CodeStyleOption2<ExpressionBodyPreference>(ExpressionBodyPreference.Never, notificationOpt);
}
if (value == "when_on_single_line")
{
return new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenOnSingleLine, notificationOpt);
return new CodeStyleOption2<ExpressionBodyPreference>(ExpressionBodyPreference.WhenOnSingleLine, notificationOpt);
}
}
}
......@@ -48,7 +38,7 @@ internal static partial class CSharpCodeStyleOptions
return @default;
}
private static string GetExpressionBodyPreferenceEditorConfigString(CodeStyleOption<ExpressionBodyPreference> value)
private static string GetExpressionBodyPreferenceEditorConfigString(CodeStyleOption2<ExpressionBodyPreference> value)
{
var notificationString = value.Notification.ToEditorConfigString();
return value.Value switch
......@@ -60,8 +50,8 @@ private static string GetExpressionBodyPreferenceEditorConfigString(CodeStyleOpt
};
}
public static CodeStyleOption<AddImportPlacement> ParseUsingDirectivesPlacement(
string optionString, CodeStyleOption<AddImportPlacement> @default)
public static CodeStyleOption2<AddImportPlacement> ParseUsingDirectivesPlacement(
string optionString, CodeStyleOption2<AddImportPlacement> @default)
{
// optionString must be similar to outside_namespace:error or inside_namespace:suggestion.
if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification(
......@@ -72,8 +62,8 @@ private static string GetExpressionBodyPreferenceEditorConfigString(CodeStyleOpt
{
return value switch
{
"inside_namespace" => new CodeStyleOption<AddImportPlacement>(AddImportPlacement.InsideNamespace, notificationOpt),
"outside_namespace" => new CodeStyleOption<AddImportPlacement>(AddImportPlacement.OutsideNamespace, notificationOpt),
"inside_namespace" => new CodeStyleOption2<AddImportPlacement>(AddImportPlacement.InsideNamespace, notificationOpt),
"outside_namespace" => new CodeStyleOption2<AddImportPlacement>(AddImportPlacement.OutsideNamespace, notificationOpt),
_ => throw new NotSupportedException(),
};
}
......@@ -82,7 +72,7 @@ private static string GetExpressionBodyPreferenceEditorConfigString(CodeStyleOpt
return @default;
}
public static string GetUsingDirectivesPlacementEditorConfigString(CodeStyleOption<AddImportPlacement> value)
public static string GetUsingDirectivesPlacementEditorConfigString(CodeStyleOption2<AddImportPlacement> value)
{
var notificationString = value.Notification.ToEditorConfigString();
return value.Value switch
......@@ -93,9 +83,9 @@ public static string GetUsingDirectivesPlacementEditorConfigString(CodeStyleOpti
};
}
private static CodeStyleOption<PreferBracesPreference> ParsePreferBracesPreference(
private static CodeStyleOption2<PreferBracesPreference> ParsePreferBracesPreference(
string optionString,
CodeStyleOption<PreferBracesPreference> defaultValue)
CodeStyleOption2<PreferBracesPreference> defaultValue)
{
if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification(
optionString,
......@@ -107,21 +97,21 @@ public static string GetUsingDirectivesPlacementEditorConfigString(CodeStyleOpti
if (bool.TryParse(value, out var boolValue))
{
return boolValue
? new CodeStyleOption<PreferBracesPreference>(PreferBracesPreference.Always, notificationOption)
: new CodeStyleOption<PreferBracesPreference>(PreferBracesPreference.None, notificationOption);
? new CodeStyleOption2<PreferBracesPreference>(PreferBracesPreference.Always, notificationOption)
: new CodeStyleOption2<PreferBracesPreference>(PreferBracesPreference.None, notificationOption);
}
}
if (value == "when_multiline")
{
return new CodeStyleOption<PreferBracesPreference>(PreferBracesPreference.WhenMultiline, notificationOption);
return new CodeStyleOption2<PreferBracesPreference>(PreferBracesPreference.WhenMultiline, notificationOption);
}
}
return defaultValue;
}
private static string GetPreferBracesPreferenceEditorConfigString(CodeStyleOption<PreferBracesPreference> value)
private static string GetPreferBracesPreferenceEditorConfigString(CodeStyleOption2<PreferBracesPreference> value)
{
var notificationString = value.Notification.ToEditorConfigString();
return value.Value switch
......
......@@ -3,18 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Xml.Linq;
#if CODE_STYLE
using Microsoft.CodeAnalysis.CSharp.Internal.CodeStyle;
#else
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
#endif
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.CodeStyle
#endif
{
/// <summary>
/// Defines the known values for <see cref="CSharpCodeStyleOptions.PreferBraces"/>.
......@@ -26,7 +17,7 @@ internal enum PreferBracesPreference
/// </summary>
/// <remarks>
/// <para>The value <c>0</c> is important for serialization compatibility in
/// <see cref="CodeStyleOption{T}.FromXElement(XElement)"/>. Prior to the use of this enum, the serialized value
/// <see cref="CodeStyleOption2{T}.FromXElement(XElement)"/>. Prior to the use of this enum, the serialized value
/// was the <see cref="bool"/> value <see langword="false"/>.</para>
/// </remarks>
None = 0,
......@@ -43,7 +34,7 @@ internal enum PreferBracesPreference
/// </summary>
/// <remarks>
/// <para>The value <c>1</c> is important for serialization compatibility in
/// <see cref="CodeStyleOption{T}.FromXElement(XElement)"/>. Prior to the use of this enum, the serialized value
/// <see cref="CodeStyleOption2{T}.FromXElement(XElement)"/>. Prior to the use of this enum, the serialized value
/// was the <see cref="bool"/> value <see langword="true"/>.</para>
/// </remarks>
Always = 1,
......
......@@ -12,14 +12,10 @@
#if CODE_STYLE
using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions;
#else
using Microsoft.CodeAnalysis.Options;
using OptionSet = Microsoft.CodeAnalysis.Options.OptionSet;
#endif
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.CSharp.Internal.CodeStyle.TypeStyle
#else
namespace Microsoft.CodeAnalysis.CSharp.CodeStyle.TypeStyle
#endif
{
internal static class TypeStyleHelper
{
......
......@@ -4,11 +4,7 @@
using System;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.CSharp.Internal.CodeStyle.TypeStyle
#else
namespace Microsoft.CodeAnalysis.CSharp.CodeStyle.TypeStyle
#endif
{
[Flags]
internal enum UseVarPreference
......
......@@ -2,12 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.CodeStyle
#endif
{
internal enum AccessibilityModifiersRequired
{
......
......@@ -4,24 +4,19 @@
using System.Collections.Immutable;
using System.Diagnostics;
using Roslyn.Utilities;
#if CODE_STYLE
using Microsoft.CodeAnalysis.Internal.Options;
#else
using Microsoft.CodeAnalysis.Options;
#endif
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeStyle
{
internal static class CodeStyleHelpers
{
public static bool TryParseStringEditorConfigCodeStyleOption(string arg, out CodeStyleOption<string> option)
public static bool TryParseStringEditorConfigCodeStyleOption(string arg, out CodeStyleOption2<string> option)
{
if (TryGetCodeStyleValueAndOptionalNotification(
arg, out var value, out var notificationOpt))
{
option = new CodeStyleOption<string>(value, notificationOpt ?? NotificationOption.Silent);
option = new CodeStyleOption2<string>(value, notificationOpt ?? NotificationOption2.Silent);
return true;
}
......@@ -29,7 +24,7 @@ public static bool TryParseStringEditorConfigCodeStyleOption(string arg, out Cod
return false;
}
public static bool TryParseBoolEditorConfigCodeStyleOption(string arg, out CodeStyleOption<bool> option)
public static bool TryParseBoolEditorConfigCodeStyleOption(string arg, out CodeStyleOption2<bool> option)
{
if (TryGetCodeStyleValueAndOptionalNotification(
arg, out var value, out var notificationOpt))
......@@ -41,32 +36,32 @@ public static bool TryParseBoolEditorConfigCodeStyleOption(string arg, out CodeS
// 'true' must always be provided with a notification option.
if (isEnabled == false)
{
notificationOpt ??= NotificationOption.Silent;
option = new CodeStyleOption<bool>(false, notificationOpt);
notificationOpt ??= NotificationOption2.Silent;
option = new CodeStyleOption2<bool>(false, notificationOpt);
return true;
}
else if (notificationOpt != null)
{
option = new CodeStyleOption<bool>(true, notificationOpt);
option = new CodeStyleOption2<bool>(true, notificationOpt);
return true;
}
}
}
option = CodeStyleOption<bool>.Default;
option = CodeStyleOption2<bool>.Default;
return false;
}
/// <summary>
/// Given an editor-config code-style-option, gives back the constituent parts of the
/// option. For example, if the option is "true:error" then "true" will be returned
/// in <paramref name="value"/> and <see cref="NotificationOption.Error"/> will be returned
/// in <paramref name="value"/> and <see cref="NotificationOption2.Error"/> will be returned
/// in <paramref name="notificationOpt"/>. Note that users are allowed to not provide
/// a NotificationOption, so <paramref name="notificationOpt"/> may be null. The caller
/// of this method must decide what to do in that case.
/// </summary>
public static bool TryGetCodeStyleValueAndOptionalNotification(
string arg, out string value, out NotificationOption notificationOpt)
string arg, out string value, out NotificationOption2 notificationOpt)
{
var args = arg.Split(':');
Debug.Assert(args.Length > 0);
......@@ -99,43 +94,43 @@ public static bool TryParseBoolEditorConfigCodeStyleOption(string arg, out CodeS
return false;
}
public static bool TryParseNotification(string value, out NotificationOption notification)
public static bool TryParseNotification(string value, out NotificationOption2 notification)
{
switch (value.Trim())
{
case EditorConfigSeverityStrings.None:
notification = NotificationOption.None;
notification = NotificationOption2.None;
return true;
case EditorConfigSeverityStrings.Refactoring:
case EditorConfigSeverityStrings.Silent:
notification = NotificationOption.Silent;
notification = NotificationOption2.Silent;
return true;
case EditorConfigSeverityStrings.Suggestion: notification = NotificationOption.Suggestion; return true;
case EditorConfigSeverityStrings.Warning: notification = NotificationOption.Warning; return true;
case EditorConfigSeverityStrings.Error: notification = NotificationOption.Error; return true;
case EditorConfigSeverityStrings.Suggestion: notification = NotificationOption2.Suggestion; return true;
case EditorConfigSeverityStrings.Warning: notification = NotificationOption2.Warning; return true;
case EditorConfigSeverityStrings.Error: notification = NotificationOption2.Error; return true;
}
notification = NotificationOption.Silent;
notification = NotificationOption2.Silent;
return false;
}
public static Option<T> CreateOption<T>(
public static Option2<T> CreateOption<T>(
OptionGroup group,
string feature,
string name,
T defaultValue,
ImmutableArray<IOption>.Builder optionsBuilder,
params OptionStorageLocation[] storageLocations)
ImmutableArray<IOption2>.Builder optionsBuilder,
params OptionStorageLocation2[] storageLocations)
{
var option = new Option<T>(feature, group, name, defaultValue, storageLocations);
var option = new Option2<T>(feature, group, name, defaultValue, storageLocations);
optionsBuilder.Add(option);
return option;
}
private static readonly CodeStyleOption<UnusedValuePreference> s_preferNoneUnusedValuePreference =
new CodeStyleOption<UnusedValuePreference>(default, NotificationOption.None);
private static readonly CodeStyleOption2<UnusedValuePreference> s_preferNoneUnusedValuePreference =
new CodeStyleOption2<UnusedValuePreference>(default, NotificationOption2.None);
private static readonly BidirectionalMap<string, UnusedValuePreference> s_unusedExpressionAssignmentPreferenceMap =
new BidirectionalMap<string, UnusedValuePreference>(new[]
......@@ -144,41 +139,41 @@ public static bool TryParseNotification(string value, out NotificationOption not
KeyValuePairUtil.Create("unused_local_variable", UnusedValuePreference.UnusedLocalVariable),
});
public static Option<CodeStyleOption<UnusedValuePreference>> CreateUnusedExpressionAssignmentOption(
public static Option2<CodeStyleOption2<UnusedValuePreference>> CreateUnusedExpressionAssignmentOption(
OptionGroup group,
string feature,
string name,
string editorConfigName,
CodeStyleOption<UnusedValuePreference> defaultValue,
ImmutableArray<IOption>.Builder optionsBuilder)
CodeStyleOption2<UnusedValuePreference> defaultValue,
ImmutableArray<IOption2>.Builder optionsBuilder)
=> CreateOption(
group,
feature,
name,
defaultValue,
optionsBuilder,
storageLocations: new OptionStorageLocation[]{
new EditorConfigStorageLocation<CodeStyleOption<UnusedValuePreference>>(
storageLocations: new OptionStorageLocation2[]{
new EditorConfigStorageLocation<CodeStyleOption2<UnusedValuePreference>>(
editorConfigName,
s => ParseUnusedExpressionAssignmentPreference(s, defaultValue),
o => GetUnusedExpressionAssignmentPreferenceEditorConfigString(o, defaultValue.Value)),
new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{name}Preference")});
private static Optional<CodeStyleOption<UnusedValuePreference>> ParseUnusedExpressionAssignmentPreference(
private static Optional<CodeStyleOption2<UnusedValuePreference>> ParseUnusedExpressionAssignmentPreference(
string optionString,
CodeStyleOption<UnusedValuePreference> defaultCodeStyleOption)
CodeStyleOption2<UnusedValuePreference> defaultCodeStyleOption)
{
if (TryGetCodeStyleValueAndOptionalNotification(optionString,
out var value, out var notificationOpt))
{
return new CodeStyleOption<UnusedValuePreference>(
return new CodeStyleOption2<UnusedValuePreference>(
s_unusedExpressionAssignmentPreferenceMap.GetValueOrDefault(value), notificationOpt ?? defaultCodeStyleOption.Notification);
}
return s_preferNoneUnusedValuePreference;
}
private static string GetUnusedExpressionAssignmentPreferenceEditorConfigString(CodeStyleOption<UnusedValuePreference> option, UnusedValuePreference defaultPreference)
private static string GetUnusedExpressionAssignmentPreferenceEditorConfigString(CodeStyleOption2<UnusedValuePreference> option, UnusedValuePreference defaultPreference)
{
Debug.Assert(s_unusedExpressionAssignmentPreferenceMap.ContainsValue(option.Value));
var value = s_unusedExpressionAssignmentPreferenceMap.GetKeyOrDefault(option.Value) ?? s_unusedExpressionAssignmentPreferenceMap.GetKeyOrDefault(defaultPreference);
......
// 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.Xml.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CodeStyle
{
internal interface ICodeStyleOption
{
XElement ToXElement();
object Value { get; }
NotificationOption2 Notification { get; }
ICodeStyleOption WithValue(object value);
ICodeStyleOption WithNotification(NotificationOption2 notification);
}
/// <summary>
/// Represents a code style option and an associated notification option. Supports
/// being instantiated with T as a <see cref="bool"/> or an <c>enum type</c>.
///
/// CodeStyleOption also has some basic support for migration a <see cref="bool"/> option
/// forward to an <c>enum type</c> option. Specifically, if a previously serialized
/// bool-CodeStyleOption is then deserialized into an enum-CodeStyleOption then 'false'
/// values will be migrated to have the 0-value of the enum, and 'true' values will be
/// migrated to have the 1-value of the enum.
///
/// Similarly, enum-type code options will serialize out in a way that is compatible with
/// hosts that expect the value to be a boolean. Specifically, if the enum value is 0 or 1
/// then those values will write back as false/true.
/// </summary>
internal class CodeStyleOption2<T> : ICodeStyleOption, IEquatable<CodeStyleOption2<T>>
{
public static CodeStyleOption2<T> Default => new CodeStyleOption2<T>(default, NotificationOption2.Silent);
private const int SerializationVersion = 1;
private NotificationOption2 _notification;
public CodeStyleOption2(T value, NotificationOption2 notification)
{
Value = value;
_notification = notification ?? throw new ArgumentNullException(nameof(notification));
}
public T Value { get; set; }
object ICodeStyleOption.Value => this.Value;
ICodeStyleOption ICodeStyleOption.WithValue(object value) => new CodeStyleOption2<T>((T)value, Notification);
ICodeStyleOption ICodeStyleOption.WithNotification(NotificationOption2 notification) => new CodeStyleOption2<T>(Value, notification);
private int EnumValueAsInt32 => (int)(object)Value;
public NotificationOption2 Notification
{
get => _notification;
set => _notification = value ?? throw new ArgumentNullException(nameof(value));
}
public XElement ToXElement() =>
new XElement(nameof(CodeStyleOption2<T>), // `nameof()` returns just "CodeStyleOption"
new XAttribute(nameof(SerializationVersion), SerializationVersion),
new XAttribute("Type", GetTypeNameForSerialization()),
new XAttribute(nameof(Value), GetValueForSerialization()),
new XAttribute(nameof(DiagnosticSeverity), Notification.Severity.ToDiagnosticSeverity() ?? DiagnosticSeverity.Hidden));
private object GetValueForSerialization()
{
if (typeof(T) == typeof(string))
{
return Value;
}
else if (typeof(T) == typeof(bool))
{
return Value;
}
else if (IsZeroOrOneValueOfEnum())
{
return EnumValueAsInt32 == 1;
}
else
{
return EnumValueAsInt32;
}
}
private string GetTypeNameForSerialization()
{
if (typeof(T) == typeof(string))
{
return nameof(String);
}
if (typeof(T) == typeof(bool) || IsZeroOrOneValueOfEnum())
{
return nameof(Boolean);
}
else
{
return nameof(Int32);
}
}
private bool IsZeroOrOneValueOfEnum()
{
var intVal = EnumValueAsInt32;
return intVal == 0 || intVal == 1;
}
public static CodeStyleOption2<T> FromXElement(XElement element)
{
var typeAttribute = element.Attribute("Type");
var valueAttribute = element.Attribute(nameof(Value));
var severityAttribute = element.Attribute(nameof(DiagnosticSeverity));
var version = (int)element.Attribute(nameof(SerializationVersion));
if (typeAttribute == null || valueAttribute == null || severityAttribute == null)
{
// data from storage is corrupt, or nothing has been stored yet.
return Default;
}
if (version != SerializationVersion)
{
return Default;
}
var parser = GetParser(typeAttribute.Value);
var value = parser(valueAttribute.Value);
var severity = (DiagnosticSeverity)Enum.Parse(typeof(DiagnosticSeverity), severityAttribute.Value);
return new CodeStyleOption2<T>(value, severity switch
{
DiagnosticSeverity.Hidden => NotificationOption2.Silent,
DiagnosticSeverity.Info => NotificationOption2.Suggestion,
DiagnosticSeverity.Warning => NotificationOption2.Warning,
DiagnosticSeverity.Error => NotificationOption2.Error,
_ => throw new ArgumentException(nameof(element)),
});
}
private static Func<string, T> GetParser(string type)
=> type switch
{
nameof(Boolean) =>
// Try to map a boolean value. Either map it to true/false if we're a
// CodeStyleOption<bool> or map it to the 0 or 1 value for an enum if we're
// a CodeStyleOption<SomeEnumType>.
(Func<string, T>)(v => Convert(bool.Parse(v))),
nameof(Int32) => v => Convert(int.Parse(v)),
nameof(String) => v => (T)(object)v,
_ => throw new ArgumentException(nameof(type)),
};
private static T Convert(bool b)
{
// If we had a bool and we wanted a bool, then just return this value.
if (typeof(T) == typeof(bool))
{
return (T)(object)b;
}
// Map booleans to the 1/0 value of the enum.
return b ? (T)(object)1 : (T)(object)0;
}
private static T Convert(int i)
{
// We got an int, but we wanted a bool. Map 0 to false, 1 to true, and anything else to default.
if (typeof(T) == typeof(bool))
{
return (T)(object)(i == 1);
}
// If had an int and we wanted an enum, then just return this value.
return (T)(object)(i);
}
public bool Equals(CodeStyleOption2<T> other)
=> EqualityComparer<T>.Default.Equals(Value, other.Value) &&
Notification == other.Notification;
public override bool Equals(object obj)
=> obj is CodeStyleOption2<T> option &&
Equals(option);
public override int GetHashCode()
=> unchecked((Notification.GetHashCode() * (int)0xA5555529) + Value.GetHashCode());
#if !CODE_STYLE
public static implicit operator CodeStyleOption<T>(CodeStyleOption2<T> option)
{
if (option == null)
{
return null;
}
return new CodeStyleOption<T>(option.Value, option.Notification);
}
public static implicit operator CodeStyleOption2<T>(CodeStyleOption<T> option)
{
if (option == null)
{
return null;
}
return new CodeStyleOption2<T>(option.Value, option.Notification);
}
#endif
}
}
// 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.
#if CODE_STYLE
using WorkspacesResources = Microsoft.CodeAnalysis.CodeStyleResources;
#else
using System.Security;
using Roslyn.Utilities;
#endif
namespace Microsoft.CodeAnalysis.CodeStyle
{
/// <summary>
/// Offers different notification styles for enforcing
/// a code style. Under the hood, it simply maps to <see cref="DiagnosticSeverity"/>
/// </summary>
/// <remarks>
/// This also supports various properties for databinding.
/// </remarks>
/// <completionlist cref="NotificationOption2"/>
internal class NotificationOption2
{
public string Name { get; set; }
public ReportDiagnostic Severity
{
get;
set;
}
public static readonly NotificationOption2 None = new NotificationOption2(WorkspacesResources.None, ReportDiagnostic.Suppress);
public static readonly NotificationOption2 Silent = new NotificationOption2(WorkspacesResources.Refactoring_Only, ReportDiagnostic.Hidden);
public static readonly NotificationOption2 Suggestion = new NotificationOption2(WorkspacesResources.Suggestion, ReportDiagnostic.Info);
public static readonly NotificationOption2 Warning = new NotificationOption2(WorkspacesResources.Warning, ReportDiagnostic.Warn);
public static readonly NotificationOption2 Error = new NotificationOption2(WorkspacesResources.Error, ReportDiagnostic.Error);
private NotificationOption2(string name, ReportDiagnostic severity)
{
Name = name;
Severity = severity;
}
public override string ToString() => Name;
#if !CODE_STYLE
public static implicit operator NotificationOption2(NotificationOption notificationOption)
{
return notificationOption.Severity switch
{
ReportDiagnostic.Suppress => None,
ReportDiagnostic.Hidden => Silent,
ReportDiagnostic.Info => Suggestion,
ReportDiagnostic.Warn => Warning,
ReportDiagnostic.Error => Error,
_ => throw ExceptionUtilities.UnexpectedValue(notificationOption.Severity),
};
}
public static implicit operator NotificationOption(NotificationOption2 notificationOption)
{
return notificationOption.Severity switch
{
ReportDiagnostic.Suppress => NotificationOption.None,
ReportDiagnostic.Hidden => NotificationOption.Silent,
ReportDiagnostic.Info => NotificationOption.Suggestion,
ReportDiagnostic.Warn => NotificationOption.Warning,
ReportDiagnostic.Error => NotificationOption.Error,
_ => throw ExceptionUtilities.UnexpectedValue(notificationOption.Severity),
};
}
public override bool Equals(object obj)
{
if (obj is NotificationOption)
{
return this.Equals((NotificationOption2)obj);
}
else if (obj is NotificationOption2 notificationOption2)
{
return this.Equals(notificationOption2);
}
return false;
}
public override int GetHashCode()
{
return Hash.Combine(Name.GetHashCode(), Severity.GetHashCode());
}
public bool Equals(NotificationOption2 notificationOption2)
{
return ReferenceEquals(this, notificationOption2);
}
public static bool operator ==(NotificationOption notificationOption, NotificationOption2 notificationOption2)
{
return notificationOption2.Equals((NotificationOption2)notificationOption);
}
public static bool operator !=(NotificationOption notificationOption, NotificationOption2 notificationOption2)
{
return !notificationOption2.Equals((NotificationOption2)notificationOption);
}
#endif
}
}
......@@ -2,12 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if CODE_STYLE
using Microsoft.CodeAnalysis.CodeStyle;
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.CodeStyle
#endif
{
internal enum OperatorPlacementWhenWrappingPreference
{
......
......@@ -2,11 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.CodeStyle
#endif
{
internal enum ParenthesesPreference
{
......
......@@ -2,11 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.CodeStyle
#endif
{
/// <summary>
/// Preferences for flagging unused parameters.
......
......@@ -2,11 +2,12 @@
using System.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
#if CODE_STYLE
using Microsoft.CodeAnalysis.Internal.Options;
using TOption = Microsoft.CodeAnalysis.Options.IOption2;
#else
using Microsoft.CodeAnalysis.Options;
using TOption = Microsoft.CodeAnalysis.Options.IOption;
#endif
namespace Microsoft.CodeAnalysis
......@@ -14,30 +15,28 @@ namespace Microsoft.CodeAnalysis
internal static class AnalyzerConfigOptionsExtensions
{
#if CODE_STYLE
public static T GetOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, PerLanguageOption<T> option, string language)
public static T GetOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, PerLanguageOption2<T> option, string language)
{
// Language is not used for .editorconfig lookups
_ = language;
return GetOption(analyzerConfigOptions, option);
}
#else
public static T GetOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, Options.Option<T> option)
=> analyzerConfigOptions.GetOptionWithAssertOnFailure<T>(option);
public static T GetOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, Options.PerLanguageOption<T> option)
=> analyzerConfigOptions.GetOptionWithAssertOnFailure<T>(option);
#endif
public static T GetOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, Option<T> option)
{
if (!TryGetEditorConfigOptionOrDefault(analyzerConfigOptions, option, out T value))
{
// There are couple of reasons this assert might fire:
// 1. Attempting to access an option which does not have an IEditorConfigStorageLocation.
// 2. Attempting to access an option which is not exposed from any option provider, i.e. IOptionProvider.Options.
Debug.Fail("Failed to find a .editorconfig key for the option.");
value = option.DefaultValue;
}
public static T GetOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, Option2<T> option)
=> analyzerConfigOptions.GetOptionWithAssertOnFailure<T>(option);
return value;
}
public static T GetOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, PerLanguageOption2<T> option)
=> analyzerConfigOptions.GetOptionWithAssertOnFailure<T>(option);
public static T GetOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, PerLanguageOption<T> option)
private static T GetOptionWithAssertOnFailure<T>(this AnalyzerConfigOptions analyzerConfigOptions, TOption option)
{
if (!TryGetEditorConfigOptionOrDefault(analyzerConfigOptions, option, out T value))
{
......@@ -45,19 +44,19 @@ public static T GetOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, P
// 1. Attempting to access an option which does not have an IEditorConfigStorageLocation.
// 2. Attempting to access an option which is not exposed from any option provider, i.e. IOptionProvider.Options.
Debug.Fail("Failed to find a .editorconfig key for the option.");
value = option.DefaultValue;
value = (T)option.DefaultValue;
}
return value;
}
public static bool TryGetEditorConfigOptionOrDefault<T>(this AnalyzerConfigOptions analyzerConfigOptions, IOption option, out T value)
public static bool TryGetEditorConfigOptionOrDefault<T>(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, out T value)
=> TryGetEditorConfigOption(analyzerConfigOptions, option, useDefaultIfMissing: true, out value);
public static bool TryGetEditorConfigOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, IOption option, out T value)
public static bool TryGetEditorConfigOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, out T value)
=> TryGetEditorConfigOption(analyzerConfigOptions, option, useDefaultIfMissing: false, out value);
private static bool TryGetEditorConfigOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, IOption option, bool useDefaultIfMissing, out T value)
private static bool TryGetEditorConfigOption<T>(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, bool useDefaultIfMissing, out T value)
{
var hasEditorConfigStorage = false;
foreach (var storageLocation in option.StorageLocations)
......
......@@ -4,15 +4,11 @@
using Microsoft.CodeAnalysis.Diagnostics;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.CodeStyle
#endif
{
internal static class NotificationOptionExtensions
{
public static string ToEditorConfigString(this NotificationOption notificationOption)
public static string ToEditorConfigString(this NotificationOption2 notificationOption)
=> notificationOption.Severity.ToEditorConfigString();
}
}
......@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using Microsoft.CodeAnalysis.CodeStyle;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics
......@@ -79,5 +80,30 @@ public static string ToEditorConfigString(this ReportDiagnostic reportDiagnostic
_ => throw ExceptionUtilities.UnexpectedValue(reportDiagnostic)
};
}
public static NotificationOption2 ToNotificationOption(this ReportDiagnostic reportDiagnostic, DiagnosticSeverity defaultSeverity)
{
switch (reportDiagnostic.WithDefaultSeverity(defaultSeverity))
{
case ReportDiagnostic.Error:
return NotificationOption2.Error;
case ReportDiagnostic.Warn:
return NotificationOption2.Warning;
case ReportDiagnostic.Info:
return NotificationOption2.Suggestion;
case ReportDiagnostic.Hidden:
return NotificationOption2.Silent;
case ReportDiagnostic.Suppress:
return NotificationOption2.None;
case ReportDiagnostic.Default:
default:
throw ExceptionUtilities.UnexpectedValue(reportDiagnostic);
}
}
}
}
......@@ -7,11 +7,7 @@
using System;
using Microsoft.CodeAnalysis.CodeStyle;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
internal static class EditorConfigStorageLocation
{
......@@ -24,11 +20,11 @@ public static EditorConfigStorageLocation<int> ForInt32Option(string keyName)
public static EditorConfigStorageLocation<string> ForStringOption(string keyName, string emptyStringRepresentation)
=> new EditorConfigStorageLocation<string>(keyName, s_parseString, (string value) => string.IsNullOrEmpty(value) ? emptyStringRepresentation : s_getStringEditorConfigStringForValue(value));
public static EditorConfigStorageLocation<CodeStyleOption<bool>> ForBoolCodeStyleOption(string keyName)
=> new EditorConfigStorageLocation<CodeStyleOption<bool>>(keyName, s_parseBoolCodeStyleOption, s_getBoolCodeStyleOptionEditorConfigStringForValue);
public static EditorConfigStorageLocation<CodeStyleOption2<bool>> ForBoolCodeStyleOption(string keyName)
=> new EditorConfigStorageLocation<CodeStyleOption2<bool>>(keyName, s_parseBoolCodeStyleOption, s_getBoolCodeStyleOptionEditorConfigStringForValue);
public static EditorConfigStorageLocation<CodeStyleOption<string>> ForStringCodeStyleOption(string keyName)
=> new EditorConfigStorageLocation<CodeStyleOption<string>>(keyName, s_parseStringCodeStyleOption, s_getStringCodeStyleOptionEditorConfigStringForValue);
public static EditorConfigStorageLocation<CodeStyleOption2<string>> ForStringCodeStyleOption(string keyName)
=> new EditorConfigStorageLocation<CodeStyleOption2<string>>(keyName, s_parseStringCodeStyleOption, s_getStringCodeStyleOptionEditorConfigStringForValue);
private static readonly Func<string, Optional<bool>> s_parseBool = ParseBool;
private static Optional<bool> ParseBool(string str)
......@@ -58,18 +54,18 @@ private static Optional<string> ParseString(string str)
private static readonly Func<string, string> s_getStringEditorConfigStringForValue = GetStringEditorConfigStringForValue;
private static string GetStringEditorConfigStringForValue(string value) => value.ToString().Replace("\r", "\\r").Replace("\n", "\\n");
private static readonly Func<string, Optional<CodeStyleOption<bool>>> s_parseBoolCodeStyleOption = ParseBoolCodeStyleOption;
private static Optional<CodeStyleOption<bool>> ParseBoolCodeStyleOption(string str)
=> CodeStyleHelpers.TryParseBoolEditorConfigCodeStyleOption(str, out var result) ? result : new Optional<CodeStyleOption<bool>>();
private static readonly Func<CodeStyleOption<bool>, string> s_getBoolCodeStyleOptionEditorConfigStringForValue = GetBoolCodeStyleOptionEditorConfigStringForValue;
private static string GetBoolCodeStyleOptionEditorConfigStringForValue(CodeStyleOption<bool> value)
private static readonly Func<string, Optional<CodeStyleOption2<bool>>> s_parseBoolCodeStyleOption = ParseBoolCodeStyleOption;
private static Optional<CodeStyleOption2<bool>> ParseBoolCodeStyleOption(string str)
=> CodeStyleHelpers.TryParseBoolEditorConfigCodeStyleOption(str, out var result) ? result : new Optional<CodeStyleOption2<bool>>();
private static readonly Func<CodeStyleOption2<bool>, string> s_getBoolCodeStyleOptionEditorConfigStringForValue = GetBoolCodeStyleOptionEditorConfigStringForValue;
private static string GetBoolCodeStyleOptionEditorConfigStringForValue(CodeStyleOption2<bool> value)
=> $"{(value.Value ? "true" : "false")}:{value.Notification.ToEditorConfigString()}";
private static readonly Func<string, Optional<CodeStyleOption<string>>> s_parseStringCodeStyleOption = ParseStringCodeStyleOption;
private static Optional<CodeStyleOption<string>> ParseStringCodeStyleOption(string str)
=> CodeStyleHelpers.TryParseStringEditorConfigCodeStyleOption(str, out var result) ? result : new Optional<CodeStyleOption<string>>();
private static readonly Func<CodeStyleOption<string>, string> s_getStringCodeStyleOptionEditorConfigStringForValue = GetStringCodeStyleOptionEditorConfigStringForValue;
private static string GetStringCodeStyleOptionEditorConfigStringForValue(CodeStyleOption<string> value)
private static readonly Func<string, Optional<CodeStyleOption2<string>>> s_parseStringCodeStyleOption = ParseStringCodeStyleOption;
private static Optional<CodeStyleOption2<string>> ParseStringCodeStyleOption(string str)
=> CodeStyleHelpers.TryParseStringEditorConfigCodeStyleOption(str, out var result) ? result : new Optional<CodeStyleOption2<string>>();
private static readonly Func<CodeStyleOption2<string>, string> s_getStringCodeStyleOptionEditorConfigStringForValue = GetStringCodeStyleOptionEditorConfigStringForValue;
private static string GetStringCodeStyleOptionEditorConfigStringForValue(CodeStyleOption2<string> value)
=> $"{value.Value.ToLowerInvariant()}:{value.Notification.ToEditorConfigString()}";
}
}
......@@ -4,11 +4,7 @@
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Diagnostics;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
internal static class EditorConfigStorageLocationExtensions
{
......
......@@ -9,22 +9,21 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Utilities;
#if CODE_STYLE
using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions;
#else
using OptionSet = Microsoft.CodeAnalysis.Options.OptionSet;
#endif
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
/// <summary>
/// Specifies that an option should be read from an .editorconfig file.
/// </summary>
internal sealed class EditorConfigStorageLocation<T> : OptionStorageLocation, IEditorConfigStorageLocation2
internal sealed class EditorConfigStorageLocation<T> : OptionStorageLocation2, IEditorConfigStorageLocation2
{
public string KeyName { get; }
......
......@@ -7,15 +7,9 @@
using System;
using System.Collections.Generic;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
{
public interface IEditorConfigStorageLocation
#else
namespace Microsoft.CodeAnalysis.Options
{
internal interface IEditorConfigStorageLocation
#endif
{
bool TryGetOption(IReadOnlyDictionary<string, string?> rawOptions, Type type, out object? value);
}
......
......@@ -6,17 +6,13 @@
#if CODE_STYLE
using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions;
#else
using OptionSet = Microsoft.CodeAnalysis.Options.OptionSet;
#endif
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
{
public interface IEditorConfigStorageLocation2 : IEditorConfigStorageLocation
#else
namespace Microsoft.CodeAnalysis.Options
{
internal interface IEditorConfigStorageLocation2 : IEditorConfigStorageLocation
#endif
{
string KeyName { get; }
......
......@@ -8,15 +8,12 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Utilities;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
internal sealed class NamingStylePreferenceEditorConfigStorageLocation : OptionStorageLocation, IEditorConfigStorageLocation
internal sealed class NamingStylePreferenceEditorConfigStorageLocation : OptionStorageLocation2, IEditorConfigStorageLocation
{
public bool TryGetOption(IReadOnlyDictionary<string, string?> rawOptions, Type type, out object result)
{
......
// 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.
#nullable enable
using System;
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.Options
{
internal interface IOption2
#if !CODE_STYLE
: IOption
#endif
{
#if CODE_STYLE
string Feature { get; }
string Name { get; }
Type Type { get; }
object? DefaultValue { get; }
bool IsPerLanguage { get; }
ImmutableArray<OptionStorageLocation2> StorageLocations { get; }
#endif
}
}
......@@ -4,16 +4,12 @@
#nullable enable
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
/// <summary>
/// Group/sub-feature associated with an <see cref="IOption"/>.
/// Group/sub-feature associated with an <see cref="IOption2"/>.
/// </summary>
internal interface IOptionWithGroup : IOption
internal interface IOptionWithGroup : IOption2
{
/// <summary>
/// Group/sub-feature for this option.
......
......@@ -4,16 +4,14 @@
#nullable enable
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.Options
#endif
{
/// <summary>
/// Specifies that the option should be stored into the user's local registry hive.
/// </summary>
internal sealed class LocalUserProfileStorageLocation : OptionStorageLocation
internal sealed class LocalUserProfileStorageLocation : OptionStorageLocation2
{
public string KeyName { get; }
......
// 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.
#nullable enable
using System;
using System.Collections.Immutable;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Options
{
/// <summary>
/// Marker interface for language specific options.
/// </summary>
internal interface ILanguageSpecificOption : IOptionWithGroup
{
}
/// <summary>
/// Marker interface for language specific options.
/// </summary>
internal interface ILanguageSpecificOption<T> : ILanguageSpecificOption
{
}
/// <summary>
/// An global option. An instance of this class can be used to access an option value from an OptionSet.
/// </summary>
internal class Option2<T> : ILanguageSpecificOption<T>
{
/// <summary>
/// Feature this option is associated with.
/// </summary>
public string Feature { get; }
/// <summary>
/// Optional group/sub-feature for this option.
/// </summary>
internal OptionGroup Group { get; }
/// <summary>
/// The name of the option.
/// </summary>
public string Name { get; }
/// <summary>
/// The default value of the option.
/// </summary>
public T DefaultValue { get; }
/// <summary>
/// The type of the option value.
/// </summary>
public Type Type => typeof(T);
public ImmutableArray<OptionStorageLocation2> StorageLocations { get; }
[Obsolete("Use a constructor that specifies an explicit default value.")]
public Option2(string feature, string name)
: this(feature, name, default!)
{
// This constructor forwards to the next one; it exists to maintain source-level compatibility with older callers.
}
public Option2(string feature, string name, T defaultValue)
: this(feature, name, defaultValue, storageLocations: Array.Empty<OptionStorageLocation2>())
{
}
public Option2(string feature, string name, T defaultValue, params OptionStorageLocation2[] storageLocations)
: this(feature, group: OptionGroup.Default, name, defaultValue, storageLocations)
{
}
internal Option2(string feature, OptionGroup group, string name, T defaultValue, params OptionStorageLocation2[] storageLocations)
: this(feature, group, name, defaultValue, storageLocations.ToImmutableArray())
{
}
internal Option2(string feature, OptionGroup group, string name, T defaultValue, ImmutableArray<OptionStorageLocation2> storageLocations)
{
if (string.IsNullOrWhiteSpace(feature))
{
throw new ArgumentNullException(nameof(feature));
}
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentException(nameof(name));
}
this.Feature = feature;
this.Group = group ?? throw new ArgumentNullException(nameof(group));
this.Name = name;
this.DefaultValue = defaultValue;
this.StorageLocations = storageLocations;
}
#if CODE_STYLE
object? IOption2.DefaultValue => this.DefaultValue;
bool IOption2.IsPerLanguage => false;
#else
object? IOption.DefaultValue => this.DefaultValue;
bool IOption.IsPerLanguage => false;
ImmutableArray<OptionStorageLocation> IOption.StorageLocations
=> this.StorageLocations.As<OptionStorageLocation>();
#endif
OptionGroup IOptionWithGroup.Group => this.Group;
public override string ToString()
{
return string.Format("{0} - {1}", this.Feature, this.Name);
}
public static implicit operator OptionKey2(Option2<T> option)
{
return new OptionKey2(option);
}
#if !CODE_STYLE
public static implicit operator Option<T>(Option2<T> option)
{
RoslynDebug.Assert(option != null);
return new Option<T>(option.Feature, option.Group, option.Name,
option.DefaultValue, option.StorageLocations.As<OptionStorageLocation>());
}
#endif
}
}
......@@ -6,14 +6,10 @@
using System;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
/// <summary>
/// Group/sub-feature associated with an <see cref="IOption"/>.
/// Group/sub-feature associated with an option.
/// </summary>
internal sealed class OptionGroup
{
......
// 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.
#nullable enable
using System;
using Roslyn.Utilities;
#if CODE_STYLE
using WorkspacesResources = Microsoft.CodeAnalysis.CodeStyleResources;
#endif
namespace Microsoft.CodeAnalysis.Options
{
[NonDefaultable]
internal readonly struct OptionKey2 : IEquatable<OptionKey2>
{
public IOption2 Option { get; }
public string? Language { get; }
public OptionKey2(IOption2 option, string? language = null)
{
if (language != null && !option.IsPerLanguage)
{
throw new ArgumentException(WorkspacesResources.A_language_name_cannot_be_specified_for_this_option);
}
else if (language == null && option.IsPerLanguage)
{
throw new ArgumentNullException(WorkspacesResources.A_language_name_must_be_specified_for_this_option);
}
this.Option = option ?? throw new ArgumentNullException(nameof(option));
this.Language = language;
}
public override bool Equals(object? obj)
{
return obj is OptionKey2 key &&
Equals(key);
}
public bool Equals(OptionKey2 other)
{
return Option == other.Option && Language == other.Language;
}
public override int GetHashCode()
{
var hash = Option?.GetHashCode() ?? 0;
if (Language != null)
{
hash = unchecked((hash * (int)0xA5555529) + Language.GetHashCode());
}
return hash;
}
public override string ToString()
{
if (Option is null)
{
return "";
}
var languageDisplay = Option.IsPerLanguage
? $"({Language}) "
: string.Empty;
return languageDisplay + Option.ToString();
}
public static bool operator ==(OptionKey2 left, OptionKey2 right)
{
return left.Equals(right);
}
public static bool operator !=(OptionKey2 left, OptionKey2 right)
{
return !left.Equals(right);
}
#if !CODE_STYLE
public static implicit operator OptionKey(OptionKey2 optionKey)
=> new OptionKey(optionKey.Option, optionKey.Language);
#endif
}
}
// 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.
#nullable enable
namespace Microsoft.CodeAnalysis.Options
{
/// <summary>
/// The base type of all types that specify where options are stored.
/// </summary>
internal abstract class OptionStorageLocation2
#if !CODE_STYLE
: OptionStorageLocation
#endif
{
}
}
// 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.
#nullable enable
using System;
using System.Collections.Immutable;
#if !CODE_STYLE
using Roslyn.Utilities;
#endif
namespace Microsoft.CodeAnalysis.Options
{
/// <summary>
/// Marker interface for <see cref="PerLanguageOption2{T}"/>
/// </summary>
internal interface IPerLanguageOption : IOptionWithGroup
{
}
/// <summary>
/// Marker interface for <see cref="PerLanguageOption2{T}"/>
/// </summary>
internal interface IPerLanguageOption<T> : IPerLanguageOption
{
}
/// <summary>
/// An option that can be specified once per language.
/// </summary>
/// <typeparam name="T"></typeparam>
internal class PerLanguageOption2<T> : IPerLanguageOption<T>
{
/// <summary>
/// Feature this option is associated with.
/// </summary>
public string Feature { get; }
/// <summary>
/// Optional group/sub-feature for this option.
/// </summary>
internal OptionGroup Group { get; }
/// <summary>
/// The name of the option.
/// </summary>
public string Name { get; }
/// <summary>
/// The type of the option value.
/// </summary>
public Type Type => typeof(T);
/// <summary>
/// The default option value.
/// </summary>
public T DefaultValue { get; }
public ImmutableArray<OptionStorageLocation2> StorageLocations { get; }
public PerLanguageOption2(string feature, string name, T defaultValue)
: this(feature, name, defaultValue, storageLocations: Array.Empty<OptionStorageLocation2>())
{
}
public PerLanguageOption2(string feature, string name, T defaultValue, params OptionStorageLocation2[] storageLocations)
: this(feature, group: OptionGroup.Default, name, defaultValue, storageLocations)
{
}
internal PerLanguageOption2(string feature, OptionGroup group, string name, T defaultValue, params OptionStorageLocation2[] storageLocations)
: this(feature, group, name, defaultValue, storageLocations.ToImmutableArray())
{
}
internal PerLanguageOption2(string feature, OptionGroup group, string name, T defaultValue, ImmutableArray<OptionStorageLocation2> storageLocations)
{
if (string.IsNullOrWhiteSpace(feature))
{
throw new ArgumentNullException(nameof(feature));
}
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentException(nameof(name));
}
this.Feature = feature;
this.Group = group ?? throw new ArgumentNullException(nameof(group));
this.Name = name;
this.DefaultValue = defaultValue;
this.StorageLocations = storageLocations;
}
OptionGroup IOptionWithGroup.Group => this.Group;
#if CODE_STYLE
object? IOption2.DefaultValue => this.DefaultValue;
bool IOption2.IsPerLanguage => true;
#else
object? IOption.DefaultValue => this.DefaultValue;
bool IOption.IsPerLanguage => true;
ImmutableArray<OptionStorageLocation> IOption.StorageLocations
=> this.StorageLocations.As<OptionStorageLocation>();
#endif
public override string ToString()
{
return string.Format("{0} - {1}", this.Feature, this.Name);
}
#if !CODE_STYLE
public static implicit operator PerLanguageOption<T>(PerLanguageOption2<T> option)
{
RoslynDebug.Assert(option != null);
return new PerLanguageOption<T>(option.Feature, option.Group, option.Name,
option.DefaultValue, option.StorageLocations.As<OptionStorageLocation>());
}
#endif
}
}
......@@ -6,16 +6,12 @@
using System;
#if CODE_STYLE
namespace Microsoft.CodeAnalysis.Internal.Options
#else
namespace Microsoft.CodeAnalysis.Options
#endif
{
/// <summary>
/// Specifies that the option should be stored into a roamed profile across machines.
/// </summary>
internal sealed class RoamingProfileStorageLocation : OptionStorageLocation
internal sealed class RoamingProfileStorageLocation : OptionStorageLocation2
{
private readonly Func<string, string> _keyNameFromLanguageName;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册