Skip to content

ONGOING / [api-xml-adjuster] add external extensibility feature and "source identifier #110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApi.XmlModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public JavaApi ()
Packages = new List<JavaPackage> ();
}

partial void Initialize ();

public string ExtendedApiSource { get; set; }
public IList<JavaPackage> Packages { get; set; }
}
Expand All @@ -25,6 +27,8 @@ public JavaPackage (JavaApi parent)
Types = new List<JavaType> ();
}

partial void Initialize ();

public JavaApi Parent { get; private set; }

public string Name { get; set; }
Expand All @@ -45,8 +49,12 @@ protected JavaType (JavaPackage parent)

Implements = new List<JavaImplements> ();
Members = new List<JavaMember> ();

Initialize ();
}

partial void Initialize ();

public JavaPackage Parent { get; private set; }

public bool IsReferenceOnly { get; set; }
Expand Down Expand Up @@ -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 ()
{
Expand All @@ -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; }
Expand All @@ -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;
Expand Down Expand Up @@ -139,7 +152,10 @@ public static IEnumerable<JavaPackage> DummyManagedPackages {

public ManagedType (JavaPackage package) : base (package)
{
Initialize ();
}

partial void Initialize ();
}


Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -194,8 +216,11 @@ protected JavaMethodBase (JavaType parent)
{
Parameters = new List<JavaParameter> ();
Exceptions = new List<JavaException> ();
Initialize ();
}

partial void Initialize ();

public IList<JavaParameter> Parameters { get; set; }
public IList<JavaException> Exceptions { get; set; }

Expand Down Expand Up @@ -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; }

Expand All @@ -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; }
Expand Down
Original file line number Diff line number Diff line change
@@ -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<IJavaInfoItem> NewExtensibleCreated;
public event Action<IJavaInfoItem> ExistingExtensibleFoundOnLoad;

public void OnNewExtensibleCreated (IJavaInfoItem item)
{
if (NewExtensibleCreated != null)
NewExtensibleCreated (item);
}

public void OnExistingExtensibleFoundOnLoad (IJavaInfoItem existingItem)
{
if (ExistingExtensibleFoundOnLoad != null)
ExistingExtensibleFoundOnLoad (existingItem);
}

Dictionary<IJavaInfoItem, IList<object>> extensions = new Dictionary<IJavaInfoItem, IList<object>> ();

IList<object> EnsureExtensionsListFor (IJavaInfoItem item)
{
IList<object> l;
if (!extensions.TryGetValue (item, out l)) {
l = new List<object> ();
extensions.Add (item, l);
}
return l;
}

public T GetExtension<T> (IJavaInfoItem item)
{
return EnsureExtensionsListFor (item).OfType<T> ().FirstOrDefault ();
}

public void SetExtension<T> (IJavaInfoItem item, T value)
{
var l = EnsureExtensionsListFor (item);
var existing = l.OfType<T> ();
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<T> (this IJavaInfoItem item)
{
return item.Api.GetExtension<T> (item);
}

public static IJavaInfoItem SetExtension<T> (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; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -58,20 +58,36 @@ public static void Load (this JavaPackage package, XmlReader reader, bool isRefe
reader.Read ();
do {
reader.MoveToContent ();
Func<JavaType> create = null;
if (reader.NodeType == XmlNodeType.EndElement)
break; // </package>
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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<Compile Include="JavaTypeResolutionUtil.cs" />
<Compile Include="JavaApiFixVisibilityExtensions.cs" />
<Compile Include="Log.cs" />
<Compile Include="JavaApi.XmlModelExtensionObjects.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
4 changes: 3 additions & 1 deletion src/Xamarin.Android.Tools.ApiXmlAdjuster/XmlUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down