ptupitsyn commented on code in PR #7933:
URL: https://github.com/apache/ignite-3/pull/7933#discussion_r3038363207
##########
modules/platforms/dotnet/Apache.Ignite/Internal/Linq/IgniteQueryParser.cs:
##########
@@ -78,16 +85,77 @@ private static CompoundExpressionTreeProcessor
CreateCompoundProcessor(
return new CompoundExpressionTreeProcessor(
new IExpressionTreeProcessor[]
{
- new PartialEvaluatingExpressionTreeProcessor(new
NullEvaluatableExpressionFilter()),
+ new PartialEvaluatingExpressionTreeProcessor(new
IgniteEvaluatableExpressionFilter()),
new TransformingExpressionTreeProcessor(transformationProvider)
});
}
/// <summary>
- /// Empty implementation of IEvaluatableExpressionFilter.
+ /// Implementation of IEvaluatableExpressionFilter.
/// </summary>
- private sealed class NullEvaluatableExpressionFilter :
EvaluatableExpressionFilterBase
+ private sealed class IgniteEvaluatableExpressionFilter :
EvaluatableExpressionFilterBase
{
- // No-op.
+ // Ignores implicit ReadOnlySpan conversion to support C# 14 first
class span Contains.
+ public override bool IsEvaluatableMethodCall(MethodCallExpression node)
+ {
+ ArgumentNullException.ThrowIfNull(node);
+ if
(MemoryExtensionsContainsExpressionTransformer.IsSpanImplicitConversion(node))
+ {
+ return false;
+ }
+
+ return base.IsEvaluatableMethodCall(node);
+ }
+ }
+
+ /// <summary>
+ /// Implementation of IExpressionTransformer handling C# 14 first class
span Contains.
+ /// </summary>
+ private sealed class MemoryExtensionsContainsExpressionTransformer :
IExpressionTransformer<MethodCallExpression>
+ {
+ private static readonly MethodInfo SourceMethodInfo =
typeof(MemoryExtensions)
+ .GetMethod(nameof(MemoryExtensions.Contains), [
+
typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)),
+ Type.MakeGenericMethodParameter(0)
+ ])!;
+
+ private static readonly MethodInfo TargetMethodInfo =
typeof(Enumerable)
+ .GetMethod(nameof(Enumerable.Contains), [
+
typeof(IEnumerable<>).MakeGenericType(Type.MakeGenericMethodParameter(0)),
+ Type.MakeGenericMethodParameter(0)
+ ])!;
+
+#pragma warning disable CA1819
+ public ExpressionType[] SupportedExpressionTypes =>
[ExpressionType.Call];
+#pragma warning restore CA1819
+
+ public static bool
IsSpanImplicitConversion([NotNullWhen(true)]MethodCallExpression? node) =>
+ node?.Method is { IsSpecialName: true, Name: "op_Implicit" }
+ && node.Method.DeclaringType is { IsGenericType: true }
+ && node.Method.DeclaringType.GetGenericTypeDefinition() ==
typeof(ReadOnlySpan<>);
+
+ public Expression Transform(MethodCallExpression expression)
+ {
+ if (expression.Method.IsConstructedGenericMethod &&
expression.Method.GetGenericMethodDefinition() == SourceMethodInfo)
Review Comment:
Invert if to reduce nesting?
##########
modules/platforms/dotnet/Apache.Ignite/Internal/Linq/IgniteQueryParser.cs:
##########
@@ -78,16 +85,77 @@ private static CompoundExpressionTreeProcessor
CreateCompoundProcessor(
return new CompoundExpressionTreeProcessor(
new IExpressionTreeProcessor[]
{
- new PartialEvaluatingExpressionTreeProcessor(new
NullEvaluatableExpressionFilter()),
+ new PartialEvaluatingExpressionTreeProcessor(new
IgniteEvaluatableExpressionFilter()),
new TransformingExpressionTreeProcessor(transformationProvider)
});
}
/// <summary>
- /// Empty implementation of IEvaluatableExpressionFilter.
+ /// Implementation of IEvaluatableExpressionFilter.
/// </summary>
- private sealed class NullEvaluatableExpressionFilter :
EvaluatableExpressionFilterBase
+ private sealed class IgniteEvaluatableExpressionFilter :
EvaluatableExpressionFilterBase
{
- // No-op.
+ // Ignores implicit ReadOnlySpan conversion to support C# 14 first
class span Contains.
+ public override bool IsEvaluatableMethodCall(MethodCallExpression node)
+ {
+ ArgumentNullException.ThrowIfNull(node);
+ if
(MemoryExtensionsContainsExpressionTransformer.IsSpanImplicitConversion(node))
+ {
+ return false;
+ }
+
+ return base.IsEvaluatableMethodCall(node);
+ }
+ }
+
+ /// <summary>
+ /// Implementation of IExpressionTransformer handling C# 14 first class
span Contains.
+ /// </summary>
+ private sealed class MemoryExtensionsContainsExpressionTransformer :
IExpressionTransformer<MethodCallExpression>
+ {
+ private static readonly MethodInfo SourceMethodInfo =
typeof(MemoryExtensions)
+ .GetMethod(nameof(MemoryExtensions.Contains), [
+
typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)),
+ Type.MakeGenericMethodParameter(0)
+ ])!;
+
+ private static readonly MethodInfo TargetMethodInfo =
typeof(Enumerable)
+ .GetMethod(nameof(Enumerable.Contains), [
+
typeof(IEnumerable<>).MakeGenericType(Type.MakeGenericMethodParameter(0)),
+ Type.MakeGenericMethodParameter(0)
+ ])!;
+
+#pragma warning disable CA1819
+ public ExpressionType[] SupportedExpressionTypes =>
[ExpressionType.Call];
+#pragma warning restore CA1819
Review Comment:
```suggestion
[SuppressMessage("Performance", "CA1819:Properties should not return
arrays", Justification = "Interface impl")]
public ExpressionType[] SupportedExpressionTypes =>
[ExpressionType.Call];
```
##########
modules/platforms/dotnet/Apache.Ignite/Internal/Linq/IgniteQueryParser.cs:
##########
@@ -78,16 +85,77 @@ private static CompoundExpressionTreeProcessor
CreateCompoundProcessor(
return new CompoundExpressionTreeProcessor(
new IExpressionTreeProcessor[]
{
- new PartialEvaluatingExpressionTreeProcessor(new
NullEvaluatableExpressionFilter()),
+ new PartialEvaluatingExpressionTreeProcessor(new
IgniteEvaluatableExpressionFilter()),
new TransformingExpressionTreeProcessor(transformationProvider)
});
}
/// <summary>
- /// Empty implementation of IEvaluatableExpressionFilter.
+ /// Implementation of IEvaluatableExpressionFilter.
/// </summary>
- private sealed class NullEvaluatableExpressionFilter :
EvaluatableExpressionFilterBase
+ private sealed class IgniteEvaluatableExpressionFilter :
EvaluatableExpressionFilterBase
{
- // No-op.
+ // Ignores implicit ReadOnlySpan conversion to support C# 14 first
class span Contains.
+ public override bool IsEvaluatableMethodCall(MethodCallExpression node)
+ {
+ ArgumentNullException.ThrowIfNull(node);
+ if
(MemoryExtensionsContainsExpressionTransformer.IsSpanImplicitConversion(node))
+ {
+ return false;
+ }
+
+ return base.IsEvaluatableMethodCall(node);
+ }
+ }
+
+ /// <summary>
+ /// Implementation of IExpressionTransformer handling C# 14 first class
span Contains.
+ /// </summary>
+ private sealed class MemoryExtensionsContainsExpressionTransformer :
IExpressionTransformer<MethodCallExpression>
+ {
+ private static readonly MethodInfo SourceMethodInfo =
typeof(MemoryExtensions)
+ .GetMethod(nameof(MemoryExtensions.Contains), [
+
typeof(ReadOnlySpan<>).MakeGenericType(Type.MakeGenericMethodParameter(0)),
+ Type.MakeGenericMethodParameter(0)
+ ])!;
+
+ private static readonly MethodInfo TargetMethodInfo =
typeof(Enumerable)
+ .GetMethod(nameof(Enumerable.Contains), [
+
typeof(IEnumerable<>).MakeGenericType(Type.MakeGenericMethodParameter(0)),
+ Type.MakeGenericMethodParameter(0)
+ ])!;
+
+#pragma warning disable CA1819
+ public ExpressionType[] SupportedExpressionTypes =>
[ExpressionType.Call];
+#pragma warning restore CA1819
+
+ public static bool
IsSpanImplicitConversion([NotNullWhen(true)]MethodCallExpression? node) =>
+ node?.Method is { IsSpecialName: true, Name: "op_Implicit" }
+ && node.Method.DeclaringType is { IsGenericType: true }
+ && node.Method.DeclaringType.GetGenericTypeDefinition() ==
typeof(ReadOnlySpan<>);
Review Comment:
```suggestion
public static bool IsSpanImplicitConversion([NotNullWhen(true)]
MethodCallExpression? node) =>
node?.Method is { IsSpecialName: true, Name: "op_Implicit",
DeclaringType.IsGenericType: true }
&& node.Method.DeclaringType.GetGenericTypeDefinition() ==
typeof(ReadOnlySpan<>);
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]