using System.Reflection.Metadata; using System.Collections.Generic; using System.Linq; namespace Semmle.Extraction.CIL.Entities { /// /// This is a late-bound reference to a method. /// internal sealed class MemberReferenceMethod : Method { private readonly MemberReferenceHandle handle; private readonly MemberReference mr; private readonly Type declaringType; private readonly IGenericContext parent; private readonly Method? sourceDeclaration; public MemberReferenceMethod(IGenericContext gc, MemberReferenceHandle handle) : base(gc) { this.handle = handle; this.gc = gc; mr = Context.MdReader.GetMemberReference(handle); signature = mr.DecodeMethodSignature(new SignatureDecoder(), gc); parent = (IGenericContext)Context.CreateGeneric(gc, mr.Parent); var declType = parent is Method parentMethod ? parentMethod.DeclaringType : parent as Type; if (declType is null) throw new InternalError("Parent context of method is not a type"); declaringType = declType; nameLabel = Context.GetString(mr.Name); var typeSourceDeclaration = declaringType.SourceDeclaration; sourceDeclaration = typeSourceDeclaration == declaringType ? (Method)this : typeSourceDeclaration.LookupMethod(mr.Name, mr.Signature); } private readonly string nameLabel; public override string NameLabel => nameLabel; public override bool Equals(object? obj) { return obj is MemberReferenceMethod method && handle.Equals(method.handle); } public override int GetHashCode() { return handle.GetHashCode(); } public override Method? SourceDeclaration => sourceDeclaration; public override bool IsStatic => !signature.Header.IsInstance; public override Type DeclaringType => declaringType; public override string Name => Context.ShortName(mr.Name); public override IEnumerable TypeParameters => parent.TypeParameters.Concat(gc.TypeParameters); public override IEnumerable Contents { get { genericParams = new MethodTypeParameter[signature.GenericParameterCount]; for (var p = 0; p < genericParams.Length; ++p) genericParams[p] = Context.Populate(new MethodTypeParameter(this, this, p)); foreach (var p in genericParams) yield return p; var typeSignature = mr.DecodeMethodSignature(Context.TypeSignatureDecoder, this); var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray(); Parameters = parameters.OfType().ToArray(); foreach (var p in parameters) yield return p; foreach (var f in PopulateFlags) yield return f; foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, typeSignature.ReturnType)) { yield return m; } if (SourceDeclaration is not null) yield return Tuples.cil_method_source_declaration(this, SourceDeclaration); } } } }