/// <summary> /// Initialize a new instance of the <see cref="MessageProcessedEventArgs"/> class. /// </summary> /// <param name="message">The message.</param> /// <param name="ordinal">Zero-based message ordinal.</param> /// <param name="count"> /// The total number of messages to be /// sent by the calling method. /// </param> /// <param name="processedType">Indicates whether the message was sent or skipped.</param> public MessageProcessedEventArgs(MimeMessage message, int ordinal, int count, ProcessedType processedType) { Message = message ?? throw new ArgumentNullException(nameof(message)); Count = count >= -1 ? count : throw new ArgumentOutOfRangeException(nameof(count)); Ordinal = ordinal >= 0 ? ordinal : throw new ArgumentOutOfRangeException(nameof(ordinal)); ProcessedType = processedType; }
bool AddDecimalSupport(Type t) { if (system_decimal != null) { return(true); } var corlib = GetMscorlib(t); system_decimal = new ProcessedType(t) { Assembly = corlib, // this is tracked because the linker (if enabled) needs to be aware of the requirement // but we do not want any code to be generated (it's referenced only from native/glue code) IsNativeReference = true, Methods = new List <ProcessedMethod> (), }; // we don't want to being everything from System.Decimal, but only the bits the support code can call var string_type = corlib.Assembly.GetType("System.String"); var iformatprovider_type = corlib.Assembly.GetType("System.IFormatProvider"); var parse = t.GetMethod("Parse", new Type [] { string_type, iformatprovider_type }); system_decimal.Methods.Add(new ProcessedMethod(parse, this)); var tostring = t.GetMethod("ToString", new Type [] { iformatprovider_type }); system_decimal.Methods.Add(new ProcessedMethod(tostring, this)); AddExtraType(system_decimal); return(true); }
public void DefineSlotNameTwice() { ProcessedType processedType = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_DefineSlotNameTwice)); TemplateCache cache = new TemplateCache(Setup("App")); Assert.DoesNotThrow(() => { cache.GetParsedTemplate(processedType); }); }
public void ParseNamespace() { ProcessedType processedType = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_Namespace)); TemplateCache cache = new TemplateCache(Setup("App")); TemplateRootNode templateRoot = cache.GetParsedTemplate(processedType); Assert.AreEqual(typeof(UIDivElement), templateRoot.children[0].processedType.rawType); }
public void ParseNamespace_NotThere() { ParseException exception = Assert.Throws <ParseException>(() => { ProcessedType processedType = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_Namespace_Unknown)); TemplateCache cache = new TemplateCache(Setup("App")); cache.GetParsedTemplate(processedType); }); Assert.IsTrue(exception.Message.Contains(ParseException.UnresolvedTagName("Data/XMLTemplateParsing/XMLTemplateParsing_Namespaces.xml", new TemplateLineInfo(11, 10), "NotHere:Div").Message)); }
void GenerateEnum(ProcessedType type) { Type t = type.Type; var managed_name = type.ObjCName; var underlying_type = t.GetEnumUnderlyingType(); var base_type = NameGenerator.GetTypeName(underlying_type); // it's nicer to expose flags as unsigned integers - but .NET defaults to `int` bool flags = t.HasCustomAttribute("System", "FlagsAttribute"); if (flags) { switch (Type.GetTypeCode(underlying_type)) { case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: base_type = "unsigned " + base_type; break; } } var macro = flags ? "NS_OPTIONS" : "NS_ENUM"; headers.WriteLine($"/** Enumeration {managed_name}"); headers.WriteLine($" * Corresponding .NET Qualified Name: `{t.AssemblyQualifiedName}`"); headers.WriteLine(" */"); headers.WriteLine($"typedef {macro}({base_type}, {managed_name}) {{"); headers.Indent++; foreach (var name in t.GetEnumNames()) { var value = t.GetField(name).GetRawConstantValue(); headers.Write($"{managed_name}{name} = "); if (flags) { headers.Write($"0x{value:x}"); } else { headers.Write(value); } headers.WriteLine(','); } headers.Indent--; headers.WriteLine("};"); headers.WriteLine(); }
public void ExpandedTemplate() { ProcessedType processedType = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_ExpandTemplate)); TemplateCache cache = new TemplateCache(Setup("App")); TemplateRootNode templateRootRoot = cache.GetParsedTemplate(processedType); Assert.AreEqual(3, templateRootRoot.ChildCount); AssertAndReturn <TextNode>(templateRootRoot[0]); ExpandedTemplateNode expandedTemplate = AssertAndReturn <ExpandedTemplateNode>(templateRootRoot[1]); Assert.AreEqual(typeof(XMLTemplateParsing_ExpandedTemplateChild), expandedTemplate.processedType.rawType); AssertAndReturn <TextNode>(templateRootRoot[2]); }
public void OverrideSlot() { ProcessedType processedType = TypeProcessor.GetProcessedType(typeof(XMLTemplateParsing_OverrideSlot)); TemplateCache cache = new TemplateCache(Setup("App")); TemplateRootNode templateRootRoot = cache.GetParsedTemplate(processedType); Assert.AreEqual(3, templateRootRoot.ChildCount); AssertTrimmedText("Hello Before", templateRootRoot[0]); AssertTrimmedText("Hello After", templateRootRoot[2]); ExpandedTemplateNode expandedTemplateNode = AssertAndReturn <ExpandedTemplateNode>(templateRootRoot[1]); SlotNode overrideNode = AssertAndReturn <SlotNode>(expandedTemplateNode.slotOverrideNodes[0]); Assert.AreEqual("my-slot", overrideNode.slotName); Assert.AreEqual(SlotType.Override, overrideNode.slotType); AssertTrimmedText("Hello Between", overrideNode[0]); }
// post processing logic IEnumerable <ProcessedConstructor> GetUnavailableParentCtors(ProcessedType pt) { var type = pt.Type; var baseType = type.BaseType; if ((baseType == null) || (baseType.Namespace == "System" && baseType.Name == "Object")) { return(Enumerable.Empty <ProcessedConstructor> ()); } var baseProcessedType = GetProcessedType(baseType); if ((baseProcessedType == null) || !baseProcessedType.HasConstructors) { return(Enumerable.Empty <ProcessedConstructor> ()); } var typeCtors = pt.Constructors; List <ProcessedConstructor> parentCtors = baseProcessedType.Constructors; var finalList = new List <ProcessedConstructor> (); foreach (var pctor in parentCtors) { var pctorParams = pctor.Parameters; foreach (var ctor in typeCtors) { var ctorParams = ctor.Parameters; if (pctorParams.Any(pc => !ctorParams.Any(p => p.Position == pc.Position && pc.ParameterType == p.ParameterType))) { finalList.Add(pctor); break; } } } return(finalList); }
public void Process() { var generatorTypes = _typesToGenerate.Select(t => new { BaseData = t, generatorType = ReflectionHelper.FindBaseDataGeneratorType(t) }) .ToDictionary(t => t.BaseData, t => t.generatorType); var metadataResolverTypes = _typesToGenerate.Select(t => new { BaseData = t, metadataResolverType = ReflectionHelper.FindBaseDataMetadataResolverType(t) }) .ToDictionary(t => t.BaseData, t => t.metadataResolverType); var typesToProcess = _typesToGenerate.ToList(); var processedTypes = new Dictionary <Type, ProcessedType>(); var baseTypeConstructorArgumentsLength = typeof(DataGenerator <>).GetConstructors().First().GetParameters().Length; bool doneAny; do { doneAny = false; for (int i = 0; i < typesToProcess.Count; i++) { var type = typesToProcess[i]; var generatorType = generatorTypes[type]; var constructorToUse = generatorType.GetConstructors().First(); var parameters = constructorToUse.GetParameters(); var additionalArguments = new List <object>(); // Iterate over any arguments in the constructor that are after the required base type arguments // Find any arguments that can be set from other type values for (int j = baseTypeConstructorArgumentsLength; j < parameters.Length; j++) { if (GetProcessedTypeForParameter(parameters[j], processedTypes, out var argument)) { additionalArguments.Add(argument); } else { break; } } // If there are enough arguments to satisfy the parameters then a generator can be instantiated if (baseTypeConstructorArgumentsLength + additionalArguments.Count == parameters.Length) { if (!metadataResolverTypes.ContainsKey(type)) { throw new InvalidOperationException($"Unable to find a MetadataResolver type for {type.Name}"); } dynamic metadataResolver = Activator.CreateInstance(metadataResolverTypes[type]); var arguments = new[] { Logger, PathResolver, metadataResolver }.Union(additionalArguments).ToArray(); dynamic dataGenerator = constructorToUse.Invoke(arguments); var result = dataGenerator.Generate(); var processedType = new ProcessedType { MetadataResolver = metadataResolver, Output = result }; processedTypes.Add(type, processedType); doneAny = true; typesToProcess.RemoveAt(i); i--; } } } while (typesToProcess.Count > 0 && doneAny); Logger.LogSection("Types where a BaseDataGenerator could not be instantiated", typesToProcess.Select(t => t.FullName ?? t.Name)); Logger.LogSection("Type Summary", processedTypes.Select(t => $"{t.Key.Name} {((dynamic)t.Value.Output).Count}")); ProcessOperations(processedTypes); }
bool IsSupported(Type t) { if (t.IsByRef) { return(IsSupported(t.GetElementType())); } if (t.IsArray) { return(IsSupported(t.GetElementType())); } if (unsupported.Contains(t)) { return(false); } if (t.IsPointer) { Delayed.Add(ErrorHelper.CreateWarning(1010, $"Type `{t}` is not generated because `unsafe pointers` are not supported.")); unsupported.Add(t); return(false); } if (t.IsGenericParameter || t.IsGenericType) { Delayed.Add(ErrorHelper.CreateWarning(1010, $"Type `{t}` is not generated because `generics` are not supported.")); unsupported.Add(t); return(false); } switch (t.Namespace) { case "System": switch (t.Name) { case "Object": // we cannot accept arbitrary NSObject (which we might not have bound) into mono case "DBNull": case "Exception": case "Type": Delayed.Add(ErrorHelper.CreateWarning(1011, $"Type `{t}` is not generated because it lacks a native counterpart.")); unsupported.Add(t); return(false); case "DateTime": // FIXME: NSDateTime Delayed.Add(ErrorHelper.CreateWarning(1012, $"Type `{t}` is not generated because it lacks a marshaling code with a native counterpart.")); unsupported.Add(t); return(false); case "Decimal": return(AddDecimalSupport(t)); case "TimeSpan": if (system_timespan == null) { system_timespan = new ProcessedType(t) { Assembly = GetMscorlib(t), }; AddExtraType(system_timespan); } return(true); case "IFormatProvider": if (system_iformatprovider == null) { system_iformatprovider = new ProcessedType(t) { Assembly = GetMscorlib(t), }; AddExtraType(system_iformatprovider); } return(true); } break; case "System.Globalization": switch (t.Name) { case "TimeSpanStyles": // enum for TimeSpan support if (system_globalization_timespanstyles == null) { system_globalization_timespanstyles = new ProcessedType(t) { Assembly = GetMscorlib(t), }; AddExtraType(system_globalization_timespanstyles); } return(true); } break; } var base_type = t.BaseType; return((base_type == null) || base_type.Is("System", "Object") ? true : IsSupported(base_type)); }
public static CompileException UnresolvableGenericElement(ProcessedType processedType, string value) { return(new CompileException($"{processedType.rawType} requires a class attribute of type {nameof(GenericElementTypeResolvedByAttribute)} in order to be used in a template and a value that is not null or default also declared in the template")); }
public override void Process(ProcessedType pt) { Types.Add(pt); if (pt.IsNativeReference) { return; } var t = pt.Type; if (t.IsEnum) { return; } extension_type = t.HasCustomAttribute("System.Runtime.CompilerServices", "ExtensionAttribute"); implement_system_icomparable = t.Implements("System", "IComparable"); implement_system_icomparable_t = t.Implements("System", "IComparable`1"); implement_system_iequatable_t = t.Implements("System", "IEquatable`1"); var constructors = GetConstructors(t).OrderBy((arg) => arg.ParameterCount).ToList(); var processedConstructors = PostProcessConstructors(constructors).ToList(); pt.Constructors = processedConstructors; var meths = GetMethods(pt).OrderBy((arg) => arg.Method.Name).ToList(); var processedMethods = PostProcessMethods(meths).ToList(); pt.Methods = processedMethods; var props = new List <PropertyInfo> (); var subscriptProps = new List <PropertyInfo> (); foreach (var pi in GetProperties(t)) { var getter = pi.GetGetMethod(); var setter = pi.GetSetMethod(); // setter only property are valid in .NET and we need to generate a method in ObjC (there's no writeonly properties) if (getter == null) { continue; } // indexers are implemented as methods and object subscripting if ((getter.ParameterCount > 0) || ((setter != null) && setter.ParameterCount > 1)) { subscriptProps.Add(pi); continue; } // we can do better than methods for the more common cases (readonly and readwrite) processedMethods.RemoveAll(x => x.Method == getter); processedMethods.RemoveAll(x => x.Method == setter); props.Add(pi); } props = props.OrderBy((arg) => arg.Name).ToList(); var processedProperties = PostProcessProperties(props).ToList(); pt.Properties = processedProperties; if (subscriptProps.Count > 0) { if (subscriptProps.Count > 1) { Delayed.Add(ErrorHelper.CreateWarning(1041, $"Indexed properties on {t.Name} is not generated because multiple indexed properties not supported.")); } else { subscriptProperties.Add(t, PostProcessSubscriptProperties(subscriptProps).ToList()); } } // fields will need to be wrapped within properties var f = GetFields(t).OrderBy((arg) => arg.Name).ToList(); var processedFields = PostProcessFields(f).ToList(); pt.Fields = processedFields; }
public static CompileException GenericElementMissingResolver(ProcessedType processedType) { return(new CompileException($"{processedType.rawType} requires a class attribute of type {nameof(GenericElementTypeResolvedByAttribute)} in order to be used in a template")); }
public TemplateNotFoundException(ProcessedType processedType, string xmlPath) : base($"Unable to find default template for type {processedType.rawType}. Searched using default resolver at paths: \n[{xmlPath}]") { }
protected override void Generate(ProcessedType type) { Type t = type.Type; var aname = t.Assembly.GetName().Name.Sanitize(); var static_type = t.IsSealed && t.IsAbstract; var managed_name = NameGenerator.GetObjCName(t); List <string> conformed_protocols = new List <string> (); foreach (var i in t.GetInterfaces()) { if (protocols.Contains(i)) { conformed_protocols.Add(NameGenerator.GetObjCName(i)); } } var tbuilder = new ClassHelper(headers, implementation) { AssemblyQualifiedName = t.AssemblyQualifiedName, AssemblyName = aname, BaseTypeName = NameGenerator.GetTypeName(t.BaseType), Name = NameGenerator.GetTypeName(t), Namespace = t.Namespace, ManagedName = t.Name, Protocols = conformed_protocols, IsBaseTypeBound = types.Contains(t.BaseType), IsStatic = t.IsSealed && t.IsAbstract, MetadataToken = t.MetadataToken, }; tbuilder.BeginHeaders(); tbuilder.BeginImplementation(); var default_init = false; List <ProcessedConstructor> constructors; if (ctors.TryGetValue(t, out constructors)) { // First get the unavailable init ctor selectors in parent class var unavailableCtors = GetUnavailableParentCtors(t, constructors); if (unavailableCtors.Count() > 0) { // TODO: Print a #pragma mark once we have a well defined header structure http://nshipster.com/pragma/ foreach (var uctor in unavailableCtors) { var ctorparams = uctor.Constructor.GetParameters(); string name = "init"; string signature = ".ctor()"; if (ctorparams.Length > 0) { GetSignatures("initWith", uctor.Constructor.Name, uctor.Constructor, ctorparams, uctor.FallBackToTypeName, false, out name, out signature); } headers.WriteLine("/** This initializer is not available as it was not re-exposed from the base type"); headers.WriteLine(" * For more details consult https://github.com/mono/Embeddinator-4000/blob/master/docs/ObjC.md#constructors-vs-initializers"); headers.WriteLine(" */"); headers.WriteLine($"- (nullable instancetype){name} NS_UNAVAILABLE;"); headers.WriteLine(); } } foreach (var ctor in constructors) { var pcount = ctor.Constructor.ParameterCount; default_init |= pcount == 0; var parameters = ctor.Constructor.GetParameters(); string name = "init"; string signature = ".ctor()"; if (parameters.Length > 0) { GetSignatures("initWith", ctor.Constructor.Name, ctor.Constructor, parameters, ctor.FallBackToTypeName, false, out name, out signature); } var builder = new MethodHelper(headers, implementation) { AssemblySafeName = aname, ReturnType = "nullable instancetype", ManagedTypeName = t.FullName, MetadataToken = ctor.Constructor.MetadataToken, MonoSignature = signature, ObjCSignature = name, ObjCTypeName = managed_name, IsConstructor = true, IsValueType = t.IsValueType, IgnoreException = true, }; builder.WriteHeaders(); builder.BeginImplementation(); builder.WriteMethodLookup(); // TODO: this logic will need to be update for managed NSObject types (e.g. from XI / XM) not to call [super init] implementation.WriteLine("if (!_object) {"); implementation.Indent++; implementation.WriteLine($"MonoObject* __instance = mono_object_new (__mono_context.domain, {managed_name}_class);"); string postInvoke = String.Empty; var args = "nil"; if (pcount > 0) { Generate(parameters, false, out postInvoke); args = "__args"; } builder.WriteInvoke(args); implementation.Write(postInvoke); implementation.WriteLine("_object = mono_embeddinator_create_object (__instance);"); implementation.Indent--; implementation.WriteLine("}"); if (types.Contains(t.BaseType)) { implementation.WriteLine("return self = [super initForSuper];"); } else { implementation.WriteLine("return self = [super init];"); } builder.EndImplementation(); headers.WriteLine(); if (members_with_default_values.Contains(ctor.Constructor)) { default_init |= GenerateDefaultValuesWrappers(name, ctor.Constructor); } } } // generate an `init` for a value type (even if none was defined, the default one is usable) if (!default_init && t.IsValueType) { var builder = new MethodHelper(headers, implementation) { AssemblySafeName = aname, ReturnType = "nullable instancetype", ManagedTypeName = t.FullName, MonoSignature = ".ctor()", ObjCSignature = "init", ObjCTypeName = managed_name, IsConstructor = true, IsValueType = t.IsValueType, IgnoreException = true, }; builder.WriteHeaders(); builder.BeginImplementation(); // no call to `WriteMethodLookup` since there is not such method if we reached this case implementation.WriteLine("if (!_object) {"); implementation.Indent++; implementation.WriteLine($"MonoObject* __instance = mono_object_new (__mono_context.domain, {managed_name}_class);"); // no call to `WriteInvoke` since there is not such method if we reached this case implementation.WriteLine("_object = mono_embeddinator_create_object (__instance);"); implementation.Indent--; implementation.WriteLine("}"); if (types.Contains(t.BaseType)) { implementation.WriteLine("return self = [super initForSuper];"); } else { implementation.WriteLine("return self = [super init];"); } builder.EndImplementation(); headers.WriteLine(); default_init = true; } if (!default_init || static_type) { tbuilder.DefineNoDefaultInit(); } List <ProcessedProperty> props; if (properties.TryGetValue(t, out props)) { headers.WriteLine(); foreach (var pi in props) { Generate(pi); } } List <ProcessedFieldInfo> f; if (fields.TryGetValue(t, out f)) { headers.WriteLine(); foreach (var fi in f) { Generate(fi); } } List <ProcessedProperty> s; if (subscriptProperties.TryGetValue(t, out s)) { headers.WriteLine(); foreach (var si in s) { GenerateSubscript(si); } } List <ProcessedMethod> meths; if (methods.TryGetValue(t, out meths)) { headers.WriteLine(); foreach (var mi in meths) { Generate(mi); } } MethodInfo m; if (icomparable.TryGetValue(t, out m)) { var pt = m.GetParameters() [0].ParameterType; var builder = new ComparableHelper(headers, implementation) { ObjCSignature = $"compare:({managed_name} * _Nullable)other", AssemblySafeName = aname, MetadataToken = m.MetadataToken, ObjCTypeName = managed_name, ManagedTypeName = t.FullName, MonoSignature = $"CompareTo({NameGenerator.GetMonoName (pt)})", }; builder.WriteHeaders(); builder.WriteImplementation(); } if (equals.TryGetValue(t, out m)) { var builder = new EqualsHelper(headers, implementation) { AssemblySafeName = aname, MetadataToken = m.MetadataToken, ObjCTypeName = managed_name, ManagedTypeName = t.FullName, }; builder.WriteHeaders(); builder.WriteImplementation(); } if (hashes.TryGetValue(t, out m)) { var builder = new HashHelper(headers, implementation) { AssemblySafeName = aname, MetadataToken = m.MetadataToken, ObjCTypeName = managed_name, ManagedTypeName = t.FullName, }; builder.WriteHeaders(); builder.WriteImplementation(); } tbuilder.EndHeaders(); tbuilder.EndImplementation(); }
void GenerateProtocol(ProcessedType type) { Type t = type.Type; var pbuilder = new ProtocolHelper(headers, implementation) { AssemblyQualifiedName = t.AssemblyQualifiedName, AssemblyName = t.Assembly.GetName().Name.Sanitize(), ProtocolName = NameGenerator.GetTypeName(t), Namespace = t.Namespace, ManagedName = t.Name, MetadataToken = t.MetadataToken, }; pbuilder.BeginHeaders(); // no need to iterate constructors or fields as they cannot be part of net interfaces // do not generate implementations for protocols implementation.Enabled = false; List <ProcessedProperty> props; if (properties.TryGetValue(t, out props)) { headers.WriteLine(); foreach (var pi in props) { Generate(pi); } } List <ProcessedMethod> meths; if (methods.TryGetValue(t, out meths)) { headers.WriteLine(); foreach (var mi in meths) { Generate(mi); } } pbuilder.EndHeaders(); // wrappers are internal so not part of the headers headers.Enabled = false; implementation.Enabled = true; pbuilder.BeginImplementation(); if (properties.TryGetValue(t, out props)) { implementation.WriteLine(); foreach (var pi in props) { Generate(pi); } } if (methods.TryGetValue(t, out meths)) { implementation.WriteLine(); foreach (var mi in meths) { Generate(mi); } } pbuilder.EndImplementation(); headers.Enabled = true; }
protected IEnumerable <ProcessedMethod> GetMethods(ProcessedType type) { var t = type.Type; foreach (var mi in t.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { if (!mi.IsPublic) { continue; } // handle special cases where we can implement something better, e.g. a better match if (implement_system_icomparable_t) { // for X we prefer `IComparable<X>` to `IComparable` - since it will be exposed identically to ObjC if (mi.Match("System.Int32", "CompareTo", t.FullName)) { icomparable [t] = mi; continue; } } if (implement_system_icomparable && mi.Match("System.Int32", "CompareTo", "System.Object")) { // don't replace CompareTo(T) with CompareTo(Object) if (!icomparable.ContainsKey(t)) { icomparable.Add(t, mi); } continue; } if (mi.Match("System.Boolean", "Equals", "System.Object")) { yield return(new ProcessedMethod(mi, this) { DeclaringType = type, MethodType = MethodType.NSObjectProcotolIsEqual, }); continue; } if (implement_system_iequatable_t && mi.Match("System.Boolean", "Equals", new string [] { null })) { yield return(new ProcessedMethod(mi, this) { DeclaringType = type, MethodType = MethodType.IEquatable, }); continue; } if (mi.Match("System.Int32", "GetHashCode")) { yield return(new ProcessedMethod(mi, this) { DeclaringType = type, MethodType = MethodType.NSObjectProcotolHash, }); continue; } var rt = mi.ReturnType; if (!IsSupported(rt)) { Delayed.Add(ErrorHelper.CreateWarning(1030, $"Method `{mi}` is not generated because return type `{rt}` is not supported.")); continue; } bool pcheck = true; foreach (var p in mi.GetParameters()) { var pt = p.ParameterType; if (!IsSupported(pt)) { Delayed.Add(ErrorHelper.CreateWarning(1031, $"Method `{mi}` is not generated because of parameter type `{pt}` is not supported.")); pcheck = false; } else if (p.HasDefaultValue) { members_with_default_values.Add(mi); } } if (!pcheck) { continue; } // handle extension methods if (extension_type && mi.HasCustomAttribute("System.Runtime.CompilerServices", "ExtensionAttribute")) { var extended_type = mi.GetParameters() [0].ParameterType; if (extended_type.IsPrimitive) { Delayed.Add(ErrorHelper.CreateWarning(1034, $"Extension method `{mi}` is not generated inside a category because they cannot be created on primitive type `{extended_type}`. A normal, static method was generated.")); } else { Dictionary <Type, List <ProcessedMethod> > extensions; if (!extensions_methods.TryGetValue(t, out extensions)) { extensions = new Dictionary <Type, List <ProcessedMethod> > (); extensions_methods.Add(t, extensions); } List <ProcessedMethod> extmethods; if (!extensions.TryGetValue(extended_type, out extmethods)) { extmethods = new List <ProcessedMethod> (); extensions.Add(extended_type, extmethods); } extmethods.Add(new ProcessedMethod(mi, this)); continue; } } yield return(new ProcessedMethod(mi, this)); } }
public static CompileException UnresolvedGenericElement(ProcessedType processedType, TemplateNodeDebugData data) { return(new CompileException($"Unable to resolve the concrete type for " + processedType.rawType + $"\n\nFailed parsing {data.tagName} at {data.fileName}:{data.lineInfo}\n" + $"You can try to fix this by providing the type explicitly. (add an attribute generic:type=\"your,types,here\"")); }