// A bit clumsy but better than full-blown reflection use or an open set of Create* methods for each // type we support now or in the future protected virtual T CreateHierarchyElement <T> (HierarchyBase parent) where T : HierarchyElement { Type type = typeof(T); HierarchyBase ret = null; if (type == typeof(HierarchyNamespace)) { ret = new HierarchyNamespace(Context, parent as Hierarchy); } else if (type == typeof(HierarchyClass)) { ret = new HierarchyClass(Context, parent as HierarchyNamespace); } else if (type == typeof(HierarchyImplements)) { ret = new HierarchyImplements(Context, parent as HierarchyObject); } else if (type == typeof(HierarchyMethod)) { ret = new HierarchyMethod(Context, parent as HierarchyObject); } else if (type == typeof(HierarchyConstructor)) { ret = new HierarchyConstructor(Context, parent as HierarchyObject); } else if (type == typeof(HierarchyException)) { ret = new HierarchyException(Context, parent as HierarchyMethod); } else if (type == typeof(HierarchyTypeParameter)) { ret = new HierarchyTypeParameter(Context, parent as HierarchyElement); } else if (type == typeof(HierarchyTypeParameterGenericConstraint)) { ret = new HierarchyTypeParameterGenericConstraint(Context, parent as HierarchyTypeParameter); } else if (type == typeof(HierarchyMethodParameter)) { ret = new HierarchyMethodParameter(Context, parent as HierarchyMethod); } else if (type == typeof(HierarchyField)) { ret = new HierarchyField(Context, parent as HierarchyObject); } else if (type == typeof(HierarchyInterface)) { ret = new HierarchyInterface(Context, parent as HierarchyNamespace); } else if (type == typeof(HierarchyEnum)) { ret = new HierarchyEnum(Context, parent as Hierarchy); } else { throw new InvalidOperationException($"Unsupported hierarchy element type {type}"); } return(ret as T); }
public HierarchyInterfaceInvoker(GeneratorContext context, HierarchyElement parent, HierarchyInterface invokedInterface) : base(context, parent) { InvokedInterface = invokedInterface ?? throw new ArgumentNullException(nameof(invokedInterface)); Visibility = ApiVisibility.Internal; }
protected abstract InterfaceCodeGenerator GetInterfaceGenerator(HierarchyInterface iface);
public abstract void AddMember(HierarchyInterface iface);
public void Build(IList <ApiElement> rawElements) { if (rawElements == null || rawElements.Count == 0) { throw new ArgumentException("must be a non-empty collection", nameof(rawElements)); } // Pass 1: build basic hierarchy (no class or interface nesting yet) Helpers.ForEachNotNull(rawElements, (ApiElement e) => { switch (e) { case ApiNameSpace ns: Process(ns); break; case ApiEnum enm: Process(enm); break; default: Logger.Warning($"Unsupported top-level element type: {e.GetType ().FullName}"); break; } }); HierarchyNamespace androidRuntime = namespaces?.Where(ns => String.Compare(DefaultInterfaceBaseTypeNamespace, ns?.FullName, StringComparison.OrdinalIgnoreCase) == 0).FirstOrDefault(); if (androidRuntime == null) { Logger.Verbose("Creating Android.Runtime namespace (not found after parsing API description)"); androidRuntime = CreateHierarchyElementInternal <HierarchyNamespace> (this); androidRuntime.Init(); androidRuntime.IgnoreForCodeGeneration = true; androidRuntime.FullName = DefaultInterfaceBaseTypeNamespace; androidRuntime.Name = Helpers.GetBaseTypeName(androidRuntime.FullName); androidRuntime.ManagedName = androidRuntime.Name; androidRuntime.FullManagedName = androidRuntime.FullName; Helpers.AddToList(androidRuntime, ref namespaces); } // IJavaObject is defined in Xamarin.Android's non-generated source and implmented by all // interfaces that don't derive from other interfaces HierarchyInterface iJavaLangObject = androidRuntime.Members?.OfType <HierarchyInterface> ().Where(iface => String.Compare(DefaultInterfaceBaseType, iface?.FullName, StringComparison.OrdinalIgnoreCase) == 0).FirstOrDefault(); if (iJavaLangObject == null) { Logger.Verbose("Synthesizing Android.Runtime.IJavaObject interface (not found after parsing API description)"); iJavaLangObject = CreateHierarchyElementInternal <HierarchyInterface> (androidRuntime); iJavaLangObject.Init(); iJavaLangObject.FullName = DefaultInterfaceBaseType; iJavaLangObject.Name = Helpers.GetBaseTypeName(iJavaLangObject.FullName); iJavaLangObject.IgnoreForCodeGeneration = true; iJavaLangObject.InvokerNotNeeded = true; iJavaLangObject.UseGlobal = true; TypeIndex.Add(iJavaLangObject); } // Pass 2: nest classes, interfaces NestNamespaces(); // Pass 3: generate managed names Helpers.ForEachNotNull(namespaces, (HierarchyNamespace ns) => GenerateManagedNames(ns)); // TODO: fix generation of full managed names for enums Helpers.ForEachNotNull(enums, (HierarchyEnum enm) => GenerateManagedNames(enm)); // Pass 4: nest enums (they need managed names) NestEnums(); // Pass 5: generate and inject synthetic elements SynthesizeElements(); // Pass 6: resolve base types since we have everything in place now ResolveBaseTypes(); // Pass 7: sort class members }