Skip to content

Commit

Permalink
fix: support nullable enums
Browse files Browse the repository at this point in the history
  • Loading branch information
rdavisau committed May 10, 2019
1 parent fc8fc81 commit da1683b
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 16 deletions.
28 changes: 21 additions & 7 deletions src/DumpEditable/EditorRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,32 @@ public static EditorRule ForNestedAnonymousType()

public static EditorRule ForEnums() =>
EditorRule.For(
(_, p) => p.PropertyType.IsEnum,
(o, p, get, set) => EditableDumpContainer.DefaultOptions.OptionsEditor(
p.PropertyType.GetEnumValues().OfType<object>(),
false,
null)(o,p,get,set));
(_, p) => p.PropertyType.IsEnum || p.PropertyType.IsNullableEnum(),
(o, p, get, set) =>
{
var isNullable = p.PropertyType.IsNullableEnum();
var type = isNullable
? Nullable.GetUnderlyingType(p.PropertyType)
: p.PropertyType;
var options = type.GetEnumValues().OfType<object>().ToList();
return EditableDumpContainer.DefaultOptions.OptionsEditor(
options,
isNullable
? NullableOptionInclusionKind.IncludeAtEnd
: NullableOptionInclusionKind.DontInclude,
null)(o, p, get, set);
});

public static EditorRule ForBool() =>
EditorRule.For(
(_, p) => p.PropertyType == typeof(bool) || p.PropertyType == typeof(bool?),
(o, p, get, set) => EditableDumpContainer.DefaultOptions.OptionsEditor(
new [] { true, false }.OfType<object>(),
p.PropertyType == typeof(bool?),
p.PropertyType == typeof(bool?)
? NullableOptionInclusionKind.IncludeAtEnd
: NullableOptionInclusionKind.DontInclude,
null)(o, p, get, set));

public static EditorRule ForTypeWithStringBasedEditor<T>(ParseFunc<string, T, bool> parseFunc, bool supportNullable = true, bool supportEnumerable = true)
Expand All @@ -95,7 +109,7 @@ public static EditorRule ForTypeWithStringBasedEditor<T>(ParseFunc<string, T, bo
return ret;
};

public delegate V ParseFunc<T, U, V>(T input, out U output);

public const string NullString = "(null)";
Expand Down
37 changes: 29 additions & 8 deletions src/DumpEditable/Editors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Reflection;
using LINQPad.Controls;
using LINQPad.DumpEditable.Helpers;
using LINQPad.DumpEditable.Models;
using Microsoft.VisualBasic;
using Newtonsoft.Json;

Expand Down Expand Up @@ -54,11 +55,11 @@ public static class Editors
};

public static Func<object, PropertyInfo, Func<object>, Action<object>, object> ChoicesWithRadioButtons<T>(
IEnumerable<T> choices, bool allowNull, Func<T, string> toString = null) =>
ChoicesWithRadioButtons(choices.OfType<object>(), allowNull, o => toString((T) o));
IEnumerable<T> choices, NullableOptionInclusionKind nullKind, Func<T, string> toString = null) =>
ChoicesWithRadioButtons(choices.OfType<object>(), nullKind, o => toString((T) o));

public static Func<object, PropertyInfo, Func<object>, Action<object>, object> ChoicesWithRadioButtons(
IEnumerable<object> choices, bool allowNull, Func<object, string> toString = null) =>
IEnumerable<object> choices, NullableOptionInclusionKind nullKind, Func<object, string> toString = null) =>
(o, p, gv, sv) =>
{
var group = Guid.NewGuid().ToString();
Expand All @@ -69,22 +70,42 @@ public static class Editors
.Select(x => new RadioButton(@group, toString?.Invoke(x) ?? $"{x}", x.Equals(v), b => sv(x)))
.ToList();
if (allowNull)
radioButtons.Add(new RadioButton(@group, NullString, v == null, _ => sv(null)));
var nullOption = new RadioButton(@group, NullString, v == null, _ => sv(null));
switch (nullKind)
{
case NullableOptionInclusionKind.IncludeAtStart:
radioButtons.Insert(0, nullOption);
break;
case NullableOptionInclusionKind.IncludeAtEnd:
radioButtons.Add(nullOption);
break;
}
return Util.HorizontalRun((bool)true, (IEnumerable)radioButtons);
};

public static Func<object, PropertyInfo, Func<object>, Action<object>, object> ChoicesWithHyperlinqs<T>(
IEnumerable<T> choices, bool allowNull, Func<T, string> toString = null) =>
IEnumerable<T> choices, NullableOptionInclusionKind nullKind, Func<T, string> toString = null) =>
(o, p, gv, sv) =>
{
var preceding = new object[] {gv(), "["};
var trailing = new object[] {"]"};
var values = choices.Select(x => new Hyperlinq(() => sv(x), toString?.Invoke(x) ?? $"{x}")).ToList();
if (allowNull)
values.Add(new Hyperlinq(() => sv(null), NullString ));
var nullOption = new Hyperlinq(() => sv(null), NullString);
switch (nullKind)
{
case NullableOptionInclusionKind.IncludeAtStart:
values.Insert(0, nullOption);
break;
case NullableOptionInclusionKind.IncludeAtEnd:
values.Add(nullOption);
break;
}
return Util.HorizontalRun(
true,
Expand Down
3 changes: 3 additions & 0 deletions src/DumpEditable/Helpers/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@ public static Type GetArrayLikeElementType(this Type type)
.Select(t => t.GenericTypeArguments[0]).FirstOrDefault();
return enumType;
}

public static bool IsNullableEnum(this Type t)
=> (Nullable.GetUnderlyingType(t)?.IsEnum ?? false);
}
}
2 changes: 1 addition & 1 deletion src/DumpEditable/Models/DumpEditableOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class DumpEditableOptions
public bool AutomaticallyKeepQueryRunning { get; set; }
public bool FailSilently { get; set; }

public Func<IEnumerable<object>, bool, Func<object,string>, Func<object, PropertyInfo, Func<object>, Action<object>, object>> OptionsEditor;
public Func<IEnumerable<object>, NullableOptionInclusionKind, Func<object,string>, Func<object, PropertyInfo, Func<object>, Action<object>, object>> OptionsEditor;
public Func<EditorRule.ParseFunc<string, object, bool>, bool, bool, Func<object, PropertyInfo, Func<object>, Action<object>, object>> StringBasedEditor;
}
}
9 changes: 9 additions & 0 deletions src/DumpEditable/Models/NullableOptionInclusionKind.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace LINQPad.DumpEditable.Models
{
public enum NullableOptionInclusionKind
{
DontInclude,
IncludeAtStart,
IncludeAtEnd
}
}

0 comments on commit da1683b

Please sign in to comment.