From fe9009a9f7cde70972bcd68e0953319e89b99ff3 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Tue, 6 Jun 2017 13:17:09 +0900 Subject: [PATCH 1/2] [generator] report warning/error location within XML metadata fixup. --- tools/generator/ApiFixup.cs | 26 +++++++------- tools/generator/Report.cs | 72 ++++++++++++++++++++++++++++++++----- 2 files changed, 76 insertions(+), 22 deletions(-) diff --git a/tools/generator/ApiFixup.cs b/tools/generator/ApiFixup.cs index 54081c572..e8d52c026 100644 --- a/tools/generator/ApiFixup.cs +++ b/tools/generator/ApiFixup.cs @@ -91,10 +91,10 @@ void Process (XmlDocument meta_doc, string apiLevelString, int productVersion) api_node.ParentNode.RemoveChild (api_node); if (matches.Count == 0) // BG8A00 - Report.Warning (0, Report.WarningApiFixup + 0, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 0, null, metanav, " matched no nodes.", path); } catch (XPathException e) { // BG4A01 - Report.Error (Report.ErrorApiFixup + 1, e, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 1, e, metanav, "Invalid XPath specification: {0}", path); } break; case "add-node": @@ -109,10 +109,10 @@ void Process (XmlDocument meta_doc, string apiLevelString, int productVersion) } if (!matched) // BG8A01 - Report.Warning (0, Report.WarningApiFixup + 1, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 1, null, metanav, " matched no nodes.", path); } catch (XPathException e) { // BG4A02 - Report.Error (Report.ErrorApiFixup + 2, e, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 2, e, metanav, "Invalid XPath specification: {0}", path); } break; case "change-node": @@ -135,10 +135,10 @@ void Process (XmlDocument meta_doc, string apiLevelString, int productVersion) if (!matched) // BG8A03 - Report.Warning (0, Report.WarningApiFixup + 3, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 3, null, metanav, " matched no nodes.", path); } catch (XPathException e) { // BG4A03 - Report.Error (Report.ErrorApiFixup + 3, e, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 3, e, metanav, "Invalid XPath specification: {0}", path); } break; case "attr": @@ -146,7 +146,7 @@ void Process (XmlDocument meta_doc, string apiLevelString, int productVersion) string attr_name = metanav.XGetAttribute ("name", ""); if (string.IsNullOrEmpty (attr_name)) // BG4A07 - Report.Error (Report.ErrorApiFixup + 7, "Target attribute name is not specified for path: {0}", path); + Report.Error (Report.ErrorApiFixup + 7, null, metanav, "Target attribute name is not specified for path: {0}", path); var nodes = attr_last_cache != null ? (IEnumerable) new XPathNavigator [] {attr_last_cache} : api_nav.Select (path).OfType (); @@ -159,12 +159,12 @@ void Process (XmlDocument meta_doc, string apiLevelString, int productVersion) } if (attr_matched == 0) // BG8A04 - Report.Warning (0, Report.WarningApiFixup + 4, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 4, null, metanav, " matched no nodes.", path); if (attr_matched != 1) attr_last_cache = null; } catch (XPathException e) { // BG4A04 - Report.Error (Report.ErrorApiFixup + 4, e, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 4, e, metanav, "Invalid XPath specification: {0}", path); } break; case "move-node": @@ -185,10 +185,10 @@ void Process (XmlDocument meta_doc, string apiLevelString, int productVersion) } if (!matched) // BG8A05 - Report.Warning (0, Report.WarningApiFixup + 5, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 5, null, metanav, " matched no nodes.", path); } catch (XPathException e) { // BG4A05 - Report.Error (Report.ErrorApiFixup + 5, e, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 5, e, metanav, "Invalid XPath specification: {0}", path); } break; case "remove-attr": @@ -206,10 +206,10 @@ void Process (XmlDocument meta_doc, string apiLevelString, int productVersion) if (!matched) // BG8A06 - Report.Warning (0, Report.WarningApiFixup + 6, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 6, null, metanav, " matched no nodes.", path); } catch (XPathException e) { // BG4A06 - Report.Error (Report.ErrorApiFixup + 6, e, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 6, e, metanav, "Invalid XPath specification: {0}", path); } break; } diff --git a/tools/generator/Report.cs b/tools/generator/Report.cs index f3cce8d98..76b62280d 100644 --- a/tools/generator/Report.cs +++ b/tools/generator/Report.cs @@ -1,5 +1,7 @@ using System; using System.Linq; +using System.Xml; +using System.Xml.XPath; namespace MonoDroid.Generation { @@ -31,25 +33,67 @@ public class Report public static void Error (int errorCode, string format, params object[] args) { - Error (errorCode, null, format, args); + Error (errorCode, null, null, -1, -1, format, args); } - - public static void Error (int errorCode, Exception innerException, string format, params object[] args) + + public static void Error (int errorCode, string sourceFile, int line, int column, string format, params object [] args) { - throw new BindingGeneratorException (errorCode, string.Format (format, args), innerException); + Error (errorCode, null, sourceFile, line, column, format, args); + } + + public static void Error (int errorCode, Exception innerException, string format, params object [] args) + { + Error (errorCode, innerException, null, -1, -1, format, args); + } + + public static void Error (int errorCode, Exception innerException, XPathNavigator nav, string format, params object [] args) + { + var hn = nav as IHasXmlNode; + var baseUri = hn != null ? hn.GetNode ().OwnerDocument.BaseURI : nav.BaseURI; + Uri uri; + string file = Uri.TryCreate (baseUri, UriKind.Absolute, out uri) ? uri.LocalPath : null; + IXmlLineInfo li = nav as IXmlLineInfo; + li = li != null && li.HasLineInfo () ? li : null; + Error (errorCode, innerException, file, li != null ? li.LineNumber : -1, li != null ? li.LinePosition : -1, format, args); + } + + public static void Error (int errorCode, Exception innerException, string sourceFile, int line, int column, string format, params object[] args) + { + throw new BindingGeneratorException (errorCode, sourceFile, line, column, string.Format (format, args), innerException); } public static void Warning (int verbosity, int errorCode, string format, params object[] args) { Warning (verbosity, errorCode, null, format, args); } + + public static void Warning (int verbosity, int errorCode, Exception innerException, XPathNavigator nav, string format, params object [] args) + { + var hn = nav as IHasXmlNode; + var baseUri = hn != null ? hn.GetNode ().OwnerDocument.BaseURI : nav.BaseURI; + Uri uri; + string file = Uri.TryCreate (baseUri, UriKind.Absolute, out uri) ? uri.LocalPath : null; + IXmlLineInfo li = nav as IXmlLineInfo; + li = li != null && li.HasLineInfo () ? li : null; + Warning (verbosity, errorCode, innerException, file, li != null ? li.LineNumber : -1, li != null ? li.LinePosition : -1, format, args); + } + + public static void Warning (int verbosity, int errorCode, string sourceFile, int line, int column, string format, params object[] args) + { + Warning (verbosity, errorCode, null, sourceFile, line, column, format, args); + } + + public static void Warning (int verbosity, int errorCode, Exception innerException, string format, params object [] args) + { + Warning (verbosity, errorCode, innerException, null, -1, -1, format, args); + } - public static void Warning (int verbosity, int errorCode, Exception innerException, string format, params object[] args) + public static void Warning (int verbosity, int errorCode, Exception innerException, string sourceFile, int line, int column, string format, params object[] args) { if (verbosity > (Verbosity ?? 0)) return; string supp = innerException != null ? " For details, see verbose output." : null; - Console.Error.WriteLine (Format (false, errorCode, format, args) + supp); + Console.Error.WriteLine (Format (false, errorCode, sourceFile, line, column, format, args) + supp); if (innerException != null) Console.Error.WriteLine (innerException); } @@ -60,10 +104,16 @@ public static void Verbose (int verbosity, string format, params object[] args) return; Console.Error.WriteLine (format, args); } + + public static string Format (bool error, int errorCode, string format, params object [] args) + { + return Format (error, errorCode, null, -1, -1, format, args); + } - public static string Format (bool error, int errorCode, string format, params object[] args) + public static string Format (bool error, int errorCode, string sourceFile, int line, int column, string format, params object[] args) { - return string.Format ("{0}{1} BG{2:X04}: ", "" /* origin? */, error ? "error" : "warning", errorCode) + + var origin = sourceFile != null ? sourceFile + (line > 0 ? column > 0 ? $"({line}, {column})" : $"({line})" : null) + ' ' : null; + return string.Format ("{0}{1} BG{2:X04}: ", origin, error ? "error" : "warning", errorCode) + string.Format (format, args); } } @@ -75,7 +125,11 @@ public BindingGeneratorException (int errorCode, string message) { } public BindingGeneratorException (int errorCode, string message, Exception innerException) - : base (Report.Format (true, errorCode, message), innerException) + : this (errorCode, null, -1, -1, message, innerException) + { + } + public BindingGeneratorException (int errorCode, string sourceFile, int line, int column, string message, Exception innerException) + : base (Report.Format (true, errorCode, sourceFile, line, column, message), innerException) { } } From 2961a06475534cf8ab2c79452586d07336e18b2d Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Tue, 6 Jun 2017 16:09:12 +0900 Subject: [PATCH 2/2] [generator] Replace XmlDocument with XLinq and report error location. XmlDocument never supported source locations, therefore it was impossible to report exact error location in metadata fixup (which was quite annoying). What were alternatives? - XPathDocument: it is no-go because it is not editable. ApiFixup step requires modifications on the API description XML tree. - XPathNavigator on XLinq: it seemed doable, because XLinq is for modifying XML tree, and it can create XPathNavigator from XNode. What actually happens, however, was that their XPathNavigator does not support CreateAttributes(), which was required for operation. Another attempt to work around by set_OuterXml() failed because it also does not support ReplaceRange() which was internally used by OuterXml. Therefore, I ended up to entirely replace XmlDocument with XLinq. It was not limited to ApiFixup but also *everywhere* in generator, because the API descriptions are also the XPath query targets. --- src/utils/EnumMappings.Xml.cs | 24 +-- src/utils/XmlExtensions.cs | 7 +- tools/generator/ApiFixup.cs | 149 ++++++++---------- tools/generator/ClassGen.cs | 18 +-- tools/generator/Ctor.cs | 36 +++-- tools/generator/EnumMappings.cs | 15 +- tools/generator/Field.cs | 11 +- tools/generator/GenBaseSupport.cs | 13 +- tools/generator/GenericParameterDefinition.cs | 10 +- tools/generator/InterfaceGen.cs | 17 +- tools/generator/Method.cs | 39 ++--- tools/generator/MethodBase.cs | 9 +- tools/generator/Parameter.cs | 13 +- tools/generator/Parser.cs | 39 ++--- tools/generator/Report.cs | 17 +- 15 files changed, 190 insertions(+), 227 deletions(-) diff --git a/src/utils/EnumMappings.Xml.cs b/src/utils/EnumMappings.Xml.cs index 975b498ad..dc13f361c 100644 --- a/src/utils/EnumMappings.Xml.cs +++ b/src/utils/EnumMappings.Xml.cs @@ -2,7 +2,8 @@ using System.IO; using System.Linq; using System.Xml; - +using System.Xml.Linq; +using System.Xml.XPath; using Xamarin.Android.Tools; namespace MonoDroid.Generation { @@ -23,19 +24,18 @@ internal static TextReader FieldXmlToCsv (string file) return null; var sw = new StringWriter (); - var doc = new XmlDocument (); - doc.Load (file); + var doc = XDocument.Load (file, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo); - foreach (XmlElement e in doc.SelectNodes ("/enum-field-mappings/mapping")) { + foreach (var e in doc.XPathSelectElements ("/enum-field-mappings/mapping")) { string enu = GetMandatoryAttribute (e, "clr-enum-type"); - string jni_type = e.HasAttribute ("jni-class") + string jni_type = e.Attribute ("jni-class") != null ? e.XGetAttribute ("jni-class") - : e.HasAttribute ("jni-interface") + : e.Attribute ("jni-interface") != null ? "I:" + e.XGetAttribute ("jni-interface") : GetMandatoryAttribute (e, "jni-class or jni-interface"); - bool bitfield = e.HasAttribute ("bitfield") && e.XGetAttribute ("bitfield") == "true"; - foreach (XmlElement m in e.SelectNodes ("field")) { - string verstr = m.HasAttribute ("api-level") + bool bitfield = e.Attribute ("bitfield") != null && e.XGetAttribute ("bitfield") == "true"; + foreach (var m in e.XPathSelectElements ("field")) { + string verstr = m.Attribute ("api-level") != null ? m.XGetAttribute ("api-level") : "0"; string member = GetMandatoryAttribute (m, "clr-name"); @@ -48,10 +48,10 @@ internal static TextReader FieldXmlToCsv (string file) return new StringReader (sw.ToString ()); } - static string GetMandatoryAttribute (XmlElement e, string name) + static string GetMandatoryAttribute (XElement e, string name) { - if (!e.HasAttribute (name)) { - throw new InvalidOperationException (String.Format ("Mandatory attribute '{0}' is missing on a mapping element: {1}", name, e.OuterXml)); + if (e.Attribute (name) == null) { + throw new InvalidOperationException (String.Format ("Mandatory attribute '{0}' is missing on a mapping element: {1}", name, e.ToString ())); } return e.XGetAttribute (name); } diff --git a/src/utils/XmlExtensions.cs b/src/utils/XmlExtensions.cs index 4a1d1477b..6a8d4b2ef 100644 --- a/src/utils/XmlExtensions.cs +++ b/src/utils/XmlExtensions.cs @@ -2,16 +2,17 @@ using System.IO; using System.Linq; using System.Xml; +using System.Xml.Linq; using System.Xml.XPath; namespace Xamarin.Android.Tools { static class XmlExtensions { - public static string XGetAttribute (this XmlElement element, string name) + public static string XGetAttribute (this XElement element, string name) { - var attr = element.GetAttribute (name); - return attr != null ? attr.Trim () : null; + var attr = element.Attribute (name); + return attr != null ? attr.Value.Trim () : null; } public static string XGetAttribute (this XPathNavigator nav, string name, string ns) diff --git a/tools/generator/ApiFixup.cs b/tools/generator/ApiFixup.cs index e8d52c026..c89c72752 100644 --- a/tools/generator/ApiFixup.cs +++ b/tools/generator/ApiFixup.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Xml; using System.Xml.XPath; +using System.Xml.Linq; using Xamarin.Android.Tools; @@ -10,47 +11,47 @@ namespace MonoDroid.Generation { public class ApiFixup { - XmlDocument api_doc; + XDocument api_doc; string apiSource = ""; public string ApiSource { get { return apiSource; } } - public ApiFixup (XmlDocument apiDoc) + public ApiFixup (XDocument apiDoc) { api_doc = apiDoc; - var api = api_doc.DocumentElement; + var api = api_doc.Root; if (api != null) apiSource = api.XGetAttribute ("api-source"); } - public void Process (IEnumerable metaDocs, string apiLevel, int productVersion) + public void Process (IEnumerable metaDocs, string apiLevel, int productVersion) { foreach (var metaDoc in metaDocs) Process (metaDoc, apiLevel, productVersion); } - bool ShouldSkip (XPathNavigator node, int apiLevel, int productVersion) + bool ShouldSkip (XElement node, int apiLevel, int productVersion) { if (apiLevel > 0) { - string apiSince = node.XGetAttribute ("api-since", ""); - string apiUntil = node.XGetAttribute ("api-until", ""); + string apiSince = node.XGetAttribute ("api-since"); + string apiUntil = node.XGetAttribute ("api-until"); if (!string.IsNullOrEmpty (apiSince) && int.Parse (apiSince) > apiLevel) return true; if (!string.IsNullOrEmpty (apiUntil) && int.Parse (apiUntil) < apiLevel) return true; } if (productVersion > 0) { - var product_version = node.XGetAttribute ("product-version", ""); + var product_version = node.XGetAttribute ("product-version"); if (!string.IsNullOrEmpty (product_version) && int.Parse (product_version) > productVersion) return true; } return false; } - bool ShouldApply (XPathNavigator node) + bool ShouldApply (XElement node) { if (!string.IsNullOrEmpty (apiSource)) { - var targetsource = node.XGetAttribute ("api-source", ""); + var targetsource = node.XGetAttribute ("api-source"); if (string.IsNullOrEmpty (targetsource)) return true; return targetsource == apiSource; @@ -58,158 +59,136 @@ bool ShouldApply (XPathNavigator node) return true; } - void Process (XmlDocument meta_doc, string apiLevelString, int productVersion) + void Process (XDocument meta_doc, string apiLevelString, int productVersion) { - XPathNavigator api_nav = api_doc.CreateNavigator (); - XPathNavigator meta_nav = meta_doc.CreateNavigator (); int apiLevel = 0; int.TryParse (apiLevelString, out apiLevel); - XPathNodeIterator metadata = meta_nav.Select ("/metadata/*"); + var metadataChildren = meta_doc.XPathSelectElements ("/metadata/*"); string prev_path = null; - XPathNavigator attr_last_cache = null; + XElement attr_last_cache = null; - while (metadata.MoveNext ()) { - var metanav = metadata.Current; - if (ShouldSkip (metanav, apiLevel, productVersion)) + foreach (var metaitem in metadataChildren) { + if (ShouldSkip (metaitem, apiLevel, productVersion)) continue; - if (!ShouldApply (metanav)) + if (!ShouldApply (metaitem)) continue; - string path = metanav.XGetAttribute ("path", ""); + string path = metaitem.XGetAttribute ("path"); if (path != prev_path) attr_last_cache = null; prev_path = path; - switch (metanav.LocalName) { + switch (metaitem.Name.LocalName) { case "remove-node": try { - XPathNodeIterator api_iter = api_nav.Select (path); - List matches = new List (); - while (api_iter.MoveNext ()) - matches.Add (((IHasXmlNode)api_iter.Current).GetNode () as XmlElement); - foreach (XmlElement api_node in matches) - api_node.ParentNode.RemoveChild (api_node); - if (matches.Count == 0) + var nodes = api_doc.XPathSelectElements (path).ToArray (); + if (nodes.Any ()) + foreach (var node in nodes) + node.Remove (); + else // BG8A00 - Report.Warning (0, Report.WarningApiFixup + 0, null, metanav, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 0, null, metaitem, " matched no nodes.", path); } catch (XPathException e) { // BG4A01 - Report.Error (Report.ErrorApiFixup + 1, e, metanav, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 1, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "add-node": try { - XPathNodeIterator api_iter = api_nav.Select (path); + var nodes = api_doc.XPathSelectElements (path); bool matched = false; - while (api_iter.MoveNext ()) { - XmlElement api_node = ((IHasXmlNode)api_iter.Current).GetNode () as XmlElement; - foreach (XmlNode child in ((IHasXmlNode)metanav).GetNode().ChildNodes) - api_node.AppendChild (api_doc.ImportNode (child, true)); + if (!nodes.Any ()) + // BG8A01 + Report.Warning (0, Report.WarningApiFixup + 1, null, metaitem, " matched no nodes.", path); + else { + foreach (var node in nodes) + node.Add (metaitem.Nodes ()); matched = true; } - if (!matched) - // BG8A01 - Report.Warning (0, Report.WarningApiFixup + 1, null, metanav, " matched no nodes.", path); } catch (XPathException e) { // BG4A02 - Report.Error (Report.ErrorApiFixup + 2, e, metanav, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 2, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "change-node": try { - XPathNodeIterator api_iter = api_nav.Select (path); + var nodes = api_doc.XPathSelectElements (path); bool matched = false; - while (api_iter.MoveNext ()) { - XmlElement node = ( (IHasXmlNode) api_iter.Current).GetNode () as XmlElement; - XmlElement parent = node.ParentNode as XmlElement; - XmlElement new_node = api_doc.CreateElement (metanav.Value); - - foreach (XmlNode child in node.ChildNodes) - new_node.AppendChild (child.Clone ()); - foreach (XmlAttribute attribute in node.Attributes) - new_node.Attributes.Append ( (XmlAttribute) attribute.Clone ()); - - parent.ReplaceChild (new_node, node); + foreach (var node in nodes) { + var newChild = new XElement (metaitem.Value); + newChild.Add (node.Attributes ()); + newChild.Add (node.Nodes ()); + node.ReplaceWith (newChild); matched = true; } if (!matched) // BG8A03 - Report.Warning (0, Report.WarningApiFixup + 3, null, metanav, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 3, null, metaitem, " matched no nodes.", path); } catch (XPathException e) { // BG4A03 - Report.Error (Report.ErrorApiFixup + 3, e, metanav, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 3, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "attr": try { - string attr_name = metanav.XGetAttribute ("name", ""); + string attr_name = metaitem.XGetAttribute ("name"); if (string.IsNullOrEmpty (attr_name)) // BG4A07 - Report.Error (Report.ErrorApiFixup + 7, null, metanav, "Target attribute name is not specified for path: {0}", path); - var nodes = attr_last_cache != null ? - (IEnumerable) new XPathNavigator [] {attr_last_cache} : - api_nav.Select (path).OfType (); + Report.Error (Report.ErrorApiFixup + 7, null, metaitem, "Target attribute name is not specified for path: {0}", path); + var nodes = attr_last_cache != null ? new XElement [] { attr_last_cache } : api_doc.XPathSelectElements (path); int attr_matched = 0; foreach (var n in nodes) { - XmlElement node = ((IHasXmlNode) n).GetNode () as XmlElement; - node.SetAttribute (attr_name, metanav.Value); - //attr_last_cache = n; + n.SetAttributeValue (attr_name, metaitem.Value); attr_matched++; } if (attr_matched == 0) // BG8A04 - Report.Warning (0, Report.WarningApiFixup + 4, null, metanav, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 4, null, metaitem, " matched no nodes.", path); if (attr_matched != 1) attr_last_cache = null; } catch (XPathException e) { // BG4A04 - Report.Error (Report.ErrorApiFixup + 4, e, metanav, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 4, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "move-node": try { - XPathExpression expr = api_nav.Compile (path); - string parent = metanav.Value; - XPathNodeIterator parent_iter = api_nav.Select (parent); + string parent = metaitem.Value; + var parents = api_doc.XPathSelectElements (parent); bool matched = false; - while (parent_iter.MoveNext ()) { - XmlNode parent_node = ((IHasXmlNode)parent_iter.Current).GetNode (); - XPathNodeIterator path_iter = parent_iter.Current.Clone ().Select (expr); - while (path_iter.MoveNext ()) { - XmlNode node = ((IHasXmlNode)path_iter.Current).GetNode (); - parent_node.AppendChild (node.Clone ()); - node.ParentNode.RemoveChild (node); - } + foreach (var parent_node in parents) { + var nodes = parent_node.XPathSelectElements (path).ToArray (); + foreach (var node in nodes) + node.Remove (); + parent_node.Add (nodes); matched = true; } if (!matched) // BG8A05 - Report.Warning (0, Report.WarningApiFixup + 5, null, metanav, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 5, null, metaitem, " matched no nodes.", path); } catch (XPathException e) { // BG4A05 - Report.Error (Report.ErrorApiFixup + 5, e, metanav, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 5, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "remove-attr": try { - string name = metanav.XGetAttribute ("name", ""); - XPathNodeIterator api_iter = api_nav.Select (path); + string name = metaitem.XGetAttribute ("name"); + var nodes = api_doc.XPathSelectElements (path); bool matched = false; - - while (api_iter.MoveNext ()) { - XmlElement node = ( (IHasXmlNode) api_iter.Current).GetNode () as XmlElement; - - node.RemoveAttribute (name); + + foreach (var node in nodes) { + node.RemoveAttributes (); matched = true; } if (!matched) // BG8A06 - Report.Warning (0, Report.WarningApiFixup + 6, null, metanav, " matched no nodes.", path); + Report.Warning (0, Report.WarningApiFixup + 6, null, metaitem, " matched no nodes.", path); } catch (XPathException e) { // BG4A06 - Report.Error (Report.ErrorApiFixup + 6, e, metanav, "Invalid XPath specification: {0}", path); + Report.Error (Report.ErrorApiFixup + 6, e, metaitem, "Invalid XPath specification: {0}", path); } break; } diff --git a/tools/generator/ClassGen.cs b/tools/generator/ClassGen.cs index d71f58949..3fc23fb09 100644 --- a/tools/generator/ClassGen.cs +++ b/tools/generator/ClassGen.cs @@ -12,6 +12,7 @@ using Xamarin.Android.Tools; using MonoDroid.Utils; +using System.Xml.Linq; namespace MonoDroid.Generation { #if USE_CECIL @@ -75,26 +76,23 @@ public class XmlClassGen : ClassGen { bool is_final; string base_type; - public XmlClassGen (XmlElement pkg, XmlElement elem) + public XmlClassGen (XElement pkg, XElement elem) : base (new XmlGenBaseSupport (pkg, elem))//FIXME: should not be xml specific { is_abstract = elem.XGetAttribute ("abstract") == "true"; is_final = elem.XGetAttribute ("final") == "true"; base_type = elem.XGetAttribute ("extends"); - foreach (XmlNode node in elem.ChildNodes) { - XmlElement child = node as XmlElement; - if (child == null) - continue; - switch (node.Name) { + foreach (var child in elem.Elements ()) { + switch (child.Name.LocalName) { case "implements": string iname = child.XGetAttribute ("name-generic-aware"); iname = iname.Length > 0 ? iname : child.XGetAttribute ("name"); AddInterface (iname); break; case "method": - var synthetic = child.GetAttribute ("synthetic") == "true"; - var finalizer = child.GetAttribute ("name") == "finalize" && - child.GetAttribute ("jni-signature") == "()V"; + var synthetic = child.XGetAttribute ("synthetic") == "true"; + var finalizer = child.XGetAttribute ("name") == "finalize" && + child.XGetAttribute ("jni-signature") == "()V"; if (!(synthetic || finalizer)) AddMethod (new XmlMethod (this, child)); break; @@ -107,7 +105,7 @@ public XmlClassGen (XmlElement pkg, XmlElement elem) case "typeParameters": break; // handled at GenBaseSupport default: - Report.Warning (0, Report.WarningClassGen + 1, "unexpected class child {0}.", node.Name); + Report.Warning (0, Report.WarningClassGen + 1, "unexpected class child {0}.", child.Name); break; } } diff --git a/tools/generator/Ctor.cs b/tools/generator/Ctor.cs index 8b5534499..092ef0d23 100644 --- a/tools/generator/Ctor.cs +++ b/tools/generator/Ctor.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using System.Xml; +using System.Xml.Linq; using Mono.Cecil; using Xamarin.Android.Tools; @@ -60,7 +61,7 @@ public class XmlCtor : Ctor { bool missing_enclosing_class; string custom_attributes; - public XmlCtor (GenBase declaringType, XmlElement elem) : base (declaringType, new XmlMethodBaseSupport (elem)) + public XmlCtor (GenBase declaringType, XElement elem) : base (declaringType, new XmlMethodBaseSupport (elem)) { name = elem.XGetAttribute ("name"); int idx = name.LastIndexOf ('.'); @@ -69,11 +70,11 @@ public class XmlCtor : Ctor { // If 'elem' is a constructor for a non-static nested type, then // the type of the containing class must be inserted as the first // argument - nonStaticNestedType = idx > 0 && elem.ParentNode.Attributes ["static"].Value == "false"; + nonStaticNestedType = idx > 0 && elem.Parent.Attribute ("static").Value == "false"; if (nonStaticNestedType) { - string declName = elem.ParentNode.Attributes ["name"].Value; + string declName = elem.Parent.XGetAttribute ("name"); string expectedEnclosingName = declName.Substring (0, idx); - XmlElement enclosingType = GetPreviousClass (elem.ParentNode.PreviousSibling, expectedEnclosingName); + XElement enclosingType = GetPreviousClass (elem.Parent.PreviousNode, expectedEnclosingName); if (enclosingType == null) { missing_enclosing_class = true; Report.Warning (0, Report.WarningCtor + 0, "For {0}, could not find enclosing type '{1}'.", name, expectedEnclosingName); @@ -82,26 +83,27 @@ public class XmlCtor : Ctor { Parameters.AddFirst (Parameter.FromClassElement (enclosingType)); } - foreach (XmlNode child in elem.ChildNodes) { + foreach (var child in elem.Elements ()) { if (child.Name == "parameter") - Parameters.Add (Parameter.FromElement (child as XmlElement)); + Parameters.Add (Parameter.FromElement (child)); } - if (elem.HasAttribute ("customAttributes")) - custom_attributes = elem.GetAttribute ("customAttributes"); + if (elem.Attribute ("customAttributes") != null) + custom_attributes = elem.XGetAttribute ("customAttributes"); } - static XmlElement GetPreviousClass (XmlNode e, string nameValue) + static XElement GetPreviousClass (XNode n, string nameValue) { - while (e != null && - (e.NodeType != XmlNodeType.Element || - e.Name != "class" || - !e.Attributes ["name"].Value.StartsWith (nameValue) || - // this complicated check (instead of simple name string equivalence match) is required for nested class inside a generic class e.g. android.content.Loader.ForceLoadContentObserver. - (e.Attributes ["name"].Value != nameValue && e.Attributes ["name"].Value.IndexOf ('<') < 0))) { - e = e.PreviousSibling; + XElement e = null; + while (n != null && + ((e = n as XElement) == null || + e.Name != "class" || + !e.XGetAttribute ("name").StartsWith (nameValue, StringComparison.Ordinal) || + // this complicated check (instead of simple name string equivalence match) is required for nested class inside a generic class e.g. android.content.Loader.ForceLoadContentObserver. + (e.XGetAttribute ("name") != nameValue && e.XGetAttribute ("name").IndexOf ('<') < 0))) { + n = n.PreviousNode; } - return (XmlElement) e; + return (XElement) e; } public override bool IsNonStaticNestedType { diff --git a/tools/generator/EnumMappings.cs b/tools/generator/EnumMappings.cs index 25df0c699..026794f13 100644 --- a/tools/generator/EnumMappings.cs +++ b/tools/generator/EnumMappings.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; using Mono.Options; using Xamarin.Android.Tools; @@ -231,27 +233,26 @@ StringReader MethodXmlToCsv (string file) return null; var sw = new StringWriter (); - var doc = new XmlDocument (); - doc.Load (file); - foreach (XmlElement e in doc.SelectNodes ("/enum-method-mappings/mapping")) { + var doc = XDocument.Load (file, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo); + foreach (XElement e in doc.XPathSelectElements ("/enum-method-mappings/mapping")) { string version = e.XGetAttribute ("api-level"); string package = null; string java_class = null; - if (e.HasAttribute ("jni-class")) { + if (e.Attribute ("jni-class") != null) { string c = e.XGetAttribute ("jni-class"); int s = c.LastIndexOf ('/'); package = c.Substring (0, s).Replace ('/', '.'); java_class = c.Substring (s+1).Replace ('$', '.'); - } else if (e.HasAttribute ("jni-interface")) { + } else if (e.Attribute ("jni-interface") != null) { string c = e.XGetAttribute ("jni-interface"); int s = c.LastIndexOf ('/'); package = c.Substring (0, s).Replace ('/', '.'); java_class = "[Interface]" + c.Substring (s+1).Replace ('$', '.'); } else { - throw new InvalidOperationException (string.Format ("Missing mandatory attribute 'jni-class' or 'jni-interface' on a mapping element: {0}", e.OuterXml)); + throw new InvalidOperationException (string.Format ("Missing mandatory attribute 'jni-class' or 'jni-interface' on a mapping element: {0}", e)); } - foreach (XmlElement m in e.SelectNodes ("method")) { + foreach (var m in e.XPathSelectElements ("method")) { string method = GetMandatoryAttribute (m, "jni-name"); string parameter = GetMandatoryAttribute (m, "parameter"); string enum_type = GetMandatoryAttribute (m, "clr-enum-type"); diff --git a/tools/generator/Field.cs b/tools/generator/Field.cs index e1a7b644c..892ecea4c 100644 --- a/tools/generator/Field.cs +++ b/tools/generator/Field.cs @@ -8,6 +8,7 @@ using Xamarin.Android.Tools; using MonoDroid.Utils; +using System.Xml.Linq; namespace MonoDroid.Generation { #if USE_CECIL @@ -86,20 +87,20 @@ protected override Parameter SetterParameter { public class XmlField : Field { - XmlElement elem; + XElement elem; string java_name; string name; string enum_type; - public XmlField (XmlElement elem) + public XmlField (XElement elem) { this.elem = elem; java_name = elem.XGetAttribute ("name"); - if (elem.HasAttribute ("managedName")) + if (elem.Attribute ("managedName") != null) name = elem.XGetAttribute ("managedName"); else name = SymbolTable.StudlyCase (Char.IsLower (java_name [0]) || java_name.ToLower ().ToUpper () != java_name ? java_name : java_name.ToLower ()); - if (elem.HasAttribute ("enumType")) + if (elem.Attribute ("enumType") != null) enum_type = elem.XGetAttribute ("enumType"); } @@ -138,7 +139,7 @@ public override string TypeName { public override string Value { get { - string val = elem.GetAttribute ("value"); // do not trim + string val = elem.XGetAttribute ("value"); // do not trim if (!String.IsNullOrEmpty (val) && Symbol != null && Symbol.FullName == "char") val = "(char)" + val; return val; diff --git a/tools/generator/GenBaseSupport.cs b/tools/generator/GenBaseSupport.cs index 481d9f978..6af0841ee 100644 --- a/tools/generator/GenBaseSupport.cs +++ b/tools/generator/GenBaseSupport.cs @@ -8,6 +8,7 @@ using Xamarin.Android.Tools; using MonoDroid.Utils; +using System.Xml.Linq; namespace MonoDroid.Generation { @@ -155,7 +156,7 @@ public override string Visibility { public class XmlGenBaseSupport : GenBaseSupport { - public XmlGenBaseSupport (XmlElement pkg, XmlElement elem) + public XmlGenBaseSupport (XElement pkg, XElement elem) { deprecated = elem.XGetAttribute ("deprecated") != "not deprecated"; if (deprecated) { @@ -169,13 +170,13 @@ public XmlGenBaseSupport (XmlElement pkg, XmlElement elem) pkg_name = pkg.XGetAttribute ("name"); java_name = elem.XGetAttribute ("name"); - if (pkg.HasAttribute ("managedName")) { + if (pkg.Attribute ("managedName") != null) { ns = pkg.XGetAttribute ("managedName"); } else { ns = StringRocks.PackageToPascalCase (PackageName); } - var tpn = elem.SelectSingleNode ("typeParameters"); + var tpn = elem.Element ("typeParameters"); if (tpn != null) { type_params = GenericParameterDefinitionList.FromXml (tpn); is_generic = true; @@ -188,7 +189,7 @@ public XmlGenBaseSupport (XmlElement pkg, XmlElement elem) throw new NotSupportedException ("Looks like old API XML is used, which we don't support anymore."); } - if (elem.HasAttribute ("managedName")) { + if (elem.Attribute ("managedName") != null) { name = elem.XGetAttribute ("managedName"); full_name = String.Format ("{0}.{1}", ns, name); int idx = name.LastIndexOf ('.'); @@ -204,7 +205,7 @@ public XmlGenBaseSupport (XmlElement pkg, XmlElement elem) full_name = String.Format ("{0}.{1}{2}", ns, idx > 0 ? StringRocks.TypeToPascalCase (java_name.Substring (0, idx + 1)) : String.Empty, name); } - obfuscated = IsObfuscatedName (pkg.ChildNodes.Count, java_name) && elem.XGetAttribute ("obfuscated") != "false"; + obfuscated = IsObfuscatedName (pkg.Elements ().Count (), java_name) && elem.XGetAttribute ("obfuscated") != "false"; } public override bool IsAcw { @@ -325,7 +326,7 @@ bool IsObfuscatedName (int threshold, string name) public class InterfaceXmlGenBaseSupport : XmlGenBaseSupport { - public InterfaceXmlGenBaseSupport (XmlElement pkg, XmlElement elem) + public InterfaceXmlGenBaseSupport (XElement pkg, XElement elem) : base (pkg, elem) { } diff --git a/tools/generator/GenericParameterDefinition.cs b/tools/generator/GenericParameterDefinition.cs index 729b5034f..a64e22e42 100644 --- a/tools/generator/GenericParameterDefinition.cs +++ b/tools/generator/GenericParameterDefinition.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Text; using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; using Mono.Cecil; using Xamarin.Android.Tools; @@ -75,13 +77,13 @@ public static GenericParameterDefinitionList FromMetadata (IEnumerable (); - foreach (XmlElement x in n.SelectNodes ("genericConstraints/genericConstraint")) + foreach (var x in n.XPathSelectElements ("genericConstraints/genericConstraint")) csts.Add (x.XGetAttribute ("type")); ret.Add (new GenericParameterDefinition (n.XGetAttribute ("name"), csts.ToArray ())); } diff --git a/tools/generator/InterfaceGen.cs b/tools/generator/InterfaceGen.cs index e96d9a92c..f17c765e5 100644 --- a/tools/generator/InterfaceGen.cs +++ b/tools/generator/InterfaceGen.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Xml; +using System.Xml.Linq; using Mono.Cecil; using Xamarin.Android.Binder; @@ -39,24 +40,20 @@ public class XmlInterfaceGen : InterfaceGen { string args_type; - public XmlInterfaceGen (XmlElement pkg, XmlElement elem) + public XmlInterfaceGen (XElement pkg, XElement elem) : base (new InterfaceXmlGenBaseSupport (pkg, elem)) { - hasManagedName = elem.HasAttribute ("managedName"); + hasManagedName = elem.Attribute ("managedName") != null; args_type = elem.XGetAttribute ("argsType"); - foreach (XmlNode node in elem.ChildNodes) { - XmlElement child = node as XmlElement; - if (child == null) - continue; - - switch (node.Name) { + foreach (var child in elem.Elements ()) { + switch (child.Name.LocalName) { case "implements": string iname = child.XGetAttribute ("name-generic-aware"); iname = iname.Length > 0 ? iname : child.XGetAttribute ("name"); AddInterface (iname); break; case "method": - if (child.GetAttribute ("synthetic") != "true") + if (child.XGetAttribute ("synthetic") != "true") AddMethod (new XmlMethod (this, child)); break; case "field": @@ -65,7 +62,7 @@ public XmlInterfaceGen (XmlElement pkg, XmlElement elem) case "typeParameters": break; // handled at GenBaseSupport default: - Report.Warning (0, Report.WarningInterfaceGen + 0, "unexpected interface child {0}.", node.Name); + Report.Warning (0, Report.WarningInterfaceGen + 0, "unexpected interface child {0}.", child); break; } } diff --git a/tools/generator/Method.cs b/tools/generator/Method.cs index 6015477ad..08a1a4f25 100644 --- a/tools/generator/Method.cs +++ b/tools/generator/Method.cs @@ -9,6 +9,7 @@ using Xamarin.Android.Tools; using MonoDroid.Utils; +using System.Xml.Linq; namespace MonoDroid.Generation { #if USE_CECIL @@ -124,15 +125,15 @@ public override string CustomAttributes { public class XmlMethod : Method { - XmlElement elem; + XElement elem; - public XmlMethod (GenBase declaringType, XmlElement elem) + public XmlMethod (GenBase declaringType, XElement elem) : base (declaringType, new XmlMethodBaseSupport (elem)) { this.elem = elem; is_static = elem.XGetAttribute ("static") == "true"; is_virtual = !is_static && elem.XGetAttribute ("final") == "false"; - if (elem.HasAttribute ("managedName")) + if (elem.Attribute ("managedName") != null) name = elem.XGetAttribute ("managedName"); else name = StringRocks.MemberToPascalCase (JavaName); @@ -141,11 +142,11 @@ public XmlMethod (GenBase declaringType, XmlElement elem) if (declaringType is InterfaceGen) is_interface_default_method = !is_abstract && !is_static; - GenerateDispatchingSetter = elem.HasAttribute ("generateDispatchingSetter"); + GenerateDispatchingSetter = elem.Attribute ("generateDispatchingSetter") != null; - foreach (XmlNode child in elem.ChildNodes) { + foreach (var child in elem.Elements ()) { if (child.Name == "parameter") - Parameters.Add (Parameter.FromElement (child as XmlElement)); + Parameters.Add (Parameter.FromElement (child)); } FillReturnType (); } @@ -154,7 +155,7 @@ public XmlMethod (GenBase declaringType, XmlElement elem) public override string ArgsType { get { - var a = elem.Attributes ["argsType"]; + var a = elem.Attribute ("argsType"); if (a == null) return null; return a.Value; @@ -163,7 +164,7 @@ public override string ArgsType { public override string EventName { get { - var a = elem.Attributes ["eventName"]; + var a = elem.Attribute ("eventName"); if (a == null) return null; return a.Value; @@ -207,24 +208,19 @@ public override string Name { // FIXME: this should not require enumReturn. Somewhere in generator uses this property improperly. public override string Return { - get { return elem.HasAttribute ("enumReturn") ? elem.XGetAttribute ("enumReturn") : elem.XGetAttribute ("return"); } + get { return IsReturnEnumified ? elem.XGetAttribute ("enumReturn") : elem.XGetAttribute ("return"); } } public override string ManagedReturn { - get { return elem.HasAttribute ("enumReturn") ? elem.XGetAttribute ("enumReturn") : elem.XGetAttribute ("managedReturn"); } + get { return IsReturnEnumified ? elem.XGetAttribute ("enumReturn") : elem.XGetAttribute ("managedReturn"); } } public override bool IsReturnEnumified { - get { return elem.HasAttribute ("enumReturn"); } + get { return elem.Attribute ("enumReturn") != null; } } protected override string PropertyNameOverride { - get { - var pn = elem.Attributes ["propertyName"]; - if (pn == null) - return null; - return pn.Value; - } + get { return elem.XGetAttribute ("propertyName"); } } static readonly Regex ApiLevel = new Regex (@"api-(\d+).xml"); @@ -248,17 +244,12 @@ public override bool Asyncify { if (IsOverride) return false; - return elem.HasAttribute ("generateAsyncWrapper"); + return elem.Attribute ("generateAsyncWrapper") != null; } } public override string CustomAttributes { - get { - if (!elem.HasAttribute ("customAttributes")) - return null; - - return elem.GetAttribute ("customAttributes"); - } + get { return elem.XGetAttribute ("customAttributes"); } } } diff --git a/tools/generator/MethodBase.cs b/tools/generator/MethodBase.cs index ee47ae33c..251b91345 100644 --- a/tools/generator/MethodBase.cs +++ b/tools/generator/MethodBase.cs @@ -9,6 +9,7 @@ using Java.Interop.Tools.TypeNameMappings; using Xamarin.Android.Tools; +using System.Xml.Linq; namespace MonoDroid.Generation { @@ -82,17 +83,17 @@ public IEnumerable GetParameters (CustomAttribute regatt) public class XmlMethodBaseSupport : IMethodBaseSupport { - XmlElement elem; + XElement elem; GenericParameterDefinitionList generic_arguments; - public XmlMethodBaseSupport (XmlElement elem) + public XmlMethodBaseSupport (XElement elem) { this.elem = elem; - var tps = elem.SelectSingleNode ("typeParameters"); + var tps = elem.Element ("typeParameters"); generic_arguments = tps != null ? GenericParameterDefinitionList.FromXml (tps) : null; } - public XmlElement Element { + public XElement Element { get { return elem; } } diff --git a/tools/generator/Parameter.cs b/tools/generator/Parameter.cs index 8d89f5606..f113b9ef2 100644 --- a/tools/generator/Parameter.cs +++ b/tools/generator/Parameter.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml; +using System.Xml.Linq; using Mono.Cecil; using Xamarin.Android.Binder; @@ -261,25 +262,25 @@ public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList return true; } - public static Parameter FromElement (XmlElement elem) + public static Parameter FromElement (XElement elem) { string managedName = elem.XGetAttribute ("managedName"); string name = !string.IsNullOrEmpty (managedName) ? managedName : SymbolTable.MangleName (elem.XGetAttribute ("name")); string java_type = elem.XGetAttribute ("type"); - string enum_type = elem.HasAttribute ("enumType") ? elem.XGetAttribute ("enumType") : null; - string managed_type = elem.HasAttribute ("managedType") ? elem.XGetAttribute ("managedType") : null; + string enum_type = elem.Attribute ("enumType") != null ? elem.XGetAttribute ("enumType") : null; + string managed_type = elem.Attribute ("managedType") != null ? elem.XGetAttribute ("managedType") : null; // FIXME: "enum_type ?? java_type" should be extraneous. Somewhere in generator uses it improperly. var result = new Parameter (name, enum_type ?? java_type, enum_type ?? managed_type, enum_type != null, java_type); - if (elem.HasAttribute ("sender")) + if (elem.Attribute ("sender") != null) result.IsSender = true; return result; } - public static Parameter FromClassElement (XmlElement elem) + public static Parameter FromClassElement (XElement elem) { string name = "__self"; string java_type = elem.XGetAttribute ("name"); - string java_package = elem.ParentNode.Attributes ["name"].Value; + string java_package = elem.Parent.XGetAttribute ("name"); return new Parameter (name, java_package + "." + java_type, null, false); } diff --git a/tools/generator/Parser.cs b/tools/generator/Parser.cs index 40b3c3b6b..1e17fe598 100644 --- a/tools/generator/Parser.cs +++ b/tools/generator/Parser.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; using System.Xml; - +using System.Xml.Linq; using Xamarin.Android.Tools; namespace MonoDroid.Generation { @@ -12,16 +12,15 @@ public class Parser { public string ApiSource { get; private set; } - public XmlDocument Load (string filename) + public XDocument Load (string filename) { - XmlDocument doc = new XmlDocument (); + XDocument doc = null; try { - doc.Load (filename); + doc = XDocument.Load (filename, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo); } catch (XmlException e) { Report.Verbose (0, "Exception: {0}", e); Report.Warning (0, Report.WarningParser + 0, e, "Invalid XML file '{0}': {1}", filename, e.Message); - doc = null; } return doc; @@ -39,7 +38,7 @@ public List Parse (string filename, IEnumerable fixups, string } } - public List Parse (XmlDocument doc, IEnumerable fixups, string apiLevel, int productVersion) + public List Parse (XDocument doc, IEnumerable fixups, string apiLevel, int productVersion) { if (doc == null) return null; @@ -53,21 +52,17 @@ public List Parse (XmlDocument doc, IEnumerable fixups, string return null; } - XmlElement root = doc.DocumentElement; + var root = doc.Root; - if ((root == null) || !root.HasChildNodes) { + if ((root == null) || !root.HasElements) { Report.Warning (0, Report.WarningParser + 1, "No packages found."); return null; } List gens = new List (); - foreach (XmlNode child in root.ChildNodes) { - XmlElement elem = child as XmlElement; - if (elem == null) - continue; - - switch (child.Name) { + foreach (var elem in root.Elements ()) { + switch (elem.Name.LocalName) { case "package": gens.AddRange (ParsePackage (elem)); break; @@ -76,7 +71,7 @@ public List Parse (XmlDocument doc, IEnumerable fixups, string SymbolTable.AddType (elem.XGetAttribute ("name"), sym); continue; default: - Report.Warning (0, Report.WarningParser + 2, "Unexpected child node: {0}.", child.Name); + Report.Warning (0, Report.WarningParser + 2, "Unexpected child node: {0}.", elem.Name); break; } } @@ -84,26 +79,22 @@ public List Parse (XmlDocument doc, IEnumerable fixups, string return gens; } - List ParsePackage (XmlElement ns) + List ParsePackage (XElement ns) { return ParsePackage (ns, null); } - List ParsePackage (XmlElement ns, Predicate p) + List ParsePackage (XElement ns, Predicate p) { List result = new List (); Dictionary nested = new Dictionary (); Dictionary by_name = new Dictionary (); - foreach (XmlNode def in ns.ChildNodes) { - - XmlElement elem = def as XmlElement; - if (elem == null) - continue; + foreach (var elem in ns.Elements ()) { string name = elem.XGetAttribute ("name"); GenBase gen = null; - switch (def.Name) { + switch (elem.Name.LocalName) { case "class": if (elem.XGetAttribute ("obfuscated") == "true") continue; @@ -115,7 +106,7 @@ List ParsePackage (XmlElement ns, Predicate p) gen = new XmlInterfaceGen (ns, elem); break; default: - Report.Warning (0, Report.WarningParser + 3, "Unexpected node in package element: {0}.", def.Name); + Report.Warning (0, Report.WarningParser + 3, "Unexpected node in package element: {0}.", elem.Name); break; } diff --git a/tools/generator/Report.cs b/tools/generator/Report.cs index 76b62280d..0db1bbd17 100644 --- a/tools/generator/Report.cs +++ b/tools/generator/Report.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Xml; +using System.Xml.Linq; using System.Xml.XPath; namespace MonoDroid.Generation @@ -46,13 +47,11 @@ public static void Error (int errorCode, Exception innerException, string format Error (errorCode, innerException, null, -1, -1, format, args); } - public static void Error (int errorCode, Exception innerException, XPathNavigator nav, string format, params object [] args) + public static void Error (int errorCode, Exception innerException, XNode node, string format, params object [] args) { - var hn = nav as IHasXmlNode; - var baseUri = hn != null ? hn.GetNode ().OwnerDocument.BaseURI : nav.BaseURI; Uri uri; - string file = Uri.TryCreate (baseUri, UriKind.Absolute, out uri) ? uri.LocalPath : null; - IXmlLineInfo li = nav as IXmlLineInfo; + string file = Uri.TryCreate (node.BaseUri, UriKind.Absolute, out uri) ? uri.LocalPath : null; + IXmlLineInfo li = node as IXmlLineInfo; li = li != null && li.HasLineInfo () ? li : null; Error (errorCode, innerException, file, li != null ? li.LineNumber : -1, li != null ? li.LinePosition : -1, format, args); } @@ -67,13 +66,11 @@ public static void Warning (int verbosity, int errorCode, string format, params Warning (verbosity, errorCode, null, format, args); } - public static void Warning (int verbosity, int errorCode, Exception innerException, XPathNavigator nav, string format, params object [] args) + public static void Warning (int verbosity, int errorCode, Exception innerException, XNode node, string format, params object [] args) { - var hn = nav as IHasXmlNode; - var baseUri = hn != null ? hn.GetNode ().OwnerDocument.BaseURI : nav.BaseURI; Uri uri; - string file = Uri.TryCreate (baseUri, UriKind.Absolute, out uri) ? uri.LocalPath : null; - IXmlLineInfo li = nav as IXmlLineInfo; + string file = Uri.TryCreate (node.BaseUri, UriKind.Absolute, out uri) ? uri.LocalPath : null; + IXmlLineInfo li = node as IXmlLineInfo; li = li != null && li.HasLineInfo () ? li : null; Warning (verbosity, errorCode, innerException, file, li != null ? li.LineNumber : -1, li != null ? li.LinePosition : -1, format, args); }