/// <summary> Converts the function to a matching delegate, if possible (returns null otherwise). </summary> /// <param name="cx">If specified, tries to find the matching delegate in this MetadataContext. If null, uses only standard delegates. </param> public TypeReference TryGetDelegate(MetadataContext cx = null) { // TODO: weird delegates (ref parameters, ...), many many arguments if (this.ResultType == TypeSignature.Void) { var reflectionAction = Type.GetType($"System.Action`{this.Params.Length}"); if (reflectionAction is null) { return(null); } var actionSig = TypeSignature.FromType(reflectionAction); var actionRef = TypeReference.SpecializedType(actionSig, this.Params.Select(p => p.Type).ToImmutableArray()); return(actionRef); } else { var reflectionAction = Type.GetType($"System.Func`{this.Params.Length + 1}"); if (reflectionAction is null) { return(null); } var actionSig = TypeSignature.FromType(reflectionAction); var actionRef = TypeReference.SpecializedType(actionSig, this.Params.Select(p => p.Type).Append(this.ResultType).ToImmutableArray()); return(actionRef); } }
public static TypeDef AutoResolveImplementations(TypeDef type, MetadataContext cx) { var thisType = type.Signature.SpecializeByItself(); var baseTypes = cx.GetBaseTypes(thisType).ToArray(); var interfaces = cx.GetDirectImplements(thisType).ToArray(); // exclude methods and properties that are already implemented var explicitImplMethods = new HashSet <MethodSignature>(type.Members.OfType <MethodDef>().SelectMany(m => m.Implements).Select(m => m.Signature)); var explicitImplProps = new HashSet <PropertySignature>(type.Members.OfType <PropertyDef>().SelectMany(m => m.Implements).Select(m => m.Signature)); var methods = baseTypes.Concat(interfaces).ZipSelectMany(t => cx.GetMemberMethodDefs(t.Type).Where(m => !explicitImplMethods.Contains(m))).ToLookup(m => m.Item2.Name); var properties = baseTypes.Concat(interfaces).ZipSelectMany(t => cx.GetMemberPropertyDefs(t.Type).Where(p => !explicitImplProps.Contains(p))).ToLookup(p => p.Item2.Name); var myMembers = type.Members.Select(member => { // implementations must be public if (member is MethodDef method && methods.Contains(method.Signature.Name)) { var mm = methods[method.Signature.Name] .Where(m2 => m2.Item2.Params.Select(p => p.Type).SequenceEqual(method.Signature.Params.Select(p => p.Type))) .Where(m2 => m2.Item2.ResultType == method.Signature.ResultType) .Where(m2 => method.Signature.Accessibility == m2.Item2.Accessibility) .Where(m2 => method.Signature.IsOverride || m2.Item2.DeclaringType.Kind == "interface") .ToArray(); return(method.With(implements: method.Implements.AddRange(mm.Select(m => m.Item2.Specialize(m.Item1.TypeArguments, m.Item2.TypeParameters.Select(TypeReference.GenericParameter)))))); }
public EmitContext(E.MetadataContext metadata, EmitSettings settings, DataSchema fullSchema) { var compilation = metadata.Compilation; // TODO: move this assert to ExprCS foreach (var t in Enum.GetValues(typeof(KnownTypeCode))) { var ft = compilation.FindType((KnownTypeCode)t); Debug.Assert(!(ft is UnknownType) || KnownTypeCode.Unsafe.Equals(t) || t.ToString().StartsWith("IAsync")); } Metadata = metadata; Compilation = compilation; Module = Compilation.MainModule; Settings = settings; FullSchema = fullSchema; }
public static TypeDef Fix(TypeDef type, MetadataContext cx) { // note that none of the referenced types must be defined in `cx`. This function is called before the types are committed. var kind = type.Signature.Kind; if (kind == "class" && !(type.Signature.IsAbstract && !type.Signature.CanOverride) && !type.Members.OfType <MethodDef>().Any(m => m.Signature.IsConstructor())) { type = type.AddMember( MethodDef.Create(MethodSignature.ImplicitConstructor(type.Signature), @this => @this.Read().Box().CallMethod(MethodSignature.Object_Constructor)) ); } // apply to descendant types type = type.With(members: type.Members.EagerSelect(m => m is TypeDef t ? Fix(t, cx) : m)); return(type); }
// public static TS.ITypeDefinition GetTypeDefinition(this MetadataContext c, TypeSignature t) => // (TS.ITypeDefinition)c.DeclaredEntities.GetValueOrDefault(t) ?? // c.Compilation.FindType(t.GetFullTypeName()).GetDefinition() ?? // throw new Exception($"Could not resolve {t.GetFullTypeName()} for some reason."); public static TS.IType GetTypeReference(this MetadataContext c, TypeReference tref) => tref.Match( st => { if (st.TypeArguments.IsEmpty) { return((IType)c.GetTypeDef(st.Type)); } var genericType = // when we have a parent type, we first need specialize it, then we can specialize our type // st.DeclaringType() is SpecializedType declaringType ? // c.GetTypeReference(declaringType).GetNestedTypes(t => t.Name == st.Type.Name && t.TypeParameterCount == st.Type.TypeParameters.Length).Single() : c.GetTypeDef(st.Type); return(new ParameterizedType( genericType, st.TypeArguments // .Skip(st.GenericParameters.Length - st.Type.TypeParameters.Length) .Select(p => GetTypeReference(c, p)))); }, arrayType => new TS.ArrayType(c.Compilation, GetTypeReference(c, arrayType.Type), arrayType.Dimensions), byrefType => new TS.ByReferenceType(GetTypeReference(c, byrefType.Type)), pointerType => new TS.PointerType(GetTypeReference(c, pointerType.Type)), gParam => c.GenericParameterStore.Retreive(gParam), function => throw new NotSupportedException($"Function types are not supported in metadata")
/// <summary> /// Gets the invoke method for a delegate type. /// </summary> /// <remarks> /// Returns null if the type is not a delegate type; or if the invoke method could not be found. /// </remarks> public static MethodReference GetDelegateInvokeMethod(this SpecializedType @delegate, MetadataContext cx) { if (@delegate == null) { throw new ArgumentNullException("type"); } if (@delegate.Type.Kind == "delegate") { return(cx.GetMemberMethods(@delegate).FirstOrDefault(m => m.Name() == "Invoke")); } else { return(null); } }
/// <summary> Returns the element type of any class implementing <see cref="IEnumerable{T}" /> interface. Returns null when it is not found. </summary> public static TypeReference GetElementTypeFromIEnumerable(this SpecializedType collectionType, MetadataContext cx, bool allowIEnumerator, out bool?isGeneric) { bool foundNonGenericIEnumerable = false; foreach (var baseType in cx.GetBaseTypes(collectionType)) { if (baseType.Type == TypeSignature.IEnumerableOfT || (allowIEnumerator && baseType.Type == TypeSignature.IEnumeratorOfT)) { isGeneric = true; return(Assert.Single(baseType.TypeArguments)); } if (baseType.Type == TypeSignature.IEnumerable || (allowIEnumerator && baseType.Type == TypeSignature.IEnumerator)) { foundNonGenericIEnumerable = true; } } // System.Collections.IEnumerable found in type hierarchy -> Object is element type. if (foundNonGenericIEnumerable) { isGeneric = false; return(TypeSignature.Object); } isGeneric = null; return(null); }
/// <summary> Returns the element type of any class implementing <see cref="IEnumerable{T}" /> interface. Returns null when it is not found. </summary> public static TypeReference GetElementTypeFromIEnumerable(this TypeReference collectionType, MetadataContext cx, bool allowIEnumerator, out bool?isGeneric) { bool?isGeneric_ = null; var r = collectionType.Match( st => GetElementTypeFromIEnumerable(st, cx, allowIEnumerator, out isGeneric_), arr => { if (arr.Dimensions == 1) { isGeneric_ = true; return(arr.Type); } else { return(null); } }, _ => null, _ => null, _ => null, _ => null); isGeneric = isGeneric_; return(r); }
/// <summary> /// Gets whether this type definition is derived from the base type definition. /// </summary> public static bool IsDerivedFrom(this SpecializedType type, SpecializedType baseType, MetadataContext cx) { if (type == null) { throw new ArgumentNullException("type"); } if (baseType == null) { return(false); } return(cx.GetBaseTypes(type).Contains(baseType)); }
/// <summary> /// Converts a delegate to a matching function type. /// </summary> /// <remarks> /// Returns null if the type is not a delegate type; or if the invoke method could not be found. /// </remarks> public static FunctionType DelegateToFunction(this SpecializedType @delegate, MetadataContext cx) { var invoke = @delegate.GetDelegateInvokeMethod(cx); return(invoke?.ToFunctionType()); }