Files
2026-08-27 10:56:38 -06:00

444 lines
15 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp;
internal static class LambdaUtilities
{
public static bool IsLambda(SyntaxNode node)
{
switch (node.Kind())
{
case SyntaxKind.AnonymousMethodExpression:
case SyntaxKind.SimpleLambdaExpression:
case SyntaxKind.ParenthesizedLambdaExpression:
case SyntaxKind.LetClause:
case SyntaxKind.JoinClause:
case SyntaxKind.WhereClause:
case SyntaxKind.AscendingOrdering:
case SyntaxKind.DescendingOrdering:
case SyntaxKind.GroupClause:
case SyntaxKind.LocalFunctionStatement:
return true;
case SyntaxKind.SelectClause:
{
SelectClauseSyntax selectClauseSyntax = (SelectClauseSyntax)(object)node;
return !IsReducedSelectOrGroupByClause(selectClauseSyntax, selectClauseSyntax.Expression);
}
case SyntaxKind.FromClause:
return !node.Parent.IsKind(SyntaxKind.QueryExpression);
default:
return false;
}
}
public static bool IsNotLambda(SyntaxNode node)
{
return !IsLambda(node);
}
public static SyntaxNode GetLambda(SyntaxNode lambdaBody)
{
SyntaxNode parent = lambdaBody.Parent;
if (parent.IsKind(SyntaxKind.ArrowExpressionClause))
{
parent = parent.Parent;
}
return parent;
}
internal static SyntaxNode? TryGetCorrespondingLambdaBody(SyntaxNode oldBody, SyntaxNode newLambda)
{
switch (newLambda.Kind())
{
case SyntaxKind.AnonymousMethodExpression:
case SyntaxKind.SimpleLambdaExpression:
case SyntaxKind.ParenthesizedLambdaExpression:
return (SyntaxNode?)(object)((AnonymousFunctionExpressionSyntax)(object)newLambda).Body;
case SyntaxKind.FromClause:
return (SyntaxNode?)(object)((FromClauseSyntax)(object)newLambda).Expression;
case SyntaxKind.LetClause:
return (SyntaxNode?)(object)((LetClauseSyntax)(object)newLambda).Expression;
case SyntaxKind.WhereClause:
return (SyntaxNode?)(object)((WhereClauseSyntax)(object)newLambda).Condition;
case SyntaxKind.AscendingOrdering:
case SyntaxKind.DescendingOrdering:
return (SyntaxNode?)(object)((OrderingSyntax)(object)newLambda).Expression;
case SyntaxKind.SelectClause:
{
SelectClauseSyntax selectClauseSyntax = (SelectClauseSyntax)(object)newLambda;
if (!IsReducedSelectOrGroupByClause(selectClauseSyntax, selectClauseSyntax.Expression))
{
return (SyntaxNode?)(object)selectClauseSyntax.Expression;
}
return null;
}
case SyntaxKind.JoinClause:
{
JoinClauseSyntax obj2 = (JoinClauseSyntax)(object)oldBody.Parent;
JoinClauseSyntax joinClauseSyntax = (JoinClauseSyntax)(object)newLambda;
if ((object)obj2.LeftExpression != oldBody)
{
return (SyntaxNode?)(object)joinClauseSyntax.RightExpression;
}
return (SyntaxNode?)(object)joinClauseSyntax.LeftExpression;
}
case SyntaxKind.GroupClause:
{
GroupClauseSyntax obj = (GroupClauseSyntax)(object)oldBody.Parent;
GroupClauseSyntax groupClauseSyntax = (GroupClauseSyntax)(object)newLambda;
if ((object)obj.GroupExpression != oldBody)
{
return (SyntaxNode?)(object)groupClauseSyntax.ByExpression;
}
if (!IsReducedSelectOrGroupByClause(groupClauseSyntax, groupClauseSyntax.GroupExpression))
{
return (SyntaxNode?)(object)groupClauseSyntax.GroupExpression;
}
return null;
}
case SyntaxKind.LocalFunctionStatement:
return GetLocalFunctionBody((LocalFunctionStatementSyntax)(object)newLambda);
default:
throw ExceptionUtilities.UnexpectedValue((object)newLambda.Kind());
}
}
public static SyntaxNode GetNestedFunctionBody(SyntaxNode nestedFunction)
{
if (!(nestedFunction is AnonymousFunctionExpressionSyntax anonymousFunctionExpressionSyntax))
{
if (nestedFunction is LocalFunctionStatementSyntax localFunctionStatementSyntax)
{
return (SyntaxNode)(((object)localFunctionStatementSyntax.Body) ?? ((object)localFunctionStatementSyntax.ExpressionBody.Expression));
}
throw ExceptionUtilities.UnexpectedValue((object)nestedFunction);
}
return (SyntaxNode)(object)anonymousFunctionExpressionSyntax.Body;
}
public static bool IsNotLambdaBody(SyntaxNode node)
{
return !IsLambdaBody(node);
}
public static bool IsLambdaBody(SyntaxNode node, bool allowReducedLambdas = false)
{
SyntaxNode val = ((node != null) ? node.Parent : null);
if (val == null)
{
return false;
}
switch (val.Kind())
{
case SyntaxKind.AnonymousMethodExpression:
case SyntaxKind.SimpleLambdaExpression:
case SyntaxKind.ParenthesizedLambdaExpression:
return (object)((AnonymousFunctionExpressionSyntax)(object)val).Body == node;
case SyntaxKind.LocalFunctionStatement:
return (object)((LocalFunctionStatementSyntax)(object)val).Body == node;
case SyntaxKind.ArrowExpressionClause:
{
ArrowExpressionClauseSyntax arrowExpressionClauseSyntax = (ArrowExpressionClauseSyntax)(object)val;
if ((object)arrowExpressionClauseSyntax.Expression == node)
{
return arrowExpressionClauseSyntax.Parent is LocalFunctionStatementSyntax;
}
return false;
}
case SyntaxKind.FromClause:
{
FromClauseSyntax fromClauseSyntax = (FromClauseSyntax)(object)val;
if ((object)fromClauseSyntax.Expression == node)
{
return fromClauseSyntax.Parent is QueryBodySyntax;
}
return false;
}
case SyntaxKind.JoinClause:
{
JoinClauseSyntax joinClauseSyntax = (JoinClauseSyntax)(object)val;
if ((object)joinClauseSyntax.LeftExpression != node)
{
return (object)joinClauseSyntax.RightExpression == node;
}
return true;
}
case SyntaxKind.LetClause:
return (object)((LetClauseSyntax)(object)val).Expression == node;
case SyntaxKind.WhereClause:
return (object)((WhereClauseSyntax)(object)val).Condition == node;
case SyntaxKind.AscendingOrdering:
case SyntaxKind.DescendingOrdering:
return (object)((OrderingSyntax)(object)val).Expression == node;
case SyntaxKind.SelectClause:
{
SelectClauseSyntax selectClauseSyntax = (SelectClauseSyntax)(object)val;
if ((object)selectClauseSyntax.Expression == node)
{
if (!allowReducedLambdas)
{
return !IsReducedSelectOrGroupByClause(selectClauseSyntax, selectClauseSyntax.Expression);
}
return true;
}
return false;
}
case SyntaxKind.GroupClause:
{
GroupClauseSyntax groupClauseSyntax = (GroupClauseSyntax)(object)val;
if ((object)groupClauseSyntax.GroupExpression != node || (!allowReducedLambdas && IsReducedSelectOrGroupByClause(groupClauseSyntax, groupClauseSyntax.GroupExpression)))
{
return (object)groupClauseSyntax.ByExpression == node;
}
return true;
}
default:
return false;
}
}
private static bool IsReducedSelectOrGroupByClause(SelectOrGroupClauseSyntax selectOrGroupClause, ExpressionSyntax selectOrGroupExpression)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
if (!((SyntaxNode?)(object)selectOrGroupExpression).IsKind(SyntaxKind.IdentifierName))
{
return false;
}
SyntaxToken identifier = ((IdentifierNameSyntax)selectOrGroupExpression).Identifier;
CSharpSyntaxNode parent = selectOrGroupClause.Parent.Parent;
QueryBodySyntax body;
SyntaxToken identifier2;
if (((SyntaxNode?)(object)parent).IsKind(SyntaxKind.QueryExpression))
{
QueryExpressionSyntax obj = (QueryExpressionSyntax)parent;
body = obj.Body;
identifier2 = obj.FromClause.Identifier;
}
else
{
QueryContinuationSyntax obj2 = (QueryContinuationSyntax)parent;
identifier2 = obj2.Identifier;
body = obj2.Body;
}
if (!SyntaxFactory.AreEquivalent(identifier2, identifier))
{
return false;
}
if (((SyntaxNode?)(object)selectOrGroupClause).IsKind(SyntaxKind.SelectClause) && body.Clauses.Count == 0)
{
return false;
}
Enumerator<QueryClauseSyntax> enumerator = body.Clauses.GetEnumerator();
while (enumerator.MoveNext())
{
QueryClauseSyntax current = enumerator.Current;
if (!((SyntaxNode?)(object)current).IsKind(SyntaxKind.WhereClause) && !((SyntaxNode?)(object)current).IsKind(SyntaxKind.OrderByClause))
{
return false;
}
}
return true;
}
public static bool IsLambdaBodyStatementOrExpression(SyntaxNode node)
{
return IsLambdaBody(node);
}
public static bool IsLambdaBodyStatementOrExpression(SyntaxNode node, out SyntaxNode lambdaBody)
{
lambdaBody = node;
return IsLambdaBody(node);
}
public static bool TryGetLambdaBodies(SyntaxNode node, [NotNullWhen(true)] out SyntaxNode? lambdaBody1, out SyntaxNode? lambdaBody2)
{
lambdaBody1 = null;
lambdaBody2 = null;
switch (node.Kind())
{
case SyntaxKind.AnonymousMethodExpression:
case SyntaxKind.SimpleLambdaExpression:
case SyntaxKind.ParenthesizedLambdaExpression:
lambdaBody1 = (SyntaxNode?)(object)((AnonymousFunctionExpressionSyntax)(object)node).Body;
return true;
case SyntaxKind.FromClause:
if (node.Parent.IsKind(SyntaxKind.QueryExpression))
{
return false;
}
lambdaBody1 = (SyntaxNode?)(object)((FromClauseSyntax)(object)node).Expression;
return true;
case SyntaxKind.JoinClause:
{
JoinClauseSyntax joinClauseSyntax = (JoinClauseSyntax)(object)node;
lambdaBody1 = (SyntaxNode?)(object)joinClauseSyntax.LeftExpression;
lambdaBody2 = (SyntaxNode?)(object)joinClauseSyntax.RightExpression;
return true;
}
case SyntaxKind.LetClause:
lambdaBody1 = (SyntaxNode?)(object)((LetClauseSyntax)(object)node).Expression;
return true;
case SyntaxKind.WhereClause:
lambdaBody1 = (SyntaxNode?)(object)((WhereClauseSyntax)(object)node).Condition;
return true;
case SyntaxKind.AscendingOrdering:
case SyntaxKind.DescendingOrdering:
lambdaBody1 = (SyntaxNode?)(object)((OrderingSyntax)(object)node).Expression;
return true;
case SyntaxKind.SelectClause:
{
SelectClauseSyntax selectClauseSyntax = (SelectClauseSyntax)(object)node;
if (IsReducedSelectOrGroupByClause(selectClauseSyntax, selectClauseSyntax.Expression))
{
return false;
}
lambdaBody1 = (SyntaxNode?)(object)selectClauseSyntax.Expression;
return true;
}
case SyntaxKind.GroupClause:
{
GroupClauseSyntax groupClauseSyntax = (GroupClauseSyntax)(object)node;
if (IsReducedSelectOrGroupByClause(groupClauseSyntax, groupClauseSyntax.GroupExpression))
{
lambdaBody1 = (SyntaxNode?)(object)groupClauseSyntax.ByExpression;
}
else
{
lambdaBody1 = (SyntaxNode?)(object)groupClauseSyntax.GroupExpression;
lambdaBody2 = (SyntaxNode?)(object)groupClauseSyntax.ByExpression;
}
return true;
}
case SyntaxKind.LocalFunctionStatement:
lambdaBody1 = GetLocalFunctionBody((LocalFunctionStatementSyntax)(object)node);
return lambdaBody1 != null;
default:
return false;
}
}
public static bool AreEquivalentIgnoringLambdaBodies(SyntaxNode oldNode, SyntaxNode newNode)
{
IEnumerable<SyntaxToken> enumerable = oldNode.DescendantTokens((Func<SyntaxNode, bool>)((SyntaxNode node) => node == oldNode || !IsLambdaBodyStatementOrExpression(node)), false);
IEnumerable<SyntaxToken> enumerable2 = newNode.DescendantTokens((Func<SyntaxNode, bool>)((SyntaxNode node) => node == newNode || !IsLambdaBodyStatementOrExpression(node)), false);
return EnumerableExtensions.SequenceEqual<SyntaxToken>(enumerable, enumerable2, (Func<SyntaxToken, SyntaxToken, bool>)SyntaxFactory.AreEquivalent);
}
internal static bool IsQueryPairLambda(SyntaxNode syntax)
{
if (!syntax.IsKind(SyntaxKind.GroupClause) && !syntax.IsKind(SyntaxKind.JoinClause))
{
return syntax.IsKind(SyntaxKind.FromClause);
}
return true;
}
internal static bool IsClosureScope(SyntaxNode node)
{
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
switch (node.Kind())
{
case SyntaxKind.Block:
case SyntaxKind.ForStatement:
case SyntaxKind.ForEachStatement:
case SyntaxKind.UsingStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CatchClause:
case SyntaxKind.CompilationUnit:
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.ArrowExpressionClause:
case SyntaxKind.ForEachVariableStatement:
return true;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.GotoCaseStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.YieldReturnStatement:
case SyntaxKind.ThrowStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.FixedStatement:
case SyntaxKind.LockStatement:
case SyntaxKind.IfStatement:
return true;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.StructDeclaration:
case SyntaxKind.RecordDeclaration:
case SyntaxKind.RecordStructDeclaration:
return true;
case SyntaxKind.AwaitExpression:
case SyntaxKind.SwitchExpression:
return true;
default:
if (node.Parent != null)
{
switch (node.Parent.Kind())
{
case SyntaxKind.EqualsValueClause:
return true;
case SyntaxKind.ForStatement:
if ((object)((ForStatementSyntax)(object)node.Parent).Incrementors.FirstOrDefault() == node)
{
return true;
}
break;
}
}
if (IsLambdaBody(node))
{
return true;
}
if (node is ExpressionSyntax && node.Parent != null && node.Parent.Parent == null)
{
return true;
}
return false;
}
}
internal static int GetDeclaratorPosition(SyntaxNode node)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
if (!(node is SwitchExpressionSyntax { SwitchKeyword: var switchKeyword }))
{
return node.SpanStart;
}
return ((SyntaxToken)(ref switchKeyword)).SpanStart;
}
private static SyntaxNode? GetLocalFunctionBody(LocalFunctionStatementSyntax localFunctionStatementSyntax)
{
object obj = localFunctionStatementSyntax.Body;
if (obj == null)
{
ArrowExpressionClauseSyntax? expressionBody = localFunctionStatementSyntax.ExpressionBody;
if (expressionBody == null)
{
return null;
}
obj = expressionBody.Expression;
}
return (SyntaxNode?)obj;
}
}