Skip to content

Commit

Permalink
Guard against NRE when working with anonymus functions STUD-73041
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-ungureanu-uipath committed Nov 18, 2024
1 parent 1f2f884 commit 97583ac
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
25 changes: 25 additions & 0 deletions src/Test/TestCases.Workflows/XamlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,31 @@ public void VisualBasic_ChangeCompiler()
VisualBasicSettings.Default.CompilerFactory = references => new VbJitCompiler(references);
}

[Theory]
[InlineData(null)]
[InlineData(typeof(object))]
public async Task CompileAnonymousTypes(Type targetType)
{
var seq = new Sequence();
IList<ValidationError> errors = [];
var location = new ActivityLocationReferenceEnvironment();
WorkflowInspectionServices.CacheMetadata(seq, location);
location.Declare(new Variable<string>("in_CountryName"), seq, ref errors);
location.Declare(new Variable<DataTable>("in_dt_OrderExport"), seq, ref errors);

string[] namespaces = ["System", "System.Linq", "System.Data"];
AssemblyReference[] assemblies = [new AssemblyReference() { Assembly = typeof(string).Assembly }, new AssemblyReference() { Assembly = typeof(DataTable).Assembly }, new AssemblyReference() { Assembly = typeof(Enumerable).Assembly }, new AssemblyReference() { Assembly = typeof(System.ComponentModel.TypeConverter).Assembly }, new AssemblyReference() { Assembly = typeof(IServiceProvider).Assembly }, new AssemblyReference() { Assembly = Assembly.Load("System.Xml.ReaderWriter") }, new AssemblyReference() { Assembly = Assembly.Load("System.Private.Xml") } ];

string visualBasicExpressionText = "in_dt_OrderExport.AsEnumerable().Where(Function(row) row.Field(Of String)(\"Country\") = in_CountryName).GroupBy(Function(row) New With {Key .SKU = row.Field(Of String)(\"SKU\"), Key .ProductTitle = row.Field(Of String)(\"Product Title\")}).Select(Function(g) New With {Key .SKU = g.Key.SKU, Key .ProductTitle = g.Key.ProductTitle, Key .NetQTY = g.Sum(Function(row) row.Field(Of Decimal)(\"Net QTY\")), Key .SD = g.Sum(Function(row) row.Field(Of Decimal)(\"S-D\")), Key .Taxes = g.Sum(Function(row) row.Field(Of Decimal)(\"Taxes\"))})";
string cSharpExpressionText = "in_dt_OrderExport.AsEnumerable().Where(row => row.Field<String>(\"Country\") == in_CountryName).GroupBy(row => new { SKU = row.Field<String>(\"SKU\"), ProductTitle = row.Field<String>(\"Product Title\")}).Select(g => new{SKU = g.Key.SKU,ProductTitle = g.Key.ProductTitle,NetQTY = g.Sum(row => row.Field<Decimal>(\"Net QTY\")),SD = g.Sum(row => row.Field<Decimal>(\"S-D\")),Taxes = g.Sum(row => row.Field<Decimal>(\"Taxes\"))})";

var visualBasicCompilationResult = await VisualBasicDesignerHelper.CreatePrecompiledValueAsync(targetType, visualBasicExpressionText, namespaces, assemblies, location);
var cSharpCompilationResult = await CSharpDesignerHelper.CreatePrecompiledValueAsync(targetType, cSharpExpressionText, namespaces, assemblies, location);

Assert.Equal(typeof(IEnumerable<object>), visualBasicCompilationResult.ReturnType);
Assert.Equal(typeof(IEnumerable<object>), cSharpCompilationResult.ReturnType);
}

private class ThrowingJitCompiler : JustInTimeCompiler
{
public override LambdaExpression CompileExpression(ExpressionToCompile compilerRequest) => throw new NotImplementedException();
Expand Down
9 changes: 7 additions & 2 deletions src/UiPath.Workflow/Activities/ExpressionCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,16 @@ protected static Type GetSystemType(ITypeSymbol typeSymbol, Assembly assembly)
{
if (namedTypeSymbol.IsGenericType)
{
return assembly.GetType($"{namedTypeSymbol.ContainingNamespace}.{namedTypeSymbol.MetadataName}").MakeGenericType(namedTypeSymbol.TypeArguments.Select(t=> GetSystemType(t, GetAssemblyForType(t))).ToArray());
return assembly.GetType($"{namedTypeSymbol.ContainingNamespace.ToDisplayString()}.{namedTypeSymbol.MetadataName}").MakeGenericType(namedTypeSymbol.TypeArguments.Select(t => GetSystemType(t, GetAssemblyForType(t))).ToArray());
}

if (namedTypeSymbol.IsAnonymousType)
{
return typeof(object);
}
}

return assembly.GetType($"{typeSymbol.ContainingNamespace}.{typeSymbol.MetadataName}");
return assembly.GetType($"{typeSymbol.ContainingNamespace.ToDisplayString()}.{typeSymbol.MetadataName}");
}

protected abstract Compilation GetCompilation(IReadOnlyCollection<AssemblyReference> assemblies, IReadOnlyCollection<string> namespaces);
Expand Down

0 comments on commit 97583ac

Please sign in to comment.