309 lines
10 KiB
C#
309 lines
10 KiB
C#
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal static class SyntaxNodeExtensions
|
|
{
|
|
public static TNode WithAnnotations<TNode>(this TNode node, params SyntaxAnnotation[] annotations) where TNode : CSharpSyntaxNode
|
|
{
|
|
return (TNode)(CSharpSyntaxNode)(object)((SyntaxNode)node).Green.SetAnnotations(annotations).CreateRed();
|
|
}
|
|
|
|
public static bool IsAnonymousFunction(this SyntaxNode syntax)
|
|
{
|
|
SyntaxKind syntaxKind = syntax.Kind();
|
|
if (syntaxKind - 8641 <= (SyntaxKind)2)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool IsQuery(this SyntaxNode syntax)
|
|
{
|
|
switch (syntax.Kind())
|
|
{
|
|
case SyntaxKind.QueryExpression:
|
|
case SyntaxKind.FromClause:
|
|
case SyntaxKind.LetClause:
|
|
case SyntaxKind.JoinClause:
|
|
case SyntaxKind.JoinIntoClause:
|
|
case SyntaxKind.WhereClause:
|
|
case SyntaxKind.OrderByClause:
|
|
case SyntaxKind.SelectClause:
|
|
case SyntaxKind.GroupClause:
|
|
case SyntaxKind.QueryContinuation:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
internal static bool MayBeNameofOperator(this InvocationExpressionSyntax node)
|
|
{
|
|
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004f: 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_0069: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
|
|
if (node.Expression.Kind() == SyntaxKind.IdentifierName && ((IdentifierNameSyntax)node.Expression).Identifier.ContextualKind() == SyntaxKind.NameOfKeyword && node.ArgumentList.Arguments.Count == 1)
|
|
{
|
|
ArgumentSyntax argumentSyntax = node.ArgumentList.Arguments[0];
|
|
if (argumentSyntax.NameColon == null && argumentSyntax.RefOrOutKeyword == default(SyntaxToken))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal static bool CanHaveAssociatedLocalBinder(this SyntaxNode syntax)
|
|
{
|
|
switch (syntax.Kind())
|
|
{
|
|
case SyntaxKind.InvocationExpression:
|
|
if (((InvocationExpressionSyntax)(object)syntax).MayBeNameofOperator())
|
|
{
|
|
return true;
|
|
}
|
|
break;
|
|
case SyntaxKind.ArgumentList:
|
|
case SyntaxKind.AnonymousMethodExpression:
|
|
case SyntaxKind.SimpleLambdaExpression:
|
|
case SyntaxKind.ParenthesizedLambdaExpression:
|
|
case SyntaxKind.CheckedExpression:
|
|
case SyntaxKind.UncheckedExpression:
|
|
case SyntaxKind.EqualsValueClause:
|
|
case SyntaxKind.SwitchSection:
|
|
case SyntaxKind.CatchClause:
|
|
case SyntaxKind.CatchFilterClause:
|
|
case SyntaxKind.Attribute:
|
|
case SyntaxKind.ConstructorDeclaration:
|
|
case SyntaxKind.BaseConstructorInitializer:
|
|
case SyntaxKind.ThisConstructorInitializer:
|
|
case SyntaxKind.ArrowExpressionClause:
|
|
case SyntaxKind.SwitchExpression:
|
|
case SyntaxKind.SwitchExpressionArm:
|
|
case SyntaxKind.PrimaryConstructorBaseType:
|
|
return true;
|
|
case SyntaxKind.RecordStructDeclaration:
|
|
return false;
|
|
}
|
|
if (!(syntax is StatementSyntax))
|
|
{
|
|
return (syntax as ExpressionSyntax).IsValidScopeDesignator();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
internal static bool IsValidScopeDesignator(this ExpressionSyntax? expression)
|
|
{
|
|
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
|
|
CSharpSyntaxNode cSharpSyntaxNode = expression?.Parent;
|
|
switch (cSharpSyntaxNode?.Kind())
|
|
{
|
|
case SyntaxKind.SimpleLambdaExpression:
|
|
case SyntaxKind.ParenthesizedLambdaExpression:
|
|
return ((LambdaExpressionSyntax)cSharpSyntaxNode).Body == expression;
|
|
case SyntaxKind.SwitchStatement:
|
|
return ((SwitchStatementSyntax)cSharpSyntaxNode).Expression == expression;
|
|
case SyntaxKind.ForStatement:
|
|
{
|
|
ForStatementSyntax forStatementSyntax = (ForStatementSyntax)cSharpSyntaxNode;
|
|
if (forStatementSyntax.Condition != expression)
|
|
{
|
|
return forStatementSyntax.Incrementors.FirstOrDefault() == expression;
|
|
}
|
|
return true;
|
|
}
|
|
case SyntaxKind.ForEachStatement:
|
|
case SyntaxKind.ForEachVariableStatement:
|
|
return ((CommonForEachStatementSyntax)cSharpSyntaxNode).Expression == expression;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
internal static bool IsLegalCSharp73SpanStackAllocPosition(this SyntaxNode node)
|
|
{
|
|
if (node.Parent.IsKind(SyntaxKind.CastExpression))
|
|
{
|
|
node = node.Parent;
|
|
}
|
|
while (node.Parent.IsKind(SyntaxKind.ConditionalExpression))
|
|
{
|
|
node = node.Parent;
|
|
}
|
|
SyntaxNode parent = node.Parent;
|
|
if (parent == null)
|
|
{
|
|
return false;
|
|
}
|
|
switch (parent.Kind())
|
|
{
|
|
case SyntaxKind.EqualsValueClause:
|
|
{
|
|
SyntaxNode parent2 = parent.Parent;
|
|
if (parent2.IsKind(SyntaxKind.VariableDeclarator))
|
|
{
|
|
return parent2.Parent.IsKind(SyntaxKind.VariableDeclaration);
|
|
}
|
|
return false;
|
|
}
|
|
case SyntaxKind.SimpleAssignmentExpression:
|
|
return parent.Parent.IsKind(SyntaxKind.ExpressionStatement);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
internal static CSharpSyntaxNode AnonymousFunctionBody(this SyntaxNode lambda)
|
|
{
|
|
return ((AnonymousFunctionExpressionSyntax)(object)lambda).Body;
|
|
}
|
|
|
|
internal static SyntaxToken ExtractAnonymousTypeMemberName(this ExpressionSyntax input)
|
|
{
|
|
//IL_0027: 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_0069: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
|
|
while (true)
|
|
{
|
|
switch (input.Kind())
|
|
{
|
|
case SyntaxKind.IdentifierName:
|
|
return ((IdentifierNameSyntax)input).Identifier;
|
|
case SyntaxKind.SimpleMemberAccessExpression:
|
|
input = ((MemberAccessExpressionSyntax)input).Name;
|
|
break;
|
|
case SyntaxKind.ConditionalAccessExpression:
|
|
input = ((ConditionalAccessExpressionSyntax)input).WhenNotNull;
|
|
if (input.Kind() == SyntaxKind.MemberBindingExpression)
|
|
{
|
|
return ((MemberBindingExpressionSyntax)input).Name.Identifier;
|
|
}
|
|
break;
|
|
default:
|
|
return default(SyntaxToken);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static RefKind GetRefKindInLocalOrReturn(this TypeSyntax syntax, BindingDiagnosticBag diagnostics)
|
|
{
|
|
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
|
|
syntax.SkipRefInLocalOrReturn(diagnostics, out var refKind);
|
|
return refKind;
|
|
}
|
|
|
|
internal static TypeSyntax SkipRef(this TypeSyntax syntax)
|
|
{
|
|
RefKind refKind;
|
|
return SkipRefWorker(syntax, null, out refKind);
|
|
}
|
|
|
|
internal static TypeSyntax SkipRefInField(this TypeSyntax syntax, out RefKind refKind)
|
|
{
|
|
return SkipRefWorker(syntax, null, out refKind);
|
|
}
|
|
|
|
internal static TypeSyntax SkipRefInLocalOrReturn(this TypeSyntax syntax, BindingDiagnosticBag? diagnostics, out RefKind refKind)
|
|
{
|
|
return SkipRefWorker(syntax, diagnostics, out refKind);
|
|
}
|
|
|
|
private static TypeSyntax SkipRefWorker(TypeSyntax syntax, BindingDiagnosticBag? diagnostics, out RefKind refKind)
|
|
{
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
|
|
if (syntax.Kind() == SyntaxKind.RefType)
|
|
{
|
|
RefTypeSyntax refTypeSyntax = (RefTypeSyntax)syntax;
|
|
refKind = (RefKind)((refTypeSyntax.ReadOnlyKeyword.Kind() != SyntaxKind.ReadOnlyKeyword) ? 1 : 3);
|
|
if (diagnostics != null)
|
|
{
|
|
MessageID.IDS_FeatureRefLocalsReturns.CheckFeatureAvailability(diagnostics, refTypeSyntax.RefKeyword);
|
|
if (refTypeSyntax.ReadOnlyKeyword != default(SyntaxToken))
|
|
{
|
|
MessageID.IDS_FeatureReadOnlyReferences.CheckFeatureAvailability(diagnostics, refTypeSyntax.ReadOnlyKeyword);
|
|
}
|
|
}
|
|
return refTypeSyntax.Type;
|
|
}
|
|
refKind = (RefKind)0;
|
|
return syntax;
|
|
}
|
|
|
|
internal static TypeSyntax SkipScoped(this TypeSyntax syntax, out bool isScoped)
|
|
{
|
|
if (syntax is ScopedTypeSyntax scopedTypeSyntax)
|
|
{
|
|
isScoped = true;
|
|
return scopedTypeSyntax.Type;
|
|
}
|
|
isScoped = false;
|
|
return syntax;
|
|
}
|
|
|
|
internal static SyntaxNode ModifyingScopedOrRefTypeOrSelf(this SyntaxNode syntax)
|
|
{
|
|
SyntaxNode parent = syntax.Parent;
|
|
if (parent is RefTypeSyntax refTypeSyntax && (object)refTypeSyntax.Type == syntax)
|
|
{
|
|
syntax = (SyntaxNode)(object)refTypeSyntax;
|
|
parent = parent.Parent;
|
|
}
|
|
if (parent is ScopedTypeSyntax scopedTypeSyntax && (object)scopedTypeSyntax.Type == syntax)
|
|
{
|
|
return (SyntaxNode)(object)scopedTypeSyntax;
|
|
}
|
|
return syntax;
|
|
}
|
|
|
|
internal static ExpressionSyntax? CheckAndUnwrapRefExpression(this ExpressionSyntax? syntax, BindingDiagnosticBag diagnostics, out RefKind refKind)
|
|
{
|
|
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
|
|
if (syntax is RefExpressionSyntax refExpressionSyntax)
|
|
{
|
|
ExpressionSyntax expression = refExpressionSyntax.Expression;
|
|
MessageID.IDS_FeatureRefLocalsReturns.CheckFeatureAvailability(diagnostics, refExpressionSyntax.RefKeyword);
|
|
refKind = (RefKind)1;
|
|
expression.CheckDeconstructionCompatibleArgument(diagnostics);
|
|
return expression;
|
|
}
|
|
refKind = (RefKind)0;
|
|
return syntax;
|
|
}
|
|
|
|
internal static void CheckDeconstructionCompatibleArgument(this ExpressionSyntax expression, BindingDiagnosticBag diagnostics)
|
|
{
|
|
if (IsDeconstructionCompatibleArgument(expression))
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_VarInvocationLvalueReserved, expression.GetLocation());
|
|
}
|
|
}
|
|
|
|
private static bool IsDeconstructionCompatibleArgument(ExpressionSyntax expression)
|
|
{
|
|
if (expression.Kind() == SyntaxKind.InvocationExpression)
|
|
{
|
|
ExpressionSyntax expression2 = ((InvocationExpressionSyntax)expression).Expression;
|
|
if (expression2.Kind() == SyntaxKind.IdentifierName)
|
|
{
|
|
return ((IdentifierNameSyntax)expression2).IsVar;
|
|
}
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
}
|