From f4e68b5b6ecda7939f91b572a2630b6e1e8445e0 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 22 Apr 2021 16:26:21 -0500 Subject: [PATCH] [generator] Separate metadata fixup step from parsing step. (#822) Context: https://github.com/xamarin/java.interop/issues/789 One issue with the proposal to flip the order of `ApiXmlAdjuster` and `metadata` in Issue #789 is that the "apply metadata" step is intertwined with the "parse API xml document into POCO's" step. This means that the adjuster step cannot be inserted between them, as the code is currently written. Separate out the two steps so that they can be reordered in the future. Additionally, refactor the metadata fixup step so that it can be unit tested more easily by moving it to `Java.Interop.Tools.Generator.dll`. Unit tests for applying metadata have been added. --- .../Extensions/UtilityExtensions.cs | 14 ++ .../Extensions/XmlExtensions.cs | 26 +++ .../Java.Interop.Tools.Generator.csproj | 4 + .../Metadata/FixupXmlDocument.cs | 207 ++++++++++++++++++ .../Utilities/ApiXmlDocument.cs | 47 ++++ .../Utilities}/ISourceLineInfo.cs | 6 +- .../Utilities/Report.cs | 127 ++++++----- .../Unit-Tests/CodeGeneratorTestBase.cs | 2 +- .../Unit-Tests/FixupXmlDocumentTests.cs | 100 +++++++++ .../generator-Tests/Unit-Tests/ReportTests.cs | 1 + .../Unit-Tests/XmlApiImporterTests.cs | 2 +- tools/generator/CodeGenerationOptions.cs | 2 +- tools/generator/CodeGenerator.cs | 24 +- tools/generator/CodeGeneratorOptions.cs | 1 + .../CodeGenerator.cs | 1 + .../XmlApiImporter.cs | 92 ++++++++ .../ClassGen.cs | 1 + .../Field.cs | 2 +- .../GenBase.cs | 1 + .../GenericParameterDefinition.cs | 1 + .../InterfaceGen.cs | 1 + .../MethodBase.cs | 1 + .../Parameter.cs | 1 + .../ReturnValue.cs | 2 +- .../ApiFixup.cs | 1 + .../EnumMap.cs | 1 + .../Parser.cs | 144 ------------ .../Extensions/SourceWriterExtensions.cs | 1 + .../InterfaceMemberAlternativeClass.cs | 1 + 29 files changed, 591 insertions(+), 223 deletions(-) create mode 100644 src/Java.Interop.Tools.Generator/Extensions/XmlExtensions.cs create mode 100644 src/Java.Interop.Tools.Generator/Metadata/FixupXmlDocument.cs create mode 100644 src/Java.Interop.Tools.Generator/Utilities/ApiXmlDocument.cs rename {tools/generator/Java.Interop.Tools.Generator.ObjectModel => src/Java.Interop.Tools.Generator/Utilities}/ISourceLineInfo.cs (54%) rename {tools/generator => src/Java.Interop.Tools.Generator}/Utilities/Report.cs (57%) create mode 100644 tests/generator-Tests/Unit-Tests/FixupXmlDocumentTests.cs delete mode 100644 tools/generator/Java.Interop.Tools.Generator.Transformation/Parser.cs diff --git a/src/Java.Interop.Tools.Generator/Extensions/UtilityExtensions.cs b/src/Java.Interop.Tools.Generator/Extensions/UtilityExtensions.cs index 38c8c372a..935885d5d 100644 --- a/src/Java.Interop.Tools.Generator/Extensions/UtilityExtensions.cs +++ b/src/Java.Interop.Tools.Generator/Extensions/UtilityExtensions.cs @@ -1,5 +1,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Xml; +using System.Xml.Linq; namespace Java.Interop.Tools.Generator { @@ -27,5 +29,17 @@ public static bool StartsWithAny (this string value, params string [] values) } public static bool HasValue ([NotNullWhen (true)]this string? str) => !string.IsNullOrEmpty (str); + + public static XDocument? LoadXmlDocument (string filename) + { + try { + return XDocument.Load (filename, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo); + } catch (XmlException e) { + Report.Verbose (0, "Exception: {0}", e); + Report.LogCodedWarning (0, Report.WarningInvalidXmlFile, e, filename, e.Message); + } + + return null; + } } } diff --git a/src/Java.Interop.Tools.Generator/Extensions/XmlExtensions.cs b/src/Java.Interop.Tools.Generator/Extensions/XmlExtensions.cs new file mode 100644 index 000000000..2c6c2b735 --- /dev/null +++ b/src/Java.Interop.Tools.Generator/Extensions/XmlExtensions.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Xml.Linq; +using System.Xml.XPath; + +namespace Xamarin.Android.Tools +{ + static class XmlExtensions + { + public static string? XGetAttribute (this XElement element, string name) + => element.Attribute (name)?.Value.Trim (); + + public static string? XGetAttribute (this XPathNavigator nav, string name, string ns) + => nav.GetAttribute (name, ns)?.Trim (); + + public static int? XGetAttributeAsInt (this XElement element, string name) + { + var value = element.XGetAttribute (name); + + if (int.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + return result; + + return null; + } + } +} diff --git a/src/Java.Interop.Tools.Generator/Java.Interop.Tools.Generator.csproj b/src/Java.Interop.Tools.Generator/Java.Interop.Tools.Generator.csproj index 8527af75c..11cc6392e 100644 --- a/src/Java.Interop.Tools.Generator/Java.Interop.Tools.Generator.csproj +++ b/src/Java.Interop.Tools.Generator/Java.Interop.Tools.Generator.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/src/Java.Interop.Tools.Generator/Metadata/FixupXmlDocument.cs b/src/Java.Interop.Tools.Generator/Metadata/FixupXmlDocument.cs new file mode 100644 index 000000000..0578fd258 --- /dev/null +++ b/src/Java.Interop.Tools.Generator/Metadata/FixupXmlDocument.cs @@ -0,0 +1,207 @@ +using System; +using System.Linq; +using System.Xml.XPath; +using System.Xml.Linq; + +using Xamarin.Android.Tools; + +namespace Java.Interop.Tools.Generator +{ + public class FixupXmlDocument + { + public XDocument FixupDocument { get; } + + public FixupXmlDocument (XDocument fixupDocument) + { + FixupDocument = fixupDocument; + } + + public static FixupXmlDocument? Load (string filename) + { + if (UtilityExtensions.LoadXmlDocument (filename) is XDocument doc) + return new FixupXmlDocument (doc); + + return null; + } + + public void Apply (ApiXmlDocument apiDocument, string apiLevelString, int productVersion) + { + // Defaulting to 0 here is fine + int.TryParse (apiLevelString, out var apiLevel); + + var metadataChildren = FixupDocument.XPathSelectElements ("/metadata/*"); + + string? prev_path = null; + XElement? attr_last_cache = null; + + foreach (var metaitem in metadataChildren) { + if (ShouldSkip (metaitem, apiLevel, productVersion)) + continue; + if (!ShouldApply (metaitem, apiDocument)) + continue; + + var path = metaitem.XGetAttribute ("path"); + + if (path != prev_path) + attr_last_cache = null; + + prev_path = path; + + switch (metaitem.Name.LocalName) { + case "remove-node": + try { + var nodes = apiDocument.ApiDocument.XPathSelectElements (path).ToArray (); + + if (nodes.Any ()) + foreach (var node in nodes) + node.Remove (); + else + // BG8A00 + Report.LogCodedWarning (0, Report.WarningRemoveNodeMatchedNoNodes, null, metaitem, $""); + } catch (XPathException e) { + // BG4301 + Report.LogCodedError (Report.ErrorRemoveNodeInvalidXPath, e, metaitem, path); + } + break; + case "add-node": + try { + var nodes = apiDocument.ApiDocument.XPathSelectElements (path); + + if (!nodes.Any ()) + // BG8A01 + Report.LogCodedWarning (0, Report.WarningAddNodeMatchedNoNodes, null, metaitem, $""); + else { + foreach (var node in nodes) + node.Add (metaitem.Nodes ()); + } + } catch (XPathException e) { + // BG4302 + Report.LogCodedError (Report.ErrorAddNodeInvalidXPath, e, metaitem, path); + } + break; + case "change-node": + try { + var nodes = apiDocument.ApiDocument.XPathSelectElements (path); + var matched = false; + + 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.LogCodedWarning (0, Report.WarningChangeNodeTypeMatchedNoNodes, null, metaitem, $""); + } catch (XPathException e) { + // BG4303 + Report.LogCodedError (Report.ErrorChangeNodeInvalidXPath, e, metaitem, path); + } + break; + case "attr": + try { + var attr_name = metaitem.XGetAttribute ("name"); + + if (string.IsNullOrEmpty (attr_name)) + // BG4307 + Report.LogCodedError (Report.ErrorMissingAttrName, null, metaitem, path); + var nodes = attr_last_cache != null ? new XElement [] { attr_last_cache } : apiDocument.ApiDocument.XPathSelectElements (path); + var attr_matched = 0; + + foreach (var n in nodes) { + n.SetAttributeValue (attr_name, metaitem.Value); + attr_matched++; + } + if (attr_matched == 0) + // BG8A04 + Report.LogCodedWarning (0, Report.WarningAttrMatchedNoNodes, null, metaitem, $""); + if (attr_matched != 1) + attr_last_cache = null; + } catch (XPathException e) { + // BG4304 + Report.LogCodedError (Report.ErrorAttrInvalidXPath, e, metaitem, path); + } + break; + case "move-node": + try { + var parent = metaitem.Value; + var parents = apiDocument.ApiDocument.XPathSelectElements (parent); + var matched = false; + + 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.LogCodedWarning (0, Report.WarningMoveNodeMatchedNoNodes, null, metaitem, $""); + } catch (XPathException e) { + // BG4305 + Report.LogCodedError (Report.ErrorMoveNodeInvalidXPath, e, metaitem, path); + } + break; + case "remove-attr": + try { + var name = metaitem.XGetAttribute ("name"); + var nodes = apiDocument.ApiDocument.XPathSelectElements (path); + var matched = false; + + foreach (var node in nodes) { + node.RemoveAttributes (); + matched = true; + } + + if (!matched) + // BG8A06 + Report.LogCodedWarning (0, Report.WarningRemoveAttrMatchedNoNodes, null, metaitem, $""); + } catch (XPathException e) { + // BG4306 + Report.LogCodedError (Report.ErrorRemoveAttrInvalidXPath, e, metaitem, path); + } + break; + } + } + } + + bool ShouldSkip (XElement node, int apiLevel, int productVersion) + { + if (apiLevel > 0) { + var since = node.XGetAttributeAsInt ("api-since"); + var until = node.XGetAttributeAsInt ("api-until"); + + if (since is int since_int && since_int > apiLevel) + return true; + else if (until is int until_int && until_int < apiLevel) + return true; + } + + if (productVersion > 0) { + var product_version = node.XGetAttributeAsInt ("product-version"); + + if (product_version is int version && version > productVersion) + return true; + + } + return false; + } + + bool ShouldApply (XElement node, ApiXmlDocument apiDocument) + { + if (apiDocument.ApiSource.HasValue ()) { + var targetsource = node.XGetAttribute ("api-source"); + + if (!targetsource.HasValue ()) + return true; + + return targetsource == apiDocument.ApiSource; + } + + return true; + } + } +} diff --git a/src/Java.Interop.Tools.Generator/Utilities/ApiXmlDocument.cs b/src/Java.Interop.Tools.Generator/Utilities/ApiXmlDocument.cs new file mode 100644 index 000000000..1bd333165 --- /dev/null +++ b/src/Java.Interop.Tools.Generator/Utilities/ApiXmlDocument.cs @@ -0,0 +1,47 @@ +using System; +using System.Xml; +using System.Xml.Linq; +using Xamarin.Android.Tools; + +namespace Java.Interop.Tools.Generator +{ + public class ApiXmlDocument + { + public XDocument ApiDocument { get; } + public string ApiLevel { get; } + public int ProductVersion { get; } + + public string? ApiSource => ApiDocument.Root?.XGetAttribute ("api-source"); + + public ApiXmlDocument (XDocument document, string apiLevel, int productVersion) + { + ApiDocument = document; + ApiLevel = apiLevel; + ProductVersion = productVersion; + } + + public static ApiXmlDocument? Load (string filename, string apiLevel, int productVersion) + { + if (UtilityExtensions.LoadXmlDocument (filename) is XDocument doc) + return new ApiXmlDocument (doc, apiLevel, productVersion); + + return null; + } + + public void ApplyFixupFile (string filename) + { + if (FixupXmlDocument.Load (filename) is FixupXmlDocument fixup) + ApplyFixupFile (fixup); + } + + public void ApplyFixupFile (FixupXmlDocument fixup) + { + try { + fixup.Apply (this, ApiLevel, ProductVersion); + } catch (XmlException ex) { + // BG4200 + Report.LogCodedError (Report.ErrorFailedToProcessMetadata, ex.Message); + } + } + } +} diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ISourceLineInfo.cs b/src/Java.Interop.Tools.Generator/Utilities/ISourceLineInfo.cs similarity index 54% rename from tools/generator/Java.Interop.Tools.Generator.ObjectModel/ISourceLineInfo.cs rename to src/Java.Interop.Tools.Generator/Utilities/ISourceLineInfo.cs index 1c0fec851..9ef4ae09c 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ISourceLineInfo.cs +++ b/src/Java.Interop.Tools.Generator/Utilities/ISourceLineInfo.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace MonoDroid.Generation +namespace Java.Interop.Tools.Generator { public interface ISourceLineInfo { diff --git a/tools/generator/Utilities/Report.cs b/src/Java.Interop.Tools.Generator/Utilities/Report.cs similarity index 57% rename from tools/generator/Utilities/Report.cs rename to src/Java.Interop.Tools.Generator/Utilities/Report.cs index 127f7fc21..e216a1535 100644 --- a/tools/generator/Utilities/Report.cs +++ b/src/Java.Interop.Tools.Generator/Utilities/Report.cs @@ -2,7 +2,7 @@ using System.Xml; using System.Xml.Linq; -namespace MonoDroid.Generation +namespace Java.Interop.Tools.Generator { public class Report { @@ -20,62 +20,62 @@ public LocalizedMessage (int code, string value) } } - public static LocalizedMessage ErrorFailedToRemoveConstants => new LocalizedMessage (0x4000, Java.Interop.Localization.Resources.Generator_BG4000); - public static LocalizedMessage ErrorFailedToProcessEnumMap => new LocalizedMessage (0x4100, Java.Interop.Localization.Resources.Generator_BG4100); - public static LocalizedMessage ErrorFailedToProcessMetadata => new LocalizedMessage (0x4200, Java.Interop.Localization.Resources.Generator_BG4200); - public static LocalizedMessage ErrorRemoveNodeInvalidXPath => new LocalizedMessage (0x4301, Java.Interop.Localization.Resources.Generator_BG4300); - public static LocalizedMessage ErrorAddNodeInvalidXPath => new LocalizedMessage (0x4302, Java.Interop.Localization.Resources.Generator_BG4300); - public static LocalizedMessage ErrorChangeNodeInvalidXPath => new LocalizedMessage (0x4303, Java.Interop.Localization.Resources.Generator_BG4300); - public static LocalizedMessage ErrorAttrInvalidXPath => new LocalizedMessage (0x4304, Java.Interop.Localization.Resources.Generator_BG4300); - public static LocalizedMessage ErrorMoveNodeInvalidXPath => new LocalizedMessage (0x4305, Java.Interop.Localization.Resources.Generator_BG4300); - public static LocalizedMessage ErrorRemoveAttrInvalidXPath => new LocalizedMessage (0x4306, Java.Interop.Localization.Resources.Generator_BG4300); - public static LocalizedMessage ErrorMissingAttrName => new LocalizedMessage (0x4307, Java.Interop.Localization.Resources.Generator_BG4307); - public static LocalizedMessage ErrorUnexpectedGlobal => new LocalizedMessage (0x4400, Java.Interop.Localization.Resources.Generator_BG4400); - public static LocalizedMessage ErrorInvalidDIMArgument => new LocalizedMessage (0x4500, Java.Interop.Localization.Resources.Generator_BG4500); - - public static LocalizedMessage WarningUnexpectedChild => new LocalizedMessage (0x8101, Java.Interop.Localization.Resources.Generator_BG8101); - public static LocalizedMessage WarningUnknownBaseType => new LocalizedMessage (0x8102, Java.Interop.Localization.Resources.Generator_BG8102); - public static LocalizedMessage WarningInvalidBaseType => new LocalizedMessage (0x8103, Java.Interop.Localization.Resources.Generator_BG8103); - public static LocalizedMessage WarningAssemblyParseFailure => new LocalizedMessage (0x8200, Java.Interop.Localization.Resources.Generator_BG8200); - public static LocalizedMessage WarningMissingClassForConstructor => new LocalizedMessage (0x8300, Java.Interop.Localization.Resources.Generator_BG8300); - public static LocalizedMessage WarningUnexpectedFieldType => new LocalizedMessage (0x8400, Java.Interop.Localization.Resources.Generator_BG8400); - public static LocalizedMessage WarningFieldNameCollision_Property => new LocalizedMessage (0x8401, Java.Interop.Localization.Resources.Generator_BG8401_Property); - public static LocalizedMessage WarningFieldNameCollision_Method => new LocalizedMessage (0x8401, Java.Interop.Localization.Resources.Generator_BG8401_Method); - public static LocalizedMessage WarningFieldNameCollision_NestedType => new LocalizedMessage (0x8401, Java.Interop.Localization.Resources.Generator_BG8401_NestedType); - public static LocalizedMessage WarningDuplicateField => new LocalizedMessage (0x8402, Java.Interop.Localization.Resources.Generator_BG8402); - public static LocalizedMessage WarningUnexpectedInterfaceChild => new LocalizedMessage (0x8500, Java.Interop.Localization.Resources.Generator_BG8500); - public static LocalizedMessage WarningEmptyEventName => new LocalizedMessage (0x8501, Java.Interop.Localization.Resources.Generator_BG8501); - public static LocalizedMessage WarningInvalidDueToInterfaces => new LocalizedMessage (0x8502, Java.Interop.Localization.Resources.Generator_BG8502); - public static LocalizedMessage WarningInvalidDueToMethods => new LocalizedMessage (0x8503, Java.Interop.Localization.Resources.Generator_BG8503); - public static LocalizedMessage WarningInvalidEventName => new LocalizedMessage (0x8504, Java.Interop.Localization.Resources.Generator_BG8504); - public static LocalizedMessage WarningInvalidEventName2 => new LocalizedMessage (0x8505, Java.Interop.Localization.Resources.Generator_BG8504); - public static LocalizedMessage WarningInvalidEventPropertyName => new LocalizedMessage (0x8506, Java.Interop.Localization.Resources.Generator_BG8506); - public static LocalizedMessage WarningInvalidXmlFile => new LocalizedMessage (0x8600, Java.Interop.Localization.Resources.Generator_BG8600); - public static LocalizedMessage WarningNoPackageElements => new LocalizedMessage (0x8601, Java.Interop.Localization.Resources.Generator_BG8601); - public static LocalizedMessage WarningUnexpectedRootChildNode => new LocalizedMessage (0x8602, Java.Interop.Localization.Resources.Generator_BG8602); - public static LocalizedMessage WarningUnexpectedPackageChildNode => new LocalizedMessage (0x8603, Java.Interop.Localization.Resources.Generator_BG8603); - public static LocalizedMessage WarningNestedTypeAncestorNotFound => new LocalizedMessage (0x8604, Java.Interop.Localization.Resources.Generator_BG8604); - public static LocalizedMessage WarningUnknownReturnType => new LocalizedMessage (0x8700, Java.Interop.Localization.Resources.Generator_BG8700); - public static LocalizedMessage WarningInvalidReturnType => new LocalizedMessage (0x8701, Java.Interop.Localization.Resources.Generator_BG8701); - public static LocalizedMessage WarningUnknownParameterType => new LocalizedMessage (0x8800, Java.Interop.Localization.Resources.Generator_BG8800); - public static LocalizedMessage WarningInvalidParameterType => new LocalizedMessage (0x8801, Java.Interop.Localization.Resources.Generator_BG8801); - public static LocalizedMessage WarningRemoveNodeMatchedNoNodes => new LocalizedMessage (0x8A00, Java.Interop.Localization.Resources.Generator_BG8A00); - public static LocalizedMessage WarningAddNodeMatchedNoNodes => new LocalizedMessage (0x8A01, Java.Interop.Localization.Resources.Generator_BG8A00); - public static LocalizedMessage WarningChangeNodeTypeMatchedNoNodes => new LocalizedMessage (0x8A03, Java.Interop.Localization.Resources.Generator_BG8A00); - public static LocalizedMessage WarningAttrMatchedNoNodes => new LocalizedMessage (0x8A04, Java.Interop.Localization.Resources.Generator_BG8A00); - public static LocalizedMessage WarningMoveNodeMatchedNoNodes => new LocalizedMessage (0x8A05, Java.Interop.Localization.Resources.Generator_BG8A00); - public static LocalizedMessage WarningRemoveAttrMatchedNoNodes => new LocalizedMessage (0x8A06, Java.Interop.Localization.Resources.Generator_BG8A00); - public static LocalizedMessage WarningUnknownGenericConstraint => new LocalizedMessage (0x8B00, Java.Interop.Localization.Resources.Generator_BG8B00); - public static LocalizedMessage WarningBaseInterfaceNotFound => new LocalizedMessage (0x8C00, Java.Interop.Localization.Resources.Generator_BG8C00); - public static LocalizedMessage WarningBaseInterfaceInvalid => new LocalizedMessage (0x8C01, Java.Interop.Localization.Resources.Generator_BG8C01); + public static LocalizedMessage ErrorFailedToRemoveConstants => new LocalizedMessage (0x4000, Localization.Resources.Generator_BG4000); + public static LocalizedMessage ErrorFailedToProcessEnumMap => new LocalizedMessage (0x4100, Localization.Resources.Generator_BG4100); + public static LocalizedMessage ErrorFailedToProcessMetadata => new LocalizedMessage (0x4200, Localization.Resources.Generator_BG4200); + public static LocalizedMessage ErrorRemoveNodeInvalidXPath => new LocalizedMessage (0x4301, Localization.Resources.Generator_BG4300); + public static LocalizedMessage ErrorAddNodeInvalidXPath => new LocalizedMessage (0x4302, Localization.Resources.Generator_BG4300); + public static LocalizedMessage ErrorChangeNodeInvalidXPath => new LocalizedMessage (0x4303, Localization.Resources.Generator_BG4300); + public static LocalizedMessage ErrorAttrInvalidXPath => new LocalizedMessage (0x4304, Localization.Resources.Generator_BG4300); + public static LocalizedMessage ErrorMoveNodeInvalidXPath => new LocalizedMessage (0x4305, Localization.Resources.Generator_BG4300); + public static LocalizedMessage ErrorRemoveAttrInvalidXPath => new LocalizedMessage (0x4306, Localization.Resources.Generator_BG4300); + public static LocalizedMessage ErrorMissingAttrName => new LocalizedMessage (0x4307, Localization.Resources.Generator_BG4307); + public static LocalizedMessage ErrorUnexpectedGlobal => new LocalizedMessage (0x4400, Localization.Resources.Generator_BG4400); + public static LocalizedMessage ErrorInvalidDIMArgument => new LocalizedMessage (0x4500, Localization.Resources.Generator_BG4500); + + public static LocalizedMessage WarningUnexpectedChild => new LocalizedMessage (0x8101, Localization.Resources.Generator_BG8101); + public static LocalizedMessage WarningUnknownBaseType => new LocalizedMessage (0x8102, Localization.Resources.Generator_BG8102); + public static LocalizedMessage WarningInvalidBaseType => new LocalizedMessage (0x8103, Localization.Resources.Generator_BG8103); + public static LocalizedMessage WarningAssemblyParseFailure => new LocalizedMessage (0x8200, Localization.Resources.Generator_BG8200); + public static LocalizedMessage WarningMissingClassForConstructor => new LocalizedMessage (0x8300, Localization.Resources.Generator_BG8300); + public static LocalizedMessage WarningUnexpectedFieldType => new LocalizedMessage (0x8400, Localization.Resources.Generator_BG8400); + public static LocalizedMessage WarningFieldNameCollision_Property => new LocalizedMessage (0x8401, Localization.Resources.Generator_BG8401_Property); + public static LocalizedMessage WarningFieldNameCollision_Method => new LocalizedMessage (0x8401, Localization.Resources.Generator_BG8401_Method); + public static LocalizedMessage WarningFieldNameCollision_NestedType => new LocalizedMessage (0x8401, Localization.Resources.Generator_BG8401_NestedType); + public static LocalizedMessage WarningDuplicateField => new LocalizedMessage (0x8402, Localization.Resources.Generator_BG8402); + public static LocalizedMessage WarningUnexpectedInterfaceChild => new LocalizedMessage (0x8500, Localization.Resources.Generator_BG8500); + public static LocalizedMessage WarningEmptyEventName => new LocalizedMessage (0x8501, Localization.Resources.Generator_BG8501); + public static LocalizedMessage WarningInvalidDueToInterfaces => new LocalizedMessage (0x8502, Localization.Resources.Generator_BG8502); + public static LocalizedMessage WarningInvalidDueToMethods => new LocalizedMessage (0x8503, Localization.Resources.Generator_BG8503); + public static LocalizedMessage WarningInvalidEventName => new LocalizedMessage (0x8504, Localization.Resources.Generator_BG8504); + public static LocalizedMessage WarningInvalidEventName2 => new LocalizedMessage (0x8505, Localization.Resources.Generator_BG8504); + public static LocalizedMessage WarningInvalidEventPropertyName => new LocalizedMessage (0x8506, Localization.Resources.Generator_BG8506); + public static LocalizedMessage WarningInvalidXmlFile => new LocalizedMessage (0x8600, Localization.Resources.Generator_BG8600); + public static LocalizedMessage WarningNoPackageElements => new LocalizedMessage (0x8601, Localization.Resources.Generator_BG8601); + public static LocalizedMessage WarningUnexpectedRootChildNode => new LocalizedMessage (0x8602, Localization.Resources.Generator_BG8602); + public static LocalizedMessage WarningUnexpectedPackageChildNode => new LocalizedMessage (0x8603, Localization.Resources.Generator_BG8603); + public static LocalizedMessage WarningNestedTypeAncestorNotFound => new LocalizedMessage (0x8604, Localization.Resources.Generator_BG8604); + public static LocalizedMessage WarningUnknownReturnType => new LocalizedMessage (0x8700, Localization.Resources.Generator_BG8700); + public static LocalizedMessage WarningInvalidReturnType => new LocalizedMessage (0x8701, Localization.Resources.Generator_BG8701); + public static LocalizedMessage WarningUnknownParameterType => new LocalizedMessage (0x8800, Localization.Resources.Generator_BG8800); + public static LocalizedMessage WarningInvalidParameterType => new LocalizedMessage (0x8801, Localization.Resources.Generator_BG8801); + public static LocalizedMessage WarningRemoveNodeMatchedNoNodes => new LocalizedMessage (0x8A00, Localization.Resources.Generator_BG8A00); + public static LocalizedMessage WarningAddNodeMatchedNoNodes => new LocalizedMessage (0x8A01, Localization.Resources.Generator_BG8A00); + public static LocalizedMessage WarningChangeNodeTypeMatchedNoNodes => new LocalizedMessage (0x8A03, Localization.Resources.Generator_BG8A00); + public static LocalizedMessage WarningAttrMatchedNoNodes => new LocalizedMessage (0x8A04, Localization.Resources.Generator_BG8A00); + public static LocalizedMessage WarningMoveNodeMatchedNoNodes => new LocalizedMessage (0x8A05, Localization.Resources.Generator_BG8A00); + public static LocalizedMessage WarningRemoveAttrMatchedNoNodes => new LocalizedMessage (0x8A06, Localization.Resources.Generator_BG8A00); + public static LocalizedMessage WarningUnknownGenericConstraint => new LocalizedMessage (0x8B00, Localization.Resources.Generator_BG8B00); + public static LocalizedMessage WarningBaseInterfaceNotFound => new LocalizedMessage (0x8C00, Localization.Resources.Generator_BG8C00); + public static LocalizedMessage WarningBaseInterfaceInvalid => new LocalizedMessage (0x8C01, Localization.Resources.Generator_BG8C01); public static void LogCodedError (LocalizedMessage message, params string [] args) => LogCodedError (message, null, null, -1, -1, args); - public static void LogCodedError (LocalizedMessage message, Exception innerException, params string [] args) + public static void LogCodedError (LocalizedMessage message, Exception? innerException, params string [] args) => LogCodedError (message, innerException, null, -1, -1, args); - public static void LogCodedError (LocalizedMessage message, Exception innerException, XNode node, params string [] args) + public static void LogCodedError (LocalizedMessage message, Exception? innerException, XNode node, params string? [] args) { var file = Uri.TryCreate (node.BaseUri, UriKind.Absolute, out var uri) ? uri.LocalPath : null; var line_info = (node as IXmlLineInfo)?.HasLineInfo () == true ? node as IXmlLineInfo : null; @@ -83,21 +83,21 @@ public static void LogCodedError (LocalizedMessage message, Exception innerExcep LogCodedError (message, innerException, file, line_info?.LineNumber ?? -1, line_info?.LinePosition ?? -1, args); } - public static void LogCodedError (LocalizedMessage message, Exception innerException, string sourceFile, int line, int column, params string [] args) + public static void LogCodedError (LocalizedMessage message, Exception? innerException, string? sourceFile, int line, int column, params string? [] args) { throw new BindingGeneratorException (message.Code, sourceFile, line, column, string.Format (message.Value, args), innerException); } - public static void LogCodedWarning (int verbosity, LocalizedMessage message, params string [] args) + public static void LogCodedWarning (int verbosity, LocalizedMessage message, params string? [] args) => LogCodedWarning (verbosity, message, null, null, -1, -1, args); - public static void LogCodedWarning (int verbosity, LocalizedMessage message, ISourceLineInfo sourceInfo, params string [] args) + public static void LogCodedWarning (int verbosity, LocalizedMessage message, ISourceLineInfo sourceInfo, params string? [] args) => LogCodedWarning (verbosity, message, null, sourceInfo.SourceFile, sourceInfo.LineNumber, sourceInfo.LinePosition, args); - public static void LogCodedWarning (int verbosity, LocalizedMessage message, Exception innerException, params string [] args) + public static void LogCodedWarning (int verbosity, LocalizedMessage message, Exception? innerException, params string? [] args) => LogCodedWarning (verbosity, message, innerException, null, -1, -1, args); - public static void LogCodedWarning (int verbosity, LocalizedMessage message, Exception innerException, XNode node, params string [] args) + public static void LogCodedWarning (int verbosity, LocalizedMessage message, Exception? innerException, XNode node, params string? [] args) { var file = Uri.TryCreate (node.BaseUri, UriKind.Absolute, out var uri) ? uri.LocalPath : null; var line_info = (node as IXmlLineInfo)?.HasLineInfo () == true ? node as IXmlLineInfo : null; @@ -105,7 +105,7 @@ public static void LogCodedWarning (int verbosity, LocalizedMessage message, Exc LogCodedWarning (verbosity, message, innerException, file, line_info?.LineNumber ?? -1, line_info?.LinePosition ?? -1, args); } - public static void LogCodedWarning (int verbosity, LocalizedMessage message, Exception innerException, string sourceFile, int line, int column, params string [] args) + public static void LogCodedWarning (int verbosity, LocalizedMessage message, Exception? innerException, string? sourceFile, int line, int column, params string? [] args) { if (verbosity > (Verbosity ?? 0)) return; @@ -117,24 +117,24 @@ public static void LogCodedWarning (int verbosity, LocalizedMessage message, Exc Console.Error.WriteLine (innerException); } - public static void Verbose (int verbosity, string format, params object[] args) + public static void Verbose (int verbosity, string format, params object?[] args) { if (verbosity > (Verbosity ?? 0)) return; Console.Error.WriteLine (format, args); } - public static string FormatCodedMessage (bool error, LocalizedMessage message, params object [] args) + public static string FormatCodedMessage (bool error, LocalizedMessage message, params object? [] args) => Format (error, message.Code, null, -1, -1, message.Value, args); - public static string Format (bool error, int errorCode, string sourceFile, int line, int column, string format, params object[] args) + public static string Format (bool error, int errorCode, string? sourceFile, int line, int column, string format, params object?[] args) { var origin = FormatOrigin (sourceFile, line, column); return $"{origin}{(error ? "error" : "warning")} BG{errorCode:X04}: " + string.Format (format, args); } - static string FormatOrigin (string sourceFile, int line, int column) + static string? FormatOrigin (string? sourceFile, int line, int column) { if (string.IsNullOrWhiteSpace (sourceFile)) return null; @@ -157,14 +157,13 @@ public BindingGeneratorException (int errorCode, string message) : this (errorCode, message, null) { } - public BindingGeneratorException (int errorCode, string message, Exception innerException) + public BindingGeneratorException (int errorCode, string message, Exception? innerException) : this (errorCode, null, -1, -1, message, innerException) { } - public BindingGeneratorException (int errorCode, string sourceFile, int line, int column, string message, Exception 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) { } } } - diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorTestBase.cs b/tests/generator-Tests/Unit-Tests/CodeGeneratorTestBase.cs index f3435d3f7..5d1abdb06 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorTestBase.cs +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorTestBase.cs @@ -62,7 +62,7 @@ string GetExpectedResults (string testName, string target) protected List ParseApiDefinition (string xml) { var doc = XDocument.Parse (xml); - var gens = new Parser (options).Parse (doc, Enumerable.Empty (), "29", 7); + var gens = XmlApiImporter.Parse (doc, options); foreach (var gen in gens) options.SymbolTable.AddType (gen); diff --git a/tests/generator-Tests/Unit-Tests/FixupXmlDocumentTests.cs b/tests/generator-Tests/Unit-Tests/FixupXmlDocumentTests.cs new file mode 100644 index 000000000..5ce1c72e1 --- /dev/null +++ b/tests/generator-Tests/Unit-Tests/FixupXmlDocumentTests.cs @@ -0,0 +1,100 @@ +using System; +using System.Xml.Linq; +using Java.Interop.Tools.Generator; +using NUnit.Framework; + +namespace generatortests +{ + [TestFixture] + public class FixupXmlDocumentTests + { + [Test] + public void RemoveNode () + { + var api = GetXmlApiDocument (); + var fixup = GetFixupXmlDocument (""); + + api.ApplyFixupFile (fixup); + + Assert.AreEqual ("", api.ApiDocument.ToString (SaveOptions.DisableFormatting).Replace ('\"', '\'')); + } + + [Test] + public void AddNode () + { + var api = GetXmlApiDocument (); + var fixup = GetFixupXmlDocument (""); + + api.ApplyFixupFile (fixup); + + Assert.AreEqual ("", api.ApiDocument.ToString (SaveOptions.DisableFormatting).Replace ('\"', '\'')); + } + + [Test] + public void ChangeNode () + { + var api = GetXmlApiDocument (); + var fixup = GetFixupXmlDocument ("method"); + + api.ApplyFixupFile (fixup); + + Assert.AreEqual ("", api.ApiDocument.ToString (SaveOptions.DisableFormatting).Replace ('\"', '\'')); + } + + [Test] + public void MoveNode () + { + var api = GetXmlApiDocument (); + var fixup = GetFixupXmlDocument ("/api/package[@name='android']"); + + api.ApplyFixupFile (fixup); + + Assert.AreEqual ("", api.ApiDocument.ToString (SaveOptions.DisableFormatting).Replace ('\"', '\'')); + } + + [Test] + public void SetNewAttribute () + { + var api = GetXmlApiDocument (); + var fixup = GetFixupXmlDocument ("true"); + + api.ApplyFixupFile (fixup); + + Assert.AreEqual ("", api.ApiDocument.ToString (SaveOptions.DisableFormatting).Replace ('\"', '\'')); + } + + [Test] + public void ChangeAttribute () + { + var api = GetXmlApiDocument (); + var fixup = GetFixupXmlDocument ("android2"); + + api.ApplyFixupFile (fixup); + + Assert.AreEqual ("", api.ApiDocument.ToString (SaveOptions.DisableFormatting).Replace ('\"', '\'')); + } + + [Test] + public void RemoveAttribute () + { + var api = GetXmlApiDocument (); + var fixup = GetFixupXmlDocument (""); + + api.ApplyFixupFile (fixup); + + Assert.AreEqual ("", api.ApiDocument.ToString (SaveOptions.DisableFormatting).Replace ('\"', '\'')); + } + + ApiXmlDocument GetXmlApiDocument () + { + var api = ""; + + return new ApiXmlDocument (XDocument.Parse (api), "30", 0); + } + + FixupXmlDocument GetFixupXmlDocument (string text) + { + return new FixupXmlDocument (XDocument.Parse ("" + text + "")); + } + } +} diff --git a/tests/generator-Tests/Unit-Tests/ReportTests.cs b/tests/generator-Tests/Unit-Tests/ReportTests.cs index bd04a850d..cdb4925df 100644 --- a/tests/generator-Tests/Unit-Tests/ReportTests.cs +++ b/tests/generator-Tests/Unit-Tests/ReportTests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Java.Interop.Tools.Generator; using MonoDroid.Generation; using NUnit.Framework; diff --git a/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs b/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs index 77b0ccb1a..ba91ba96e 100644 --- a/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs +++ b/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs @@ -260,7 +260,7 @@ public void IgnoreKotlinInternalMembers () "); - var gens = new Parser (opt).Parse (xml, new List (), "0", 0); + var gens = XmlApiImporter.Parse (xml, opt); var klass = gens.Single (); Assert.AreEqual (0, klass.Fields.Count); diff --git a/tools/generator/CodeGenerationOptions.cs b/tools/generator/CodeGenerationOptions.cs index a2a3690bf..515b3585d 100644 --- a/tools/generator/CodeGenerationOptions.cs +++ b/tools/generator/CodeGenerationOptions.cs @@ -4,7 +4,7 @@ using System.IO; using System.Linq; using System.Text; - +using Java.Interop.Tools.Generator; using Java.Interop.Tools.JavaCallableWrappers; using Xamarin.Android.Binder; diff --git a/tools/generator/CodeGenerator.cs b/tools/generator/CodeGenerator.cs index 720582879..2f8fc1cc8 100644 --- a/tools/generator/CodeGenerator.cs +++ b/tools/generator/CodeGenerator.cs @@ -14,6 +14,7 @@ using Java.Interop.Tools.TypeNameMappings; using MonoDroid.Generation.Utilities; using Java.Interop.Tools.Generator.Transformation; +using Java.Interop.Tools.Generator; namespace Xamarin.Android.Binder { @@ -139,12 +140,25 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve fixups.Add (enum_metadata); } - Parser p = new Parser (opt); - List gens = p.Parse (apiXmlFile, fixups, api_level, product_version); - if (gens == null) { + // Load the API XML document + var api = ApiXmlDocument.Load (apiXmlFile, api_level, product_version); + + if (api is null) return; - } - apiSource = p.ApiSource; + + // Apply metadata fixups + foreach (var fixup in fixups) + api.ApplyFixupFile (fixup); + + api.ApiDocument.Save (apiXmlFile + ".fixed"); + + // Parse API XML + var gens = XmlApiImporter.Parse (api.ApiDocument, opt); + + if (gens is null) + return; + + apiSource = api.ApiSource; // disable interface default methods here, especially before validation. gens = gens.Where (g => !g.IsObfuscated && g.Visibility != "private").ToList (); diff --git a/tools/generator/CodeGeneratorOptions.cs b/tools/generator/CodeGeneratorOptions.cs index 8a601d4e2..81d42ff79 100644 --- a/tools/generator/CodeGeneratorOptions.cs +++ b/tools/generator/CodeGeneratorOptions.cs @@ -6,6 +6,7 @@ using Java.Interop.Tools.JavaSource; using MonoDroid.Generation; +using Java.Interop.Tools.Generator; namespace Xamarin.Android.Binder { diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs index 29fbb3e3a..f7cbfa234 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using generator.SourceWriters; +using Java.Interop.Tools.Generator; using Xamarin.Android.Binder; namespace MonoDroid.Generation diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs index e526a73e0..2a3238eb9 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs @@ -1,8 +1,10 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Xml; using System.Xml.Linq; +using Java.Interop.Tools.Generator; using Java.Interop.Tools.JavaCallableWrappers; using MonoDroid.Utils; using Xamarin.Android.Tools; @@ -13,6 +15,96 @@ class XmlApiImporter { static readonly Regex api_level = new Regex (@"api-(\d+).xml"); + public static List Parse (XDocument doc, CodeGenerationOptions options) + { + if (doc is null) + return null; + + var root = doc.Root; + + if ((root == null) || !root.HasElements) { + Report.LogCodedWarning (0, Report.WarningNoPackageElements); + return null; + } + + var gens = new List (); + + foreach (var elem in root.Elements ()) { + switch (elem.Name.LocalName) { + case "package": + gens.AddRange (ParsePackage (elem, options)); + break; + case "enum": + var name = elem.XGetAttribute ("name"); + var sym = new EnumSymbol (name); + options.SymbolTable.AddType (name, sym); + continue; + default: + Report.LogCodedWarning (0, Report.WarningUnexpectedRootChildNode, elem.Name.ToString ()); + break; + } + } + + return gens; + } + + public static List ParsePackage (XElement ns, CodeGenerationOptions options) + { + var result = new List (); + var nested = new Dictionary (); + var by_name = new Dictionary (); + + foreach (var elem in ns.Elements ()) { + + var name = elem.XGetAttribute ("name"); + GenBase gen = null; + + switch (elem.Name.LocalName) { + case "class": + if (elem.XGetAttribute ("obfuscated") == "true") + continue; + gen = CreateClass (ns, elem, options); + break; + case "interface": + if (elem.XGetAttribute ("obfuscated") == "true") + continue; + gen = CreateInterface (ns, elem, options); + break; + default: + Report.LogCodedWarning (0, Report.WarningUnexpectedPackageChildNode, elem.Name.ToString ()); + break; + } + + if (gen is null) + continue; + + var idx = name.IndexOf ('<'); + + if (idx > 0) + name = name.Substring (0, idx); + + by_name [name] = gen; + + if (name.IndexOf ('.') > 0) + nested [name] = gen; + else + result.Add (gen); + } + + foreach (var name in nested.Keys) { + var top_ancestor = name.Substring (0, name.IndexOf ('.')); + + if (by_name.ContainsKey (top_ancestor)) + by_name [top_ancestor].AddNestedType (nested [name]); + else { + Report.LogCodedWarning (0, Report.WarningNestedTypeAncestorNotFound, top_ancestor, nested [name].FullName); + nested [name].Invalidate (); + } + } + + return result; + } + public static ClassGen CreateClass (XElement pkg, XElement elem, CodeGenerationOptions options) { var klass = new ClassGen (CreateGenBaseSupport (pkg, elem, false)) { diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs index e65a9f296..7d31ba635 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Java.Interop.Tools.Generator; using Java.Interop.Tools.TypeNameMappings; using Xamarin.Android.Binder; diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs index a3ded000b..da6b2423d 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using MonoDroid.Utils; +using Java.Interop.Tools.Generator; namespace MonoDroid.Generation { diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index 75003763f..609b027cf 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Java.Interop.Tools.Generator; using MonoDroid.Generation.Utilities; namespace MonoDroid.Generation diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenericParameterDefinition.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenericParameterDefinition.cs index 9cf846206..e4a39e9ea 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenericParameterDefinition.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenericParameterDefinition.cs @@ -5,6 +5,7 @@ using System.Xml; using System.Xml.Linq; using System.Xml.XPath; +using Java.Interop.Tools.Generator; using Mono.Cecil; using Xamarin.Android.Tools; diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs index d7f5f4162..6158c9f57 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Java.Interop.Tools.Generator; using Xamarin.Android.Binder; namespace MonoDroid.Generation diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs index b43a2cea8..a9222d4ca 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Text; +using Java.Interop.Tools.Generator; using MonoDroid.Generation.Utilities; namespace MonoDroid.Generation diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs index 1fc7eb870..1c79726e0 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Xml; using System.Xml.Linq; +using Java.Interop.Tools.Generator; using Mono.Cecil; using Xamarin.Android.Binder; diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ReturnValue.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ReturnValue.cs index efb07e660..55d989d6a 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ReturnValue.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ReturnValue.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Xml; - +using Java.Interop.Tools.Generator; using MonoDroid.Utils; namespace MonoDroid.Generation { diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/ApiFixup.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/ApiFixup.cs index 7dc1f38ec..f9500d368 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/ApiFixup.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/ApiFixup.cs @@ -6,6 +6,7 @@ using System.Xml.Linq; using Xamarin.Android.Tools; +using Java.Interop.Tools.Generator; namespace MonoDroid.Generation { diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMap.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMap.cs index dc6250bb7..43d6f6513 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMap.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMap.cs @@ -5,6 +5,7 @@ using System.Xml; using Xamarin.Android; +using Java.Interop.Tools.Generator; namespace MonoDroid.Generation { diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/Parser.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/Parser.cs deleted file mode 100644 index 3ca272bc3..000000000 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/Parser.cs +++ /dev/null @@ -1,144 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml; -using System.Xml.Linq; -using Xamarin.Android.Tools; - -namespace MonoDroid.Generation -{ - public class Parser - { - readonly CodeGenerationOptions opt; - - public Parser (CodeGenerationOptions opt) - { - this.opt = opt; - } - - public string ApiSource { get; private set; } - - public XDocument Load (string filename) - { - XDocument doc = null; - - try { - doc = XDocument.Load (filename, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo); - } catch (XmlException e) { - Report.Verbose (0, "Exception: {0}", e); - Report.LogCodedWarning (0, Report.WarningInvalidXmlFile, e, filename, e.Message); - } - - return doc; - } - - public List Parse (string filename, IEnumerable fixups, string apiLevel, int productVersion) - { - var doc = Load (filename); - try { - return Parse (doc, fixups, apiLevel, productVersion); - } finally { - try { - doc.Save (filename + ".fixed"); - } catch { } // skip any error here. - } - } - - public List Parse (XDocument doc, IEnumerable fixups, string apiLevel, int productVersion) - { - if (doc == null) - return null; - try { - var apiFixup = new ApiFixup (doc); - apiFixup.Process (from fixup in fixups select Load (fixup), apiLevel, productVersion); - ApiSource = apiFixup.ApiSource; - } catch (XmlException ex) { - // BG4200 - Report.LogCodedError (Report.ErrorFailedToProcessMetadata, ex.Message); - return null; - } - - var root = doc.Root; - - if ((root == null) || !root.HasElements) { - Report.LogCodedWarning (0, Report.WarningNoPackageElements); - return null; - } - - List gens = new List (); - - foreach (var elem in root.Elements ()) { - switch (elem.Name.LocalName) { - case "package": - gens.AddRange (ParsePackage (elem)); - break; - case "enum": - ISymbol sym = new EnumSymbol (elem.XGetAttribute ("name")); - opt.SymbolTable.AddType (elem.XGetAttribute ("name"), sym); - continue; - default: - Report.LogCodedWarning (0, Report.WarningUnexpectedRootChildNode, elem.Name.ToString ()); - break; - } - } - - return gens; - } - - List ParsePackage (XElement ns) - { - return ParsePackage (ns, null); - } - - List ParsePackage (XElement ns, Predicate p) - { - List result = new List (); - Dictionary nested = new Dictionary (); - Dictionary by_name = new Dictionary (); - - foreach (var elem in ns.Elements ()) { - - string name = elem.XGetAttribute ("name"); - GenBase gen = null; - switch (elem.Name.LocalName) { - case "class": - if (elem.XGetAttribute ("obfuscated") == "true") - continue; - gen = XmlApiImporter.CreateClass (ns, elem, opt); - break; - case "interface": - if (elem.XGetAttribute ("obfuscated") == "true") - continue; - gen = XmlApiImporter.CreateInterface (ns, elem, opt); - break; - default: - Report.LogCodedWarning (0, Report.WarningUnexpectedPackageChildNode, elem.Name.ToString ()); - break; - } - - if (gen == null) - continue; - int idx = name.IndexOf ('<'); - if (idx > 0) - name = name.Substring (0, idx); - by_name [name] = gen; - if (name.IndexOf ('.') > 0) - nested [name] = gen; - else - result.Add (gen); - } - - foreach (string name in nested.Keys) { - string top_ancestor = name.Substring (0, name.IndexOf ('.')); - if (by_name.ContainsKey (top_ancestor)) - by_name [top_ancestor].AddNestedType (nested [name]); - else { - Report.LogCodedWarning (0, Report.WarningNestedTypeAncestorNotFound, top_ancestor, nested [name].FullName); - nested [name].Invalidate (); - } - } - return result; - } - } -} diff --git a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs index e92eb0b0b..fc7a94b86 100644 --- a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs +++ b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Java.Interop.Tools.Generator; using MonoDroid.Generation; using Xamarin.SourceWriter; diff --git a/tools/generator/SourceWriters/InterfaceMemberAlternativeClass.cs b/tools/generator/SourceWriters/InterfaceMemberAlternativeClass.cs index 2dddb1674..a427529d0 100644 --- a/tools/generator/SourceWriters/InterfaceMemberAlternativeClass.cs +++ b/tools/generator/SourceWriters/InterfaceMemberAlternativeClass.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Java.Interop.Tools.Generator; using MonoDroid.Generation; using Xamarin.SourceWriter;