Skip to content

Commit

Permalink
Generate change-tracking delegates in the compiled model.
Browse files Browse the repository at this point in the history
Part of #29761
  • Loading branch information
AndriySvyryd committed Jan 9, 2024
1 parent b5b1abf commit 78d8e80
Show file tree
Hide file tree
Showing 137 changed files with 46,784 additions and 1,510 deletions.
41 changes: 37 additions & 4 deletions src/EFCore.Design/Design/Internal/CSharpHelper.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections;
using System.Globalization;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text;
Expand Down Expand Up @@ -1553,16 +1554,48 @@ private string ToSourceCode(SyntaxNode node)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual string Statement(Expression node, ISet<string> collectedNamespaces)
=> ToSourceCode(_translator.TranslateStatement(node, collectedNamespaces));
=> ToSourceCode(_translator.TranslateStatement(node, null, null, collectedNamespaces));

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual string Expression(Expression node, ISet<string> collectedNamespaces)
=> ToSourceCode(_translator.TranslateExpression(node, collectedNamespaces));
public virtual string Expression(
Expression node,
Dictionary<object, string>? knownInstances,
Dictionary<(MemberInfo, bool), string>? replacementMethods,
ISet<string> collectedNamespaces)
{
Dictionary<object, ExpressionSyntax>? knownInstanceExpressions = null;
if (knownInstances != null)
{
knownInstanceExpressions = new();

foreach (var instancePair in knownInstances)
{
knownInstanceExpressions[instancePair.Key] = SyntaxFactory.IdentifierName(instancePair.Value);
}
}

Dictionary<(MemberInfo, bool), ExpressionSyntax>? replacementMethodExpressions = null;
if (replacementMethods != null)
{
replacementMethodExpressions = new();

foreach (var methodPair in replacementMethods)
{
replacementMethodExpressions[methodPair.Key] = SyntaxFactory.IdentifierName(methodPair.Value);
}
}

return ToSourceCode(_translator.TranslateExpression(
node,
knownInstanceExpressions,
replacementMethodExpressions,
collectedNamespaces));
}

private static bool IsIdentifierStartCharacter(char ch)
{
Expand Down
17 changes: 15 additions & 2 deletions src/EFCore.Design/Query/Internal/ILinqToCSharpSyntaxTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Microsoft.EntityFrameworkCore.Query.Internal;

Expand All @@ -20,6 +21,8 @@ public interface ILinqToCSharpSyntaxTranslator
/// Translates a node representing a statement into a Roslyn syntax tree.
/// </summary>
/// <param name="node">The node to be translated.</param>
/// <param name="knownInstances">Collection of translations for statically known instances.</param>
/// <param name="replacementMethods">Collection of translations for non-public member accesses.</param>
/// <param name="collectedNamespaces">Any namespaces required by the translated code will be added to this set.</param>
/// <returns>A Roslyn syntax tree representation of <paramref name="node" />.</returns>
/// <remarks>
Expand All @@ -28,12 +31,18 @@ public interface ILinqToCSharpSyntaxTranslator
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </remarks>
SyntaxNode TranslateStatement(Expression node, ISet<string> collectedNamespaces);
SyntaxNode TranslateStatement(
Expression node,
Dictionary<object, ExpressionSyntax>? knownInstances,
Dictionary<(MemberInfo, bool), ExpressionSyntax>? replacementMethods,
ISet<string> collectedNamespaces);

/// <summary>
/// Translates a node representing an expression into a Roslyn syntax tree.
/// </summary>
/// <param name="node">The node to be translated.</param>
/// <param name="knownInstances">Collection of translations for statically known instances.</param>
/// <param name="replacementMethods">Collection of translations for non-public member accesses.</param>
/// <param name="collectedNamespaces">Any namespaces required by the translated code will be added to this set.</param>
/// <returns>A Roslyn syntax tree representation of <paramref name="node" />.</returns>
/// <remarks>
Expand All @@ -42,7 +51,11 @@ public interface ILinqToCSharpSyntaxTranslator
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </remarks>
SyntaxNode TranslateExpression(Expression node, ISet<string> collectedNamespaces);
SyntaxNode TranslateExpression(
Expression node,
Dictionary<object, ExpressionSyntax>? knownInstances,
Dictionary<(MemberInfo, bool), ExpressionSyntax>? replacementMethods,
ISet<string> collectedNamespaces);

/// <summary>
/// Returns the captured variables detected in the last translation.
Expand Down
Loading

0 comments on commit 78d8e80

Please sign in to comment.