diff --git a/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApi.XmlModel.cs b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApi.XmlModel.cs index c6fc86961..26a7c99b2 100644 --- a/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApi.XmlModel.cs +++ b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApi.XmlModel.cs @@ -12,6 +12,8 @@ public JavaApi () Packages = new List (); } + partial void Initialize (); + public string ExtendedApiSource { get; set; } public IList Packages { get; set; } } @@ -25,6 +27,8 @@ public JavaPackage (JavaApi parent) Types = new List (); } + partial void Initialize (); + public JavaApi Parent { get; private set; } public string Name { get; set; } @@ -45,8 +49,12 @@ protected JavaType (JavaPackage parent) Implements = new List (); Members = new List (); + + Initialize (); } + partial void Initialize (); + public JavaPackage Parent { get; private set; } public bool IsReferenceOnly { get; set; } @@ -81,8 +89,11 @@ public partial class JavaInterface : JavaType public JavaInterface (JavaPackage parent) : base (parent) { + Initialize (); } + partial void Initialize (); + // Content of this value is not stable. public override string ToString () { @@ -97,6 +108,8 @@ public JavaClass (JavaPackage parent) { } + partial void Initialize (); + public string Extends { get; set; } public string ExtendsGeneric { get; set; } public string ExtendedJniExtends { get; set; } @@ -109,7 +122,7 @@ public override string ToString () } - class ManagedType : JavaType + partial class ManagedType : JavaType { static JavaPackage dummy_system_package, dummy_system_io_package, dummy_system_xml_package; static JavaType system_object, system_exception, system_io_stream, system_xml_xmlreader; @@ -139,7 +152,10 @@ public static IEnumerable DummyManagedPackages { public ManagedType (JavaPackage package) : base (package) { + Initialize (); } + + partial void Initialize (); } @@ -156,8 +172,11 @@ public partial class JavaMember protected JavaMember (JavaType parent) { Parent = parent; + Initialize (); } - + + partial void Initialize (); + public JavaType Parent { get; private set; } public string Deprecated { get; set; } @@ -172,8 +191,11 @@ public partial class JavaField : JavaMember public JavaField (JavaType parent) : base (parent) { + Initialize (); } + partial void Initialize (); + public bool Transient { get; set; } public string Type { get; set; } public string TypeGeneric { get; set; } @@ -194,8 +216,11 @@ protected JavaMethodBase (JavaType parent) { Parameters = new List (); Exceptions = new List (); + Initialize (); } + partial void Initialize (); + public IList Parameters { get; set; } public IList Exceptions { get; set; } @@ -223,8 +248,11 @@ public partial class JavaConstructor : JavaMethodBase public JavaConstructor (JavaType parent) : base (parent) { + Initialize (); } + partial void Initialize (); + // it was required in the original API XML, but removed in class-parsed... public string Type { get; set; } @@ -242,6 +270,8 @@ public JavaMethod (JavaType parent) { } + partial void Initialize (); + public bool Abstract { get; set; } public bool Native { get; set; } public string Return { get; set; } diff --git a/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApi.XmlModelExtensionObjects.cs b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApi.XmlModelExtensionObjects.cs new file mode 100644 index 000000000..5fa044d53 --- /dev/null +++ b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApi.XmlModelExtensionObjects.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Xamarin.Android.Tools.ApiXmlAdjuster +{ + public partial class JavaApi + { + public event Action NewExtensibleCreated; + public event Action ExistingExtensibleFoundOnLoad; + + public void OnNewExtensibleCreated (IJavaInfoItem item) + { + if (NewExtensibleCreated != null) + NewExtensibleCreated (item); + } + + public void OnExistingExtensibleFoundOnLoad (IJavaInfoItem existingItem) + { + if (ExistingExtensibleFoundOnLoad != null) + ExistingExtensibleFoundOnLoad (existingItem); + } + + Dictionary> extensions = new Dictionary> (); + + IList EnsureExtensionsListFor (IJavaInfoItem item) + { + IList l; + if (!extensions.TryGetValue (item, out l)) { + l = new List (); + extensions.Add (item, l); + } + return l; + } + + public T GetExtension (IJavaInfoItem item) + { + return EnsureExtensionsListFor (item).OfType ().FirstOrDefault (); + } + + public void SetExtension (IJavaInfoItem item, T value) + { + var l = EnsureExtensionsListFor (item); + var existing = l.OfType (); + if (existing is T) + l.Remove (existing); + l.Add (value); + } + } + + public partial interface IJavaInfoItem + { + JavaApi Api { get; } + } + + public static class IJavaInfoItemExtensions + { + public static T GetExtension (this IJavaInfoItem item) + { + return item.Api.GetExtension (item); + } + + public static IJavaInfoItem SetExtension (this IJavaInfoItem item, T value) + { + item.Api.SetExtension (item, value); + return item; + } + } + + public partial class JavaPackage : IJavaInfoItem + { + JavaApi IJavaInfoItem.Api { + get { + return Parent; + } + } + + partial void Initialize () + { + ((IJavaInfoItem) this).Api.OnNewExtensibleCreated (this); + } + } + + public abstract partial class JavaType : IJavaInfoItem + { + public JavaApi Api { + get { return Parent.Parent; } + } + + partial void Initialize () + { + ((IJavaInfoItem)this).Api.OnNewExtensibleCreated (this); + } + } + + public partial class JavaMember : IJavaInfoItem + { + public JavaApi Api { + get { return Parent.Parent.Parent; } + } + + partial void Initialize () + { + ((IJavaInfoItem)this).Api.OnNewExtensibleCreated (this); + } + } + + public class SourceIdentifier + { + public SourceIdentifier (string sourceUri) + { + SourceUri = sourceUri; + } + + public string SourceUri { get; set; } + } +} diff --git a/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApiXmlLoaderExtensions.cs b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApiXmlLoaderExtensions.cs index 69d78b4e0..058831e8d 100644 --- a/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApiXmlLoaderExtensions.cs +++ b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApiXmlLoaderExtensions.cs @@ -32,10 +32,10 @@ public static void Load (this JavaApi api, XmlReader reader, bool isReferenceOnl if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "package") throw XmlUtil.UnexpectedElementOrContent ("api", reader, "package"); var pkg = api.Packages.FirstOrDefault (p => p.Name == reader.GetAttribute ("name")); - if (pkg == null) { - pkg = new JavaPackage (api); - api.Packages.Add (pkg); - } + if (pkg != null) + api.OnExistingExtensibleFoundOnLoad (pkg); + else + api.Packages.Add (pkg = new JavaPackage (api)); pkg.Load (reader, isReferenceOnly); } while (true); @@ -58,20 +58,36 @@ public static void Load (this JavaPackage package, XmlReader reader, bool isRefe reader.Read (); do { reader.MoveToContent (); + Func create = null; if (reader.NodeType == XmlNodeType.EndElement) break; // if (reader.NodeType != XmlNodeType.Element) throw XmlUtil.UnexpectedElementOrContent ("package", reader, "class", "interface"); - if (reader.LocalName == "class") { - var kls = new JavaClass (package) { IsReferenceOnly = isReferenceOnly }; - kls.Load (reader); - package.Types.Add (kls); - } else if (reader.LocalName == "interface") { - var iface = new JavaInterface (package) { IsReferenceOnly = isReferenceOnly }; - iface.Load (reader); - package.Types.Add (iface); - } else + + var type = package.Types.FirstOrDefault (arg => arg.Name == reader.GetAttribute ("name")); + + if (reader.LocalName == "class") + create = () => type = new JavaClass (package) { IsReferenceOnly = isReferenceOnly }; + else if (reader.LocalName == "interface") + create = () => type = new JavaInterface (package) { IsReferenceOnly = isReferenceOnly }; + else throw XmlUtil.UnexpectedElementOrContent ("package", reader, "class", "interface"); + + if (type != null) + package.Parent.OnExistingExtensibleFoundOnLoad (type); + else + package.Types.Add (type = create ()); + if (type is JavaClass) { + if (reader.LocalName != "class") + reader.Skip (); + else + ((JavaClass) type).Load (reader); + } else { + if (reader.LocalName != "interface") + reader.Skip (); + else + ((JavaInterface) type).Load (reader); + } } while (true); XmlUtil.VerifyEndElement (reader, "package"); diff --git a/src/Xamarin.Android.Tools.ApiXmlAdjuster/Xamarin.Android.Tools.ApiXmlAdjuster.csproj b/src/Xamarin.Android.Tools.ApiXmlAdjuster/Xamarin.Android.Tools.ApiXmlAdjuster.csproj index ce1e01293..7ed712366 100644 --- a/src/Xamarin.Android.Tools.ApiXmlAdjuster/Xamarin.Android.Tools.ApiXmlAdjuster.csproj +++ b/src/Xamarin.Android.Tools.ApiXmlAdjuster/Xamarin.Android.Tools.ApiXmlAdjuster.csproj @@ -50,6 +50,7 @@ + diff --git a/src/Xamarin.Android.Tools.ApiXmlAdjuster/XmlUtil.cs b/src/Xamarin.Android.Tools.ApiXmlAdjuster/XmlUtil.cs index b829b461a..a4774bcd6 100644 --- a/src/Xamarin.Android.Tools.ApiXmlAdjuster/XmlUtil.cs +++ b/src/Xamarin.Android.Tools.ApiXmlAdjuster/XmlUtil.cs @@ -11,7 +11,9 @@ class XmlUtil static string GetLocation (XmlReader reader) { var li = reader as IXmlLineInfo; - return string.Format ("{0} ({1},{2})", new Uri (reader.BaseURI).LocalPath, li.LineNumber, li.LinePosition); + Uri uri; + // Uri.TryCreate() with UriKind.RelativeOrAbsolute results in "relative Uri not supported" !? + return string.Format ("{0} ({1},{2})", Uri.TryCreate (reader.BaseURI, UriKind.Absolute, out uri) ? uri.LocalPath : string.Empty, li.LineNumber, li.LinePosition); } public static Exception UnexpectedElementOrContent (string elementName, XmlReader reader, params string [] expected)