206 lines
7.3 KiB
C#
206 lines
7.3 KiB
C#
using System.Collections.Immutable;
|
|
using System.Threading;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
|
|
internal abstract class SourceOrdinaryMethodOrUserDefinedOperatorSymbol : SourceMemberMethodSymbol
|
|
{
|
|
private ImmutableArray<MethodSymbol> _lazyExplicitInterfaceImplementations;
|
|
|
|
private ImmutableArray<CustomModifier> _lazyRefCustomModifiers;
|
|
|
|
private ImmutableArray<ParameterSymbol> _lazyParameters;
|
|
|
|
private TypeWithAnnotations _lazyReturnType;
|
|
|
|
protected abstract Location ReturnTypeLocation { get; }
|
|
|
|
public sealed override bool ReturnsVoid
|
|
{
|
|
get
|
|
{
|
|
LazyMethodChecks();
|
|
return base.ReturnsVoid;
|
|
}
|
|
}
|
|
|
|
protected abstract TypeSymbol? ExplicitInterfaceType { get; }
|
|
|
|
internal sealed override int ParameterCount
|
|
{
|
|
get
|
|
{
|
|
if (!_lazyParameters.IsDefault)
|
|
{
|
|
return _lazyParameters.Length;
|
|
}
|
|
return GetParameterCountFromSyntax();
|
|
}
|
|
}
|
|
|
|
public sealed override ImmutableArray<ParameterSymbol> Parameters
|
|
{
|
|
get
|
|
{
|
|
LazyMethodChecks();
|
|
return _lazyParameters;
|
|
}
|
|
}
|
|
|
|
public sealed override TypeWithAnnotations ReturnTypeWithAnnotations
|
|
{
|
|
get
|
|
{
|
|
LazyMethodChecks();
|
|
return _lazyReturnType;
|
|
}
|
|
}
|
|
|
|
internal sealed override bool IsExplicitInterfaceImplementation => (int)MethodKind == 8;
|
|
|
|
public sealed override ImmutableArray<MethodSymbol> ExplicitInterfaceImplementations
|
|
{
|
|
get
|
|
{
|
|
LazyMethodChecks();
|
|
return _lazyExplicitInterfaceImplementations;
|
|
}
|
|
}
|
|
|
|
public sealed override ImmutableArray<CustomModifier> RefCustomModifiers
|
|
{
|
|
get
|
|
{
|
|
LazyMethodChecks();
|
|
return _lazyRefCustomModifiers;
|
|
}
|
|
}
|
|
|
|
protected SourceOrdinaryMethodOrUserDefinedOperatorSymbol(NamedTypeSymbol containingType, SyntaxReference syntaxReferenceOpt, Location location, bool isIterator, (DeclarationModifiers declarationModifiers, Flags flags) modifiersAndFlags)
|
|
: base(containingType, syntaxReferenceOpt, location, isIterator, modifiersAndFlags)
|
|
{
|
|
}
|
|
|
|
protected MethodSymbol? MethodChecks(TypeWithAnnotations returnType, ImmutableArray<ParameterSymbol> parameters, BindingDiagnosticBag diagnostics)
|
|
{
|
|
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0097: Invalid comparison between Unknown and I4
|
|
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f1: Invalid comparison between Unknown and I4
|
|
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0139: Invalid comparison between Unknown and I4
|
|
_lazyReturnType = returnType;
|
|
_lazyParameters = parameters;
|
|
SetReturnsVoid(_lazyReturnType.IsVoidType());
|
|
CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics);
|
|
CheckFileTypeUsage(_lazyReturnType, _lazyParameters, diagnostics);
|
|
if (Name == "Finalize" && ParameterCount == 0 && Arity == 0 && ReturnsVoid)
|
|
{
|
|
diagnostics.Add(ErrorCode.WRN_FinalizeMethod, _location);
|
|
}
|
|
ExtensionMethodChecks(diagnostics);
|
|
if (base.IsPartial)
|
|
{
|
|
if ((int)MethodKind == 8)
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_PartialMethodNotExplicit, _location);
|
|
}
|
|
if (!ContainingType.IsPartial())
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_PartialMethodOnlyInPartialClass, _location);
|
|
}
|
|
}
|
|
if (!base.IsPartial)
|
|
{
|
|
LazyAsyncMethodChecks(CancellationToken.None);
|
|
}
|
|
_lazyRefCustomModifiers = ImmutableArray<CustomModifier>.Empty;
|
|
MethodSymbol methodSymbol = null;
|
|
if ((int)MethodKind != 8)
|
|
{
|
|
_lazyExplicitInterfaceImplementations = ImmutableArray<MethodSymbol>.Empty;
|
|
if (IsOverride)
|
|
{
|
|
methodSymbol = base.OverriddenMethod;
|
|
if ((object)methodSymbol != null)
|
|
{
|
|
CustomModifierUtils.CopyMethodCustomModifiers(methodSymbol, this, out _lazyReturnType, out _lazyRefCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: true);
|
|
}
|
|
}
|
|
else if ((int)RefKind == 3)
|
|
{
|
|
NamedTypeSymbol wellKnownType = Binder.GetWellKnownType(DeclaringCompilation, (WellKnownType)273, diagnostics, ReturnTypeLocation);
|
|
_lazyRefCustomModifiers = ImmutableArray.Create<CustomModifier>(CSharpCustomModifier.CreateRequired(wellKnownType));
|
|
}
|
|
}
|
|
else if ((object)ExplicitInterfaceType != null)
|
|
{
|
|
methodSymbol = FindExplicitlyImplementedMethod(diagnostics);
|
|
if ((object)methodSymbol != null)
|
|
{
|
|
_lazyExplicitInterfaceImplementations = ImmutableArray.Create(methodSymbol);
|
|
CustomModifierUtils.CopyMethodCustomModifiers(methodSymbol, this, out _lazyReturnType, out _lazyRefCustomModifiers, out _lazyParameters, alsoCopyParamsModifier: false);
|
|
this.FindExplicitlyImplementedMemberVerification(methodSymbol, diagnostics);
|
|
TypeSymbol.CheckModifierMismatchOnImplementingMember(ContainingType, this, methodSymbol, isExplicit: true, diagnostics);
|
|
}
|
|
else
|
|
{
|
|
_lazyExplicitInterfaceImplementations = ImmutableArray<MethodSymbol>.Empty;
|
|
}
|
|
}
|
|
return methodSymbol;
|
|
}
|
|
|
|
protected abstract void ExtensionMethodChecks(BindingDiagnosticBag diagnostics);
|
|
|
|
protected abstract MethodSymbol? FindExplicitlyImplementedMethod(BindingDiagnosticBag diagnostics);
|
|
|
|
protected abstract int GetParameterCountFromSyntax();
|
|
|
|
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, BindingDiagnosticBag diagnostics)
|
|
{
|
|
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0082: Invalid comparison between Unknown and I4
|
|
base.AfterAddingTypeMembersChecks(conversions, diagnostics);
|
|
Location returnTypeLocation = null;
|
|
CSharpCompilation declaringCompilation = DeclaringCompilation;
|
|
CheckConstraintsForExplicitInterfaceType(conversions, diagnostics);
|
|
base.ReturnType.CheckAllConstraints(declaringCompilation, conversions, GetFirstLocation(), diagnostics);
|
|
ImmutableArray<ParameterSymbol>.Enumerator enumerator = Parameters.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
ParameterSymbol current = enumerator.Current;
|
|
current.Type.CheckAllConstraints(declaringCompilation, conversions, current.GetFirstLocation(), diagnostics);
|
|
}
|
|
PartialMethodChecks(diagnostics);
|
|
if ((int)RefKind == 3)
|
|
{
|
|
declaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, getReturnTypeLocation(), modifyCompilation: true);
|
|
}
|
|
ParameterHelpers.EnsureRefKindAttributesExist(declaringCompilation, Parameters, diagnostics, modifyCompilation: true);
|
|
if (declaringCompilation.ShouldEmitNativeIntegerAttributes(base.ReturnType))
|
|
{
|
|
declaringCompilation.EnsureNativeIntegerAttributeExists(diagnostics, getReturnTypeLocation(), modifyCompilation: true);
|
|
}
|
|
ParameterHelpers.EnsureNativeIntegerAttributeExists(declaringCompilation, Parameters, diagnostics, modifyCompilation: true);
|
|
ParameterHelpers.EnsureScopedRefAttributeExists(declaringCompilation, Parameters, diagnostics, modifyCompilation: true);
|
|
if (declaringCompilation.ShouldEmitNullableAttributes(this) && ReturnTypeWithAnnotations.NeedsNullableAttribute())
|
|
{
|
|
declaringCompilation.EnsureNullableAttributeExists(diagnostics, getReturnTypeLocation(), modifyCompilation: true);
|
|
}
|
|
ParameterHelpers.EnsureNullableAttributeExists(declaringCompilation, this, Parameters, diagnostics, modifyCompilation: true);
|
|
Location getReturnTypeLocation()
|
|
{
|
|
if (returnTypeLocation == null)
|
|
{
|
|
returnTypeLocation = ReturnTypeLocation;
|
|
}
|
|
return returnTypeLocation;
|
|
}
|
|
}
|
|
|
|
protected abstract void CheckConstraintsForExplicitInterfaceType(ConversionsBase conversions, BindingDiagnosticBag diagnostics);
|
|
|
|
protected abstract void PartialMethodChecks(BindingDiagnosticBag diagnostics);
|
|
}
|