diff --git a/src/bgen/BindingTouch.cs b/src/bgen/BindingTouch.cs index e5401015f36a..a6f63bac1855 100644 --- a/src/bgen/BindingTouch.cs +++ b/src/bgen/BindingTouch.cs @@ -431,7 +431,7 @@ int Main3 (string [] args) "mscorlib" ); - if (!TryLoadApi (tmpass, out Assembly? api) || !TryLoadApi (baselibdll, out Assembly? baselib)) + if (!TryLoadApi (tmpass, out Assembly? apiAssembly) || !TryLoadApi (baselibdll, out Assembly? baselib)) return 1; attributeManager ??= new AttributeManager (this); @@ -440,10 +440,10 @@ int Main3 (string [] args) // Explicitly load our attribute library so that IKVM doesn't try (and fail) to find it. universe.LoadFromAssemblyPath (GetAttributeLibraryPath ()); - typeCache ??= new (universe, Frameworks, CurrentPlatform, api, universe.CoreAssembly, baselib, BindThirdPartyLibrary); + typeCache ??= new (universe, Frameworks, CurrentPlatform, apiAssembly, universe.CoreAssembly, baselib, BindThirdPartyLibrary); typeManager ??= new (this); - foreach (var linkWith in AttributeManager.GetCustomAttributes (api)) { + foreach (var linkWith in AttributeManager.GetCustomAttributes (apiAssembly)) { #if NET if (string.IsNullOrEmpty (linkWith.LibraryName)) #else @@ -479,26 +479,14 @@ int Main3 (string [] args) } } - var types = new List (); - var strong_dictionaries = new List (); - foreach (var t in api.GetTypes ()) { - if ((config.ProcessEnums && t.IsEnum) || - AttributeManager.HasAttribute (t) || - AttributeManager.HasAttribute (t) || - AttributeManager.HasAttribute (t) || - AttributeManager.HasAttribute (t)) - types.Add (t); - if (AttributeManager.HasAttribute (t)) - strong_dictionaries.Add (t); - } - + var api = TypeManager.ParseApi (apiAssembly, config.ProcessEnums); namespaceCache ??= new NamespaceCache ( CurrentPlatform, config.HelperClassNamespace ?? firstApiDefinitionName, skipSystemDrawing ); - var g = new Generator (this, config.IsPublicMode, config.IsExternal, config.IsDebug, types.ToArray (), strong_dictionaries.ToArray ()) { + var g = new Generator (this, api, config.IsPublicMode, config.IsExternal, config.IsDebug) { BaseDir = config.BindingFilesOutputDirectory ?? config.TemporaryFileDirectory, ZeroCopyStrings = config.UseZeroCopy, InlineSelectors = config.InlineSelectors ?? (CurrentPlatform != PlatformName.MacOSX), diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs index bf604e0ad375..1c400d248c57 100644 --- a/src/bgen/Generator.cs +++ b/src/bgen/Generator.cs @@ -101,7 +101,7 @@ Nomenclator Nomenclator { public string CoreServicesMap => CurrentPlatform.GetCoreServicesMap (); public string PDFKitMap => CurrentPlatform.GetPDFKitMap (); - Type [] types, strong_dictionaries; + Api api; bool debug; bool external; StreamWriter sw, m; @@ -1273,14 +1273,13 @@ public ExportAttribute GetGetterExportAttribute (PropertyInfo pinfo) return AttributeManager.GetCustomAttribute (pinfo).ToGetter (pinfo); } - public Generator (BindingTouch binding_touch, bool is_public_mode, bool external, bool debug, Type [] types, Type [] strong_dictionaries) + public Generator (BindingTouch binding_touch, Api api, bool is_public_mode, bool external, bool debug) { BindingTouch = binding_touch; IsPublicMode = is_public_mode; this.external = external; this.debug = debug; - this.types = types; - this.strong_dictionaries = strong_dictionaries; + this.api = api; basedir = "."; NativeHandleType = binding_touch.IsDotNet ? "NativeHandle" : "IntPtr"; } @@ -1314,10 +1313,9 @@ public void Go () send_methods ["IntPtr_objc_msgSendSuper_IntPtr"] = "IntPtr_objc_msgSendSuper_IntPtr"; } - Array.Sort (types, (a, b) => string.CompareOrdinal (a.FullName, b.FullName)); - TypeManager.SetTypesThatMustAlwaysBeGloballyNamed (types); + TypeManager.SetTypesThatMustAlwaysBeGloballyNamed (api.Types); - foreach (Type t in types) { + foreach (Type t in api.Types) { if (t.IsUnavailable (this)) continue; @@ -1485,7 +1483,7 @@ public void Go () selectors [t] = tselectors.Distinct (); } - foreach (Type t in types) { + foreach (Type t in api.Types) { if (t.IsUnavailable (this)) continue; @@ -1781,7 +1779,7 @@ void GenerateLibraryHandles () // void GenerateStrongDictionaryTypes () { - foreach (var dictType in strong_dictionaries) { + foreach (var dictType in api.StrongDictionaries) { if (dictType.IsUnavailable (this)) continue; var sa = AttributeManager.GetCustomAttribute (dictType); @@ -4712,7 +4710,7 @@ IEnumerable SelectProtocolProperties (Type type, bool? @static = n // If a type comes from the assembly with the api definition we're processing. bool IsApiType (Type type) { - return type.Assembly == types [0].Assembly; + return type.Assembly == api.Types [0].Assembly; } bool IsRequired (MemberInfo provider, Attribute [] attributes = null) @@ -5511,7 +5509,7 @@ public void Generate (Type type) continue; string nonInterfaceName = protocolType.Name.Substring (1); - if (!types.Any (x => x.Name.Contains (nonInterfaceName))) + if (!api.Types.Any (x => x.Name.Contains (nonInterfaceName))) continue; if (is_category_class) @@ -6607,7 +6605,7 @@ public void Generate (Type type) // // Copy delegates from the API files into the output if they were declared there // - var rootAssembly = types [0].Assembly; + var rootAssembly = api.Types [0].Assembly; foreach (var deltype in trampolines.Keys.OrderBy (d => d.Name, StringComparer.Ordinal)) { if (deltype.Assembly != rootAssembly) continue; diff --git a/src/bgen/Models/Api.cs b/src/bgen/Models/Api.cs new file mode 100644 index 000000000000..55c6f2af0f34 --- /dev/null +++ b/src/bgen/Models/Api.cs @@ -0,0 +1,13 @@ +#nullable enable + +using System; +using System.Reflection; + +// contains all the types defined in the API to generate. This could have +// been a (Type [] Types, Type [] StrongDictionaries) but we have to keep +// backcompat before dotnet. records do work ;) +public record Api (Type [] Types, Type [] StrongDictionaries) { + + public Type [] Types { get; } = Types; + public Type [] StrongDictionaries { get; } = StrongDictionaries; +} diff --git a/src/bgen/TypeManager.cs b/src/bgen/TypeManager.cs index 5df70f68d5f2..849db79b4764 100644 --- a/src/bgen/TypeManager.cs +++ b/src/bgen/TypeManager.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Foundation; #nullable enable @@ -362,4 +363,28 @@ public bool IsDictionaryContainerType (Type t) { return t.IsSubclassOf (TypeCache.DictionaryContainerType) || (t.IsInterface && AttributeManager.HasAttribute (t)); } + + public Api ParseApi (Assembly api, bool processEnums) + { + var types = new List (); + var strongDictionaries = new List (); + + foreach (var t in api.GetTypes ()) { + if ((processEnums && t.IsEnum) || + AttributeManager.HasAttribute (t) || + AttributeManager.HasAttribute (t) || + AttributeManager.HasAttribute (t) || + AttributeManager.HasAttribute (t)) + // skip those types that are not available + types.Add (t); + if (AttributeManager.HasAttribute (t)) + strongDictionaries.Add (t); + } + + // we should sort the types based on the full name + var typesArray = types.ToArray (); + Array.Sort (typesArray, (a, b) => string.CompareOrdinal (a.FullName, b.FullName)); + + return new (typesArray, strongDictionaries.ToArray ()); + } } diff --git a/src/generator.csproj b/src/generator.csproj index b66d68afe265..1ea167b0d4ea 100644 --- a/src/generator.csproj +++ b/src/generator.csproj @@ -156,6 +156,7 @@ +