Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/Bonsai.Scripting.Expressions.Tests/ExpressionScriptingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,23 @@ public Task TestCasingCompatibility<TSource, TResult>(string expression, TSource
return AssertExpressionTransform(expression, value, expected);
}

[TestMethod]
[DataRow("it.Value == NestedEnum.B", true)]
[DataRow("NestedEnum(it.Value + 1)", NestedEnum.C)]
public Task TestNestedPropertyType<TResult>(string expression, TResult expected)
{
return AssertExpressionTransform(expression, new NestedElement { Value = NestedEnum.B }, expected);
}

[TestMethod]
[DataRow("it.Element.Value == NestedEnum.B", true)]
[DataRow("NestedElement(object(it.Element)).Value", NestedEnum.B)]
public Task TestTransitiveNestedPropertyType<TResult>(string expression, TResult expected)
{
var value = new NestedContainer { Element = new NestedElement { Value = NestedEnum.B } };
return AssertExpressionTransform(expression, value, expected);
}

[TestMethod]
[DataRow("")]
[DataRow("string(it)")]
Expand All @@ -79,6 +96,18 @@ public Task TestInvalidExpression(string expression)
AssertExpressionTransform(expression, 42, (object)null));
}

public enum NestedEnum { A, B, C }

public class NestedElement
{
public NestedEnum Value { get; set; }
}

public class NestedContainer
{
public NestedElement Element { get; set; }
}

class Return<TValue>(TValue value) : Source<TValue>
{
public TValue Value { get; } = value;
Expand Down
27 changes: 18 additions & 9 deletions src/Bonsai.Scripting.Expressions/ParsingConfigHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,25 @@ static IDynamicLinqCustomTypeProvider CreateCustomTypeProvider(ParsingConfig con

static IEnumerable<Type> EnumerateTypeHierarchy(Type type)
{
var interfaces = type.GetInterfaces();
for (int i = 0; i < interfaces.Length; i++)
var visited = new HashSet<Type>();
var stack = new Stack<Type>();
stack.Push(type);
while (stack.Count > 0)
{
yield return interfaces[i];
}

while (type is not null)
{
yield return type;
type = type.BaseType;
var current = stack.Pop();
if (!visited.Add(current)) continue;
foreach (var interfaceType in current.GetInterfaces())
{
yield return interfaceType;
}
for (var baseType = current; baseType is not null; baseType = baseType.BaseType)
{
yield return baseType;
}
foreach (var property in current.GetProperties())
{
stack.Push(property.PropertyType);
}
}
}

Expand Down
Loading