Skip to content

Commit b9fb280

Browse files
Guard against NRE when working with anonymus functions STUD-73041 (#344)
1 parent 1f2f884 commit b9fb280

File tree

2 files changed

+54
-2
lines changed

2 files changed

+54
-2
lines changed

src/Test/TestCases.Workflows/XamlTests.cs

+47
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,53 @@ public void VisualBasic_ChangeCompiler()
199199
VisualBasicSettings.Default.CompilerFactory = references => new VbJitCompiler(references);
200200
}
201201

202+
[Theory]
203+
[InlineData(null)]
204+
[InlineData(typeof(object))]
205+
public async Task VisualBasic_CompileAnonymousTypes(Type targetType)
206+
{
207+
SetupCompilation(out var location, out var namespaces, out var assemblyReferences);
208+
string expressionText = "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\"))})";
209+
210+
var compilationResult = await VisualBasicDesignerHelper.CreatePrecompiledValueAsync(targetType, expressionText, namespaces, assemblyReferences, location);
211+
212+
Assert.Equal(typeof(IEnumerable<object>), compilationResult.ReturnType);
213+
}
214+
215+
[Theory]
216+
[InlineData(null)]
217+
[InlineData(typeof(object))]
218+
public async Task CSharp_CompileAnonymousTypes(Type targetType)
219+
{
220+
SetupCompilation(out var location, out var namespaces, out var assemblyReferences);
221+
string expressionText = "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\"))})";
222+
223+
var compilationResult = await CSharpDesignerHelper.CreatePrecompiledValueAsync(targetType, expressionText, namespaces, assemblyReferences, location);
224+
225+
Assert.Equal(typeof(IEnumerable<object>), compilationResult.ReturnType);
226+
}
227+
228+
private static void SetupCompilation(out ActivityLocationReferenceEnvironment location, out string[] namespaces, out AssemblyReference[] assemblyReferences)
229+
{
230+
var seq = new Sequence();
231+
IList<ValidationError> errors = [];
232+
location = new ActivityLocationReferenceEnvironment();
233+
WorkflowInspectionServices.CacheMetadata(seq, location);
234+
location.Declare(new Variable<string>("in_CountryName"), seq, ref errors);
235+
location.Declare(new Variable<DataTable>("in_dt_OrderExport"), seq, ref errors);
236+
namespaces = ["System", "System.Linq", "System.Data"];
237+
assemblyReferences =
238+
[
239+
new AssemblyReference() { Assembly = typeof(string).Assembly },
240+
new AssemblyReference() { Assembly = typeof(DataTable).Assembly },
241+
new AssemblyReference() { Assembly = typeof(Enumerable).Assembly },
242+
new AssemblyReference() { Assembly = typeof(System.ComponentModel.TypeConverter).Assembly },
243+
new AssemblyReference() { Assembly = typeof(IServiceProvider).Assembly },
244+
new AssemblyReference() { Assembly = Assembly.Load("System.Xml.ReaderWriter") },
245+
new AssemblyReference() { Assembly = Assembly.Load("System.Private.Xml") }
246+
];
247+
}
248+
202249
private class ThrowingJitCompiler : JustInTimeCompiler
203250
{
204251
public override LambdaExpression CompileExpression(ExpressionToCompile compilerRequest) => throw new NotImplementedException();

src/UiPath.Workflow/Activities/ExpressionCompiler.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,16 @@ protected static Type GetSystemType(ITypeSymbol typeSymbol, Assembly assembly)
4343
{
4444
if (namedTypeSymbol.IsGenericType)
4545
{
46-
return assembly.GetType($"{namedTypeSymbol.ContainingNamespace}.{namedTypeSymbol.MetadataName}").MakeGenericType(namedTypeSymbol.TypeArguments.Select(t=> GetSystemType(t, GetAssemblyForType(t))).ToArray());
46+
return assembly.GetType($"{namedTypeSymbol.ContainingNamespace.ToDisplayString()}.{namedTypeSymbol.MetadataName}").MakeGenericType(namedTypeSymbol.TypeArguments.Select(t => GetSystemType(t, GetAssemblyForType(t))).ToArray());
47+
}
48+
49+
if (namedTypeSymbol.IsAnonymousType)
50+
{
51+
return typeof(object);
4752
}
4853
}
4954

50-
return assembly.GetType($"{typeSymbol.ContainingNamespace}.{typeSymbol.MetadataName}");
55+
return assembly.GetType($"{typeSymbol.ContainingNamespace.ToDisplayString()}.{typeSymbol.MetadataName}");
5156
}
5257

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

0 commit comments

Comments
 (0)