Skip to content
Merged
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
6 changes: 3 additions & 3 deletions src/LLTSharp/DataAccessors/TemplateArrayAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public TemplateArrayAccessor(IEnumerable<TemplateDataAccessor> array)
_array = array?.ToArray() ?? throw new ArgumentNullException(nameof(array));
}

public override TemplateDataAccessor Index(TemplateDataAccessor index)
public override TemplateDataAccessor Index(TemplateDataAccessor index, bool safe)
{
try
{
var i = Convert.ToInt32(index.GetValue());
if (i >= 0 && i < _array.Length)
{
return _array[i];
}
if (safe)
return TemplateNullAccessor.Instance;
throw new TemplateRuntimeException($"Index out of range: {index}, Length: {_array.Length}", dataAccessor: this);
}
catch (TemplateRuntimeException)
Expand Down
8 changes: 4 additions & 4 deletions src/LLTSharp/DataAccessors/TemplateDictionaryAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,21 @@ public TemplateDictionaryAccessor(IDictionary<string, TemplateDataAccessor> dict
Dictionary = new ReadOnlyDictionary<string, TemplateDataAccessor>(_dictionary);
}

public override TemplateDataAccessor Index(TemplateDataAccessor index)
public override TemplateDataAccessor Index(TemplateDataAccessor index, bool safe)
{
return Property(index.ToString());
return Property(index.ToString(), safe);
}

public override bool HasProperty(string name)
{
return _dictionary.ContainsKey(name);
}

public override TemplateDataAccessor Property(string key)
public override TemplateDataAccessor Property(string key, bool safe)
{
if (_dictionary.TryGetValue(key, out var accessor))
return accessor;
return base.Property(key);
return base.Property(key, safe);
}

public override bool AsBoolean()
Expand Down
6 changes: 4 additions & 2 deletions src/LLTSharp/DataAccessors/TemplateObjectAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public override bool HasProperty(string name)
return _propertyAccessors.ContainsKey(name);
}

public override TemplateDataAccessor Property(string key)
public override TemplateDataAccessor Property(string key, bool safe)
{
if (_propertyAccessors.TryGetValue(key, out var accessor))
{
Expand All @@ -70,14 +70,16 @@ public override TemplateDataAccessor Property(string key)
}
catch (Exception ex)
{
if (safe)
return TemplateNullAccessor.Instance;
throw new TemplateRuntimeException(
$"Error accessing property '{key}' on {_target.GetType().Name}",
ex,
dataAccessor: this);
}
}

return base.Property(key);
return base.Property(key, safe);
}

public override bool AsBoolean() => true;
Expand Down
6 changes: 3 additions & 3 deletions src/LLTSharp/DataAccessors/TemplateStringAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ public override object GetValue()
return Value;
}

public override TemplateDataAccessor Index(TemplateDataAccessor index)
public override TemplateDataAccessor Index(TemplateDataAccessor index, bool safe)
{
try
{
var i = Convert.ToInt32(index.GetValue());
if (i >= 0 && i < Value.Length)
{
return new TemplateStringAccessor(Value[i].ToString());
}
if (safe)
return new TemplateStringAccessor(string.Empty);
throw new TemplateRuntimeException($"Index out of range: {index}, Length: {Value.Length}", dataAccessor: this);
}
catch (TemplateRuntimeException)
Expand Down
12 changes: 10 additions & 2 deletions src/LLTSharp/ExpressionNodes/TemplateIndexExpressionNode.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using LLTSharp.DataAccessors;

namespace LLTSharp.ExpressionNodes
{
Expand All @@ -19,23 +20,30 @@ public class TemplateIndexExpressionNode : TemplateExpressionNode
/// </summary>
public TemplateExpressionNode Index { get; }

/// <summary>
/// Whether to return <see cref="TemplateNullAccessor"/> instead of exception if index does not exist.
/// </summary>
public bool SafeMode { get; }

/// <summary>
/// Creates a new instance of the TemplateIndexExpressionNode class.
/// </summary>
/// <param name="child">The child expression node that is being indexed.</param>
/// <param name="index">The index expression node that specifies the index to access.</param>
/// <param name="safe">Whether to return <see cref="TemplateNullAccessor"/> instead of exception if index does not exist.</param>
/// <exception cref="ArgumentNullException"></exception>
public TemplateIndexExpressionNode(TemplateExpressionNode child, TemplateExpressionNode index)
public TemplateIndexExpressionNode(TemplateExpressionNode child, TemplateExpressionNode index, bool safe)
{
Child = child ?? throw new ArgumentNullException(nameof(child));
Index = index ?? throw new ArgumentNullException(nameof(index));
SafeMode = safe;
}

public override TemplateDataAccessor Evaluate(TemplateContextAccessor data)
{
var child = Child.Evaluate(data);
var index = Index.Evaluate(data);
return child.Index(index);
return child.Index(index, SafeMode);
}

public override string ToString()
Expand Down
16 changes: 14 additions & 2 deletions src/LLTSharp/ExpressionNodes/TemplateMethodCallExpressionNode.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using LLTSharp.DataAccessors;

namespace LLTSharp.ExpressionNodes
{
Expand All @@ -19,6 +20,11 @@ public class TemplateMethodCallExpressionNode : TemplateExpressionNode
/// </summary>
public string MethodName { get; }

/// <summary>
/// Whether to return <see cref="TemplateNullAccessor"/> instead of exception if method does not exist.
/// </summary>
public bool SafeMode { get; }

/// <summary>
/// The arguments to the method call expression node.
/// </summary>
Expand All @@ -29,20 +35,26 @@ public class TemplateMethodCallExpressionNode : TemplateExpressionNode
/// </summary>
/// <param name="child">The child expression node that is passed as caller to the method.</param>
/// <param name="methodName">The name of the method to be called.</param>
/// <param name="safe">Whether to return <see cref="TemplateNullAccessor"/> instead of exception if method does not exist.</param>
/// <param name="arguments">The arguments to the method call expression node.</param>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="child"/> parameter is null.</exception>
/// <exception cref="ArgumentException">Thrown when the <paramref name="methodName"/> parameter is null or empty.</exception>
public TemplateMethodCallExpressionNode(TemplateExpressionNode child, string methodName, IEnumerable<TemplateExpressionNode> arguments)
public TemplateMethodCallExpressionNode(TemplateExpressionNode child, string methodName, bool safe, IEnumerable<TemplateExpressionNode> arguments)
{
Child = child ?? throw new ArgumentNullException(nameof(child));
MethodName = string.IsNullOrEmpty(methodName) ? throw new ArgumentException("Method name cannot be null or empty.", nameof(methodName)) : methodName;
SafeMode = safe;
Arguments = arguments.ToArray();
}

public override TemplateDataAccessor Evaluate(TemplateContextAccessor context)
{
var child = Child.Evaluate(context);
return child.Call(MethodName, Arguments.Select(arg => arg.Evaluate(context)).ToArray());

var function = context.Functions.TryGetFunction(MethodName);
if (function != null && function.CanBeMethod)
return function.Call(child, Arguments.Select(arg => arg.Evaluate(context)).ToArray());
return child.Call(MethodName, SafeMode, Arguments.Select(arg => arg.Evaluate(context)).ToArray());
}

public override string ToString()
Expand Down
53 changes: 51 additions & 2 deletions src/LLTSharp/ExpressionNodes/TemplatePropertyExpressionNode.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using LLTSharp.DataAccessors;

namespace LLTSharp.ExpressionNodes
{
Expand All @@ -19,28 +20,76 @@ public class TemplatePropertyExpressionNode : TemplateExpressionNode
/// </summary>
public string PropertyName { get; }

/// <summary>
/// Whether to return <see cref="TemplateNullAccessor"/> instead of exception if property does not exist.
/// </summary>
public bool SafeMode { get; }

/// <summary>
/// Creates a new instance of the <see cref="TemplatePropertyExpressionNode"/> class.
/// </summary>
/// <param name="child">The child expression node that has the property to access.</param>
/// <param name="propertyName">The name of the property to access.</param>
/// <param name="safe">Whether to return <see cref="TemplateNullAccessor"/> instead of exception if property does not exist.</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public TemplatePropertyExpressionNode(TemplateExpressionNode child, string propertyName)
public TemplatePropertyExpressionNode(TemplateExpressionNode child, string propertyName, bool safe)
{
Child = child ?? throw new ArgumentNullException(nameof(child));
PropertyName = string.IsNullOrEmpty(propertyName) ? throw new ArgumentException("Property name cannot be null or empty.", nameof(propertyName)) : propertyName;
SafeMode = safe;
}

public override TemplateDataAccessor Evaluate(TemplateContextAccessor context)
{
var child = Child.Evaluate(context);
return child.Property(PropertyName);
return child.Property(PropertyName, SafeMode);
}

public override string ToString()
{
return $"{Child}.{PropertyName}";
}
}

/// <summary>
/// Represents a property check expression node in a template.
/// </summary>
public class TemplateHasPropertyExpressionNode : TemplateExpressionNode
{
/// <summary>
/// Gets the child expression node that has the property to check.
/// </summary>
public TemplateExpressionNode Child { get; }

/// <summary>
/// Gets the name of the property to check.
/// </summary>
public TemplateExpressionNode PropertyName { get; }

/// <summary>
/// Creates a new instance of the <see cref="TemplateHasPropertyExpressionNode"/> class.
/// </summary>
/// <param name="child">The child expression node that has the property to check.</param>
/// <param name="propertyName">The name of the property to check.</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public TemplateHasPropertyExpressionNode(TemplateExpressionNode child, TemplateExpressionNode propertyName)
{
Child = child ?? throw new ArgumentNullException(nameof(child));
PropertyName = propertyName ?? throw new ArgumentException("Property name cannot be null or empty.", nameof(propertyName));
}

public override TemplateDataAccessor Evaluate(TemplateContextAccessor context)
{
var child = Child.Evaluate(context);
var propertyName = PropertyName.Evaluate(context).ToString();
return new TemplateBooleanAccessor(child.HasProperty(propertyName));
}

public override string ToString()
{
return $"{Child} ? {PropertyName}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ private static string OperatorToString(UnaryOperatorType type)
{
UnaryOperatorType.Negate => "-",
UnaryOperatorType.LogicalNot => "!",
UnaryOperatorType.LengthOf => "#",
_ => throw new ArgumentOutOfRangeException(nameof(type)),
};
}
Expand Down
Loading
Loading