Skip to content

Commit

Permalink
Bring in LinqToCSharpTranslator (#31294)
Browse files Browse the repository at this point in the history
  • Loading branch information
roji authored Jul 18, 2023
1 parent c218c1a commit a40f93b
Show file tree
Hide file tree
Showing 5 changed files with 4,385 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/EFCore.Design/EFCore.Design.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

<ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(MicrosoftCodeAnalysisVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftExtensionsDependencyModelVersion)" />
<PackageReference Include="Microsoft.Extensions.HostFactoryResolver.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsHostFactoryResolverSourcesVersion)" />
<PackageReference Include="Mono.TextTemplating" Version="2.2.1" />
Expand Down
104 changes: 104 additions & 0 deletions src/EFCore.Design/Extensions/Internal/TypeExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

namespace Microsoft.EntityFrameworkCore.Query.Internal;

internal static class TypeExtensions
{
internal static TypeSyntax GetTypeSyntax(this Type type)
{
// TODO: Qualification...
if (type.IsGenericType)
{
return GenericName(
Identifier(type.Name.Substring(0, type.Name.IndexOf('`'))),
TypeArgumentList(SeparatedList(type.GenericTypeArguments.Select(GetTypeSyntax))));
}

if (type == typeof(string))
{
return PredefinedType(Token(SyntaxKind.StringKeyword));
}

if (type == typeof(bool))
{
return PredefinedType(Token(SyntaxKind.BoolKeyword));
}

if (type == typeof(byte))
{
return PredefinedType(Token(SyntaxKind.ByteKeyword));
}

if (type == typeof(sbyte))
{
return PredefinedType(Token(SyntaxKind.SByteKeyword));
}

if (type == typeof(int))
{
return PredefinedType(Token(SyntaxKind.IntKeyword));
}

if (type == typeof(uint))
{
return PredefinedType(Token(SyntaxKind.UIntKeyword));
}

if (type == typeof(short))
{
return PredefinedType(Token(SyntaxKind.ShortKeyword));
}

if (type == typeof(ushort))
{
return PredefinedType(Token(SyntaxKind.UShortKeyword));
}

if (type == typeof(long))
{
return PredefinedType(Token(SyntaxKind.LongKeyword));
}

if (type == typeof(ulong))
{
return PredefinedType(Token(SyntaxKind.ULongKeyword));
}

if (type == typeof(float))
{
return PredefinedType(Token(SyntaxKind.FloatKeyword));
}

if (type == typeof(double))
{
return PredefinedType(Token(SyntaxKind.DoubleKeyword));
}

if (type == typeof(decimal))
{
return PredefinedType(Token(SyntaxKind.DecimalKeyword));
}

if (type == typeof(char))
{
return PredefinedType(Token(SyntaxKind.CharKeyword));
}

if (type == typeof(object))
{
return PredefinedType(Token(SyntaxKind.ObjectKeyword));
}

if (type == typeof(void))
{
return PredefinedType(Token(SyntaxKind.VoidKeyword));
}

return IdentifierName(type.Name);
}
}
58 changes: 58 additions & 0 deletions src/EFCore.Design/Query/Internal/ILinqToCSharpTranslator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

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

namespace Microsoft.EntityFrameworkCore.Query.Internal;

/// <summary>
/// Translates a LINQ expression tree to a Roslyn syntax tree.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public interface ILinqToCSharpTranslator
{
/// <summary>
/// Translates a node representing a statement into a Roslyn syntax tree.
/// </summary>
/// <param name="node">The node to be translated.</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>
/// 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.
/// </remarks>
SyntaxNode TranslateStatement(Expression node, 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="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>
/// 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.
/// </remarks>
SyntaxNode TranslateExpression(Expression node, ISet<string> collectedNamespaces);

/// <summary>
/// Returns the captured variables detected in the last translation.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
IReadOnlySet<ParameterExpression> CapturedVariables { get; }
}
Loading

0 comments on commit a40f93b

Please sign in to comment.