Skip to content

Commit

Permalink
Merge pull request #72800 from CyrusNajmabadi/nullableEnumOptinos
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi authored Mar 29, 2024
2 parents ca48b2f + bb6d815 commit acaba32
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,20 @@ public bool TryFetch(OptionKey2 optionKey, string storageKey, out object? value)

var underlyingType = Nullable.GetUnderlyingType(storageType);
if (underlyingType?.IsEnum == true)
return manager.TryGetValue(storageKey, out int? value) == GetValueResult.Success ? (value.HasValue ? Enum.ToObject(underlyingType, value.Value) : null) : default(Optional<object?>);
{
if (manager.TryGetValue(storageKey, out int? nullableValue) == GetValueResult.Success)
{
return nullableValue.HasValue ? Enum.ToObject(underlyingType, nullableValue.Value) : null;
}
else if (manager.TryGetValue(storageKey, out int value) == GetValueResult.Success)
{
return Enum.ToObject(underlyingType, value);
}
else
{
return default;
}
}

if (storageType == typeof(NamingStylePreferences))
{
Expand Down
63 changes: 52 additions & 11 deletions src/VisualStudio/Core/Impl/Options/AbstractOptionPageControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,40 @@ private protected void BindToOption<T>(ComboBox comboBox, PerLanguageOption2<T>
_bindingExpressions.Add(bindingExpression);
}

private protected void BindToOption<T>(RadioButton radiobutton, Option2<T> optionKey, T optionValue)
{
var binding = new Binding()
{
Source = new OptionBinding<T>(OptionStore, optionKey),
Path = new PropertyPath("Value"),
UpdateSourceTrigger = UpdateSourceTrigger.Default,
Converter = new RadioButtonCheckedConverter(),
ConverterParameter = optionValue
};

AddSearchHandler(radiobutton);

var bindingExpression = radiobutton.SetBinding(RadioButton.IsCheckedProperty, binding);
_bindingExpressions.Add(bindingExpression);
}

private protected void BindToOption<T>(RadioButton radioButton, Option2<T?> nullableOptionKey, T optionValue, Func<bool> onNullValue) where T : struct
{
var binding = new Binding()
{
Source = new OptionBinding<T?>(OptionStore, nullableOptionKey),
Path = new PropertyPath("Value"),
UpdateSourceTrigger = UpdateSourceTrigger.Default,
Converter = new RadioButtonCheckedConverter<T>(onNullValue),
ConverterParameter = optionValue,
};

AddSearchHandler(radioButton);

var bindingExpression = radioButton.SetBinding(RadioButton.IsCheckedProperty, binding);
_bindingExpressions.Add(bindingExpression);
}

private protected void BindToOption<T>(RadioButton radiobutton, PerLanguageOption2<T> optionKey, T optionValue, string languageName)
{
var binding = new Binding()
Expand Down Expand Up @@ -255,19 +289,26 @@ private protected void AddSearchHandler(ContentControl control)
}
}

public class RadioButtonCheckedConverter : IValueConverter
public sealed class RadioButtonCheckedConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return value.Equals(parameter);
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
=> value.Equals(parameter);

public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return value.Equals(true) ? parameter : Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> value.Equals(true) ? parameter : Binding.DoNothing;
}

public sealed class RadioButtonCheckedConverter<T>(Func<bool> onNullValue) : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
=> value switch
{
null => onNullValue(),
_ => value.Equals(parameter),
};

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> value.Equals(true) ? parameter : Binding.DoNothing;
}

public class ComboBoxItemTagToIndexConverter : IValueConverter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,18 @@
using System.Windows;
using System.Windows.Data;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options.Converters
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options.Converters;

internal sealed class NullableBoolOptionConverter(Func<bool> onNullValue) : IValueConverter
{
internal class NullableBoolOptionConverter : IValueConverter
{
private readonly Func<bool> _onNullValue;
public NullableBoolOptionConverter(Func<bool> onNullValue)
public object Convert(object? value, Type targetType, object parameter, CultureInfo culture)
=> value switch
{
_onNullValue = onNullValue;
}

public object Convert(object? value, Type targetType, object parameter, CultureInfo culture)
=> value switch
{
null => _onNullValue(),
bool b => b,
_ => DependencyProperty.UnsetValue
};
null => onNullValue(),
bool b => b,
_ => DependencyProperty.UnsetValue
};

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,6 @@ private static (object? value, object? storageValue) GetSomeOptionValue(Type opt
optionType == typeof(ImmutableArray<string>) ? (ImmutableArray.Create("a", "b"), new[] { "a", "b" }) :
throw ExceptionUtilities.UnexpectedValue(optionType);

private static Type GetStorageType(Type optionType)
=> optionType.IsEnum ? typeof(int) :
(Nullable.GetUnderlyingType(optionType)?.IsEnum == true) ? typeof(int?) :
optionType == typeof(NamingStylePreferences) ? typeof(string) :
typeof(ICodeStyleOption2).IsAssignableFrom(optionType) ? typeof(string) :
optionType == typeof(ImmutableArray<string>) ? typeof(string[]) :
optionType == typeof(ImmutableArray<bool>) ? typeof(bool[]) :
optionType == typeof(ImmutableArray<int>) ? typeof(int[]) :
optionType == typeof(ImmutableArray<long>) ? typeof(long[]) :
optionType;

private static bool IsDefaultImmutableArray(object array)
=> (bool)array.GetType().GetMethod("get_IsDefault").Invoke(array, [])!;

Expand Down Expand Up @@ -229,11 +218,10 @@ public void SettingsManagerReadOptionValue_Error(
Type optionType)
{
var (optionValue, storageValue) = GetSomeOptionValue(optionType);
var storageType = GetStorageType(optionType);

var mockManager = new MockSettingsManager()
{
GetValueImpl = (_, type) => (type == storageType ? specializedTypeResult : GetValueResult.Success, storageValue)
GetValueImpl = (_, type) => (specializedTypeResult, storageValue)
};

var result = VisualStudioSettingsOptionPersister.TryReadOptionValue(mockManager, "key", optionType, optionValue);
Expand Down

0 comments on commit acaba32

Please sign in to comment.