UO.TryGetProperty should determine the result value (#2592)

Issue https://github.com/microsoft/Power-Fx/issues/2591.
This commit is contained in:
Anderson Silva 2024-08-13 18:42:04 -05:00 коммит произвёл GitHub
Родитель 8c5342c598
Коммит 72f09636da
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 61 добавлений и 1 удалений

Просмотреть файл

@ -101,6 +101,31 @@ namespace Microsoft.PowerFx.Types
public abstract bool TryGetProperty(string value, out IUntypedObject result);
/// <summary>
/// Get the property value of the untyped object.
/// Hosts should override this method in case a different return value is needed. For example, a host may want to return a ErrorValue in case of a missing property.
/// </summary>
/// <param name="value"></param>
/// <param name="returnType"></param>
/// <param name="span"></param>
/// <returns></returns>
public virtual FormulaValue GetProperty(string value, FormulaType returnType)
{
if (TryGetProperty(value, out var res))
{
if (res.Type == FormulaType.Blank)
{
return new BlankValue(IRContext.NotInSource(returnType));
}
return new UntypedObjectValue(IRContext.NotInSource(returnType), res);
}
else
{
return new BlankValue(IRContext.NotInSource(returnType));
}
}
public abstract bool TryGetPropertyNames(out IEnumerable<string> propertyNames);
/// <summary>

Просмотреть файл

@ -558,7 +558,12 @@ namespace Microsoft.PowerFx
if (arg1 is UntypedObjectValue cov && arg2 is StringValue sv)
{
if (cov.Impl.Type is ExternalType et && (et.Kind == ExternalTypeKind.Object || et.Kind == ExternalTypeKind.ArrayAndObject))
{
{
if (cov.Impl is UntypedObjectBase untypedObjectBase)
{
return untypedObjectBase.GetProperty(sv.Value, node.IRContext.ResultType);
}
if (cov.Impl.TryGetProperty(sv.Value, out var res))
{
if (res.Type == FormulaType.Blank)

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Data;
using System.Linq;
using Microsoft.PowerFx.Core.IR;
using Microsoft.PowerFx.Syntax;
using Microsoft.PowerFx.Types;
using Xunit;
@ -138,6 +139,30 @@ namespace Microsoft.PowerFx.Interpreter.Tests
Assert.Equal(97m, result.ToObject());
}
[Fact]
public void PadUntypedObjectMissingProperty()
{
var uo1 = new PadUntypedObject(GetDataTable());
var uo2 = new PadUntypedObject2(GetDataTable());
var uov1 = new UntypedObjectValue(IRContext.NotInSource(FormulaType.UntypedObject), uo1);
var uov2 = new UntypedObjectValue(IRContext.NotInSource(FormulaType.UntypedObject), uo2);
RecalcEngine engine = new RecalcEngine();
engine.Config.SymbolTable.EnableMutationFunctions();
engine.UpdateVariable("padTable1", uov1);
engine.UpdateVariable("padTable2", uov2);
// PadUntypedObject does not override GetProperty. Returns blank if property is missing.
var result1 = engine.Eval(@"Index(padTable1, 1).Missing");
Assert.IsType<BlankValue>(result1);
// PadUntypedObject2 overrides GetProperty. Returns error if property is missing.
var result2 = engine.Eval(@"Index(padTable2, 1).Missing");
Assert.IsType<ErrorValue>(result2);
}
private DataTable GetDataTable()
{
var dt = new DataTable("someTable");
@ -562,6 +587,11 @@ namespace Microsoft.PowerFx.Interpreter.Tests
throw new CustomFunctionErrorException("Something went wrong.", ErrorKind.InvalidArgument);
}
public override FormulaValue GetProperty(string value, FormulaType returnType)
{
return new ErrorValue(IRContext.NotInSource(returnType), new ExpressionError() { Kind = ErrorKind.InvalidArgument });
}
}
#endregion
}