248 lines
7.2 KiB
C#
248 lines
7.2 KiB
C#
using System.Collections.Immutable;
|
|
using System.Threading;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
|
|
internal static class MethodSymbolExtensions
|
|
{
|
|
public static bool IsParams(this MethodSymbol method)
|
|
{
|
|
if (method.ParameterCount != 0)
|
|
{
|
|
return method.Parameters[method.ParameterCount - 1].IsParams;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal static bool IsSynthesizedLambda(this MethodSymbol method)
|
|
{
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000f: Invalid comparison between Unknown and I4
|
|
if (method.IsImplicitlyDeclared)
|
|
{
|
|
return (int)method.MethodKind == 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool IsRuntimeFinalizer(this MethodSymbol method, bool skipFirstMethodKindCheck = false)
|
|
{
|
|
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004a: Invalid comparison between Unknown and I4
|
|
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003a: Invalid comparison between Unknown and I4
|
|
if ((object)method == null || method.Name != "Finalize" || method.ParameterCount != 0 || method.Arity != 0 || !method.IsMetadataVirtual(ignoreInterfaceImplementationChanges: true))
|
|
{
|
|
return false;
|
|
}
|
|
while ((object)method != null)
|
|
{
|
|
if (!skipFirstMethodKindCheck && (int)method.MethodKind == 4)
|
|
{
|
|
return true;
|
|
}
|
|
if ((int)method.ContainingType.SpecialType == 1)
|
|
{
|
|
return true;
|
|
}
|
|
if (method.IsMetadataNewSlot(ignoreInterfaceImplementationChanges: true))
|
|
{
|
|
return false;
|
|
}
|
|
method = method.GetFirstRuntimeOverriddenMethodIgnoringNewSlot(out var _);
|
|
skipFirstMethodKindCheck = false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static MethodSymbol ConstructIfGeneric(this MethodSymbol method, ImmutableArray<TypeWithAnnotations> typeArguments)
|
|
{
|
|
if (!method.IsGenericMethod)
|
|
{
|
|
return method;
|
|
}
|
|
return method.Construct(typeArguments);
|
|
}
|
|
|
|
public static bool CanBeHiddenByMemberKind(this MethodSymbol hiddenMethod, SymbolKind hidingMemberKind)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Invalid comparison between Unknown and I4
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0033: Expected I4, but got Unknown
|
|
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0036: Invalid comparison between Unknown and I4
|
|
if ((int)hiddenMethod.MethodKind == 4)
|
|
{
|
|
return false;
|
|
}
|
|
switch (hidingMemberKind - 4)
|
|
{
|
|
default:
|
|
if ((int)hidingMemberKind != 15)
|
|
{
|
|
break;
|
|
}
|
|
goto case 0;
|
|
case 0:
|
|
case 5:
|
|
case 7:
|
|
return CanBeHiddenByMethodPropertyOrType(hiddenMethod);
|
|
case 1:
|
|
case 2:
|
|
return true;
|
|
case 3:
|
|
case 4:
|
|
case 6:
|
|
break;
|
|
}
|
|
throw ExceptionUtilities.UnexpectedValue((object)hidingMemberKind);
|
|
}
|
|
|
|
private static bool CanBeHiddenByMethodPropertyOrType(MethodSymbol method)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0047: Expected I4, but got Unknown
|
|
MethodKind methodKind = method.MethodKind;
|
|
switch (methodKind - 1)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 3:
|
|
case 8:
|
|
case 13:
|
|
return false;
|
|
case 4:
|
|
case 6:
|
|
case 10:
|
|
case 11:
|
|
return method.IsIndexedPropertyAccessor();
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public static bool IsAsyncReturningVoid(this MethodSymbol method)
|
|
{
|
|
if (method.IsAsync)
|
|
{
|
|
return method.ReturnsVoid;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool IsAsyncEffectivelyReturningTask(this MethodSymbol method, CSharpCompilation compilation)
|
|
{
|
|
if (method.IsAsync && method.ReturnType is NamedTypeSymbol { Arity: 0 })
|
|
{
|
|
if (!method.HasAsyncMethodBuilderAttribute(out object _))
|
|
{
|
|
return method.ReturnType.IsNonGenericTaskType(compilation);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool IsAsyncEffectivelyReturningGenericTask(this MethodSymbol method, CSharpCompilation compilation)
|
|
{
|
|
if (method.IsAsync && method.ReturnType is NamedTypeSymbol { Arity: 1 })
|
|
{
|
|
if (!method.HasAsyncMethodBuilderAttribute(out object _))
|
|
{
|
|
return method.ReturnType.IsGenericTaskType(compilation);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool IsAsyncReturningIAsyncEnumerable(this MethodSymbol method, CSharpCompilation compilation)
|
|
{
|
|
if (method.IsAsync)
|
|
{
|
|
return method.ReturnType.IsIAsyncEnumerableType(compilation);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool IsAsyncReturningIAsyncEnumerator(this MethodSymbol method, CSharpCompilation compilation)
|
|
{
|
|
if (method.IsAsync)
|
|
{
|
|
return method.ReturnType.IsIAsyncEnumeratorType(compilation);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal static CSharpSyntaxNode ExtractReturnTypeSyntax(this MethodSymbol method)
|
|
{
|
|
if (method is SynthesizedSimpleProgramEntryPointSymbol synthesizedSimpleProgramEntryPointSymbol)
|
|
{
|
|
return (CSharpSyntaxNode)(object)synthesizedSimpleProgramEntryPointSymbol.ReturnTypeSyntax;
|
|
}
|
|
method = method.PartialDefinitionPart ?? method;
|
|
ImmutableArray<SyntaxReference>.Enumerator enumerator = method.DeclaringSyntaxReferences.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
SyntaxNode syntax = enumerator.Current.GetSyntax(default(CancellationToken));
|
|
if (syntax is MethodDeclarationSyntax methodDeclarationSyntax)
|
|
{
|
|
return methodDeclarationSyntax.ReturnType;
|
|
}
|
|
if (syntax is LocalFunctionStatementSyntax localFunctionStatementSyntax)
|
|
{
|
|
return localFunctionStatementSyntax.ReturnType;
|
|
}
|
|
}
|
|
return (CSharpSyntaxNode)(object)CSharpSyntaxTree.Dummy.GetRoot(default(CancellationToken));
|
|
}
|
|
|
|
internal static bool IsValidUnscopedRefAttributeTarget(this MethodSymbol method)
|
|
{
|
|
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002a: Invalid comparison between Unknown and I4
|
|
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0031: Invalid comparison between Unknown and I4
|
|
bool flag = !method.IsStatic && (method.ContainingType?.IsStructType() ?? false);
|
|
if (flag)
|
|
{
|
|
MethodKind methodKind = method.MethodKind;
|
|
bool flag2 = (((int)methodKind == 8 || methodKind - 10 <= 2) ? true : false);
|
|
flag = flag2;
|
|
}
|
|
if (flag)
|
|
{
|
|
return !method.IsInitOnly;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal static bool HasUnscopedRefAttributeOnMethodOrProperty(this MethodSymbol? method)
|
|
{
|
|
if ((object)method == null)
|
|
{
|
|
return false;
|
|
}
|
|
if (!method.HasUnscopedRefAttribute)
|
|
{
|
|
if (method.AssociatedSymbol is PropertySymbol propertySymbol)
|
|
{
|
|
return propertySymbol.HasUnscopedRefAttribute;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|