diff --git a/RdXml.Test/RdXml.Test.csproj b/RdXml.Test/RdXml.Test.csproj new file mode 100644 index 0000000..35b65d2 --- /dev/null +++ b/RdXml.Test/RdXml.Test.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + + diff --git a/RdXml.Test/TypeTests.cs b/RdXml.Test/TypeTests.cs new file mode 100644 index 0000000..9b2e470 --- /dev/null +++ b/RdXml.Test/TypeTests.cs @@ -0,0 +1,40 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml.Test +{ + [TestClass] + public class TypeTests + { + [TestMethod] + public void TestSubType() + { + string inputXml = @" + + + + + + "; + + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(inputXml); + RdDirective directive = new RdDirective(xmlDocument); + Assert.IsNotNull(directive.Application); + Assert.AreEqual(1, directive.Application.Types.Count); + Assert.IsNotNull(directive.Application.Types[0].SubTypes); + } + } +} diff --git a/RdXml/RdAssembly.cs b/RdXml/RdAssembly.cs new file mode 100644 index 0000000..732958c --- /dev/null +++ b/RdXml/RdAssembly.cs @@ -0,0 +1,85 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using System.Linq; + +namespace RdXml +{ + public class RdAssembly : RdNamespace + { + public new const string ELEMENT_TAG = "Assembly"; + + public RdAssembly(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + } + + public override void WriteNativeAOT(XmlDocument xmlDocument, XmlElement parentElement, HashSet writtenTypes) + { + string assemblyName = AssemblyName; + + XmlElement xmlElement = xmlDocument.CreateElement(ELEMENT_TAG); + xmlElement.SetAttribute(ATTRIBUTE_NAME, assemblyName); + xmlDocument.AppendChild(xmlElement); + + if (HasReflectAttribute) + { + xmlElement.SetAttribute(ATTRIBUTE_DYNAMIC, VALUE_REQUIRED_ALL); + } + if(HasMarshalDelegateAttribute || HasMarshalStructureAttribute) + { + IEnumerable delegates = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(t => t.GetTypes()) + .Where(t => !t.IsClass && t.Assembly.FullName == assemblyName); + foreach (Type type in delegates) + { + if (!writtenTypes.Add(type)) + { + continue; + } + XmlElement delegateElement = xmlDocument.CreateElement(RdType.ELEMENT_TAG); + delegateElement.SetAttribute(RdElement.ATTRIBUTE_NAME, type.FullName); + if (HasMarshalDelegateAttribute) + { + delegateElement.SetAttribute(RdElement.ATTRIBUTE_MARSHAL_DELEGATE, "Required All"); + } + if (HasMarshalStructureAttribute) + { + delegateElement.SetAttribute(RdElement.ATTRIBUTE_MARSHAL_STRUCTURE, "Required All"); + } + xmlElement.AppendChild(delegateElement); + } + } + + foreach (RdNamespace @namespace in Namespaces) + { + @namespace.WriteNativeAOT(xmlDocument, parentElement, writtenTypes); + } + foreach (RdType type in Types) + { + type.WriteNativeAOT(xmlDocument, parentElement, writtenTypes); + } + foreach (RdTypeInstantiation typeInstantiation in TypeInstantiations) + { + typeInstantiation.WriteNativeAOT(xmlDocument, parentElement, writtenTypes); + } + } + + public new string AssemblyName + { + get + { + return XmlElement.GetAttribute(ATTRIBUTE_NAME); + } + } + } +} diff --git a/RdXml/RdAttributeImplies.cs b/RdXml/RdAttributeImplies.cs new file mode 100644 index 0000000..cd0fdbe --- /dev/null +++ b/RdXml/RdAttributeImplies.cs @@ -0,0 +1,30 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdAttributeImplies : RdElement + { + public const string ELEMENT_TAG = "AttributeImplies"; + + public RdAttributeImplies(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + } + + public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes) + { + throw new NotImplementedException(); + } + } +} diff --git a/RdXml/RdDirective.cs b/RdXml/RdDirective.cs new file mode 100644 index 0000000..0a3ac12 --- /dev/null +++ b/RdXml/RdDirective.cs @@ -0,0 +1,86 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdDirective : RdElement + { + public const string ELEMENT_TAG = "Directives"; + public const string APPLICATION_TAG = "Application"; + public const string LIBRARY_TAG = "Library"; + + public RdDll Application { get; private set; } + public List Libraries { get; } = new List(); + + public RdDirective(XmlDocument xmlDocument) : base(null, xmlDocument.DocumentElement) + { + XmlNodeList applicationNodeList = xmlDocument.GetElementsByTagName(APPLICATION_TAG); + if(applicationNodeList.Count > 0) + { + Application = new RdDll(this, (XmlElement) applicationNodeList[0]); + } + + XmlNodeList libraryNodeList = xmlDocument.GetElementsByTagName(LIBRARY_TAG); + foreach(XmlNode xmlNode in libraryNodeList) + { + Libraries.Add(new RdDll(this, (XmlElement) xmlNode)); + } + } + + public void WriteNativeAOT(Stream outputStream) + { + XmlDocument result = new XmlDocument(); + HashSet writtenTypes = new HashSet(); + WriteNativeAOT(result, result.DocumentElement, writtenTypes); + result.Save(outputStream); + } + + public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes) + { + XmlElement rootElement = result.CreateElement(ELEMENT_TAG); + result.AppendChild(rootElement); + + if(Application != null) + { + Application.WriteNativeAOT(result, rootElement, writtenTypes); + } + foreach(RdDll dll in Libraries) + { + dll.WriteNativeAOT(result, rootElement, writtenTypes); + } + } + + public static RdDirective FromStream(Stream stream) + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(stream); + return new RdDirective(xmlDocument); + } + + public static RdDirective FromTextReader(TextReader textReader) + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(textReader); + return new RdDirective(xmlDocument); + } + + public static RdDirective FromXmlReader(XmlReader xmlReader) + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(xmlReader); + return new RdDirective(xmlDocument); + } + } +} diff --git a/RdXml/RdDll.cs b/RdXml/RdDll.cs new file mode 100644 index 0000000..e5f8674 --- /dev/null +++ b/RdXml/RdDll.cs @@ -0,0 +1,71 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdDll : RdElement + { + public List Assemblies { get; } = new List(); + public List Namespaces { get; } = new List(); + public List Types { get; } = new List(); + public List TypeInstantiations { get; } = new List(); + + public RdDll(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + XmlNodeList assemblyNodeList = xmlElement.GetElementsByTagName(RdAssembly.ELEMENT_TAG); + foreach(XmlNode assemblyNode in assemblyNodeList) + { + Assemblies.Add(new RdAssembly(this, (XmlElement) assemblyNode)); + } + XmlNodeList namespaceList = xmlElement.GetElementsByTagName(RdNamespace.ELEMENT_TAG); + foreach (XmlNode namespaceNode in namespaceList) + { + Namespaces.Add(new RdNamespace(this, (XmlElement)namespaceNode)); + } + XmlNodeList typeList = xmlElement.GetElementsByTagName(RdType.ELEMENT_TAG); + foreach (XmlNode typeNode in typeList) + { + Types.Add(new RdType(this, (XmlElement)typeNode)); + } + XmlNodeList typeInstantiationList = xmlElement.GetElementsByTagName(RdTypeInstantiation.ELEMENT_TAG); + foreach (XmlNode typeInstantiationNode in typeInstantiationList) + { + TypeInstantiations.Add(new RdTypeInstantiation(this, (XmlElement)typeInstantiationNode)); + } + } + + public override void WriteNativeAOT(XmlDocument xmlDocument, XmlElement parentElement, HashSet writtenTypes) + { + XmlElement xmlElement = xmlDocument.CreateElement(XmlElement.Name); + parentElement.AppendChild(xmlElement); + + foreach(RdAssembly assembly in Assemblies) + { + assembly.WriteNativeAOT(xmlDocument, xmlElement, writtenTypes); + } + foreach(RdNamespace @namespace in Namespaces) + { + @namespace.WriteNativeAOT(xmlDocument, xmlElement, writtenTypes); + } + foreach(RdType type in Types) + { + type.WriteNativeAOT(xmlDocument, xmlElement, writtenTypes); + } + foreach(RdTypeInstantiation typeInstantiation in TypeInstantiations) + { + typeInstantiation.WriteNativeAOT(xmlDocument, xmlElement, writtenTypes); + } + } + } +} diff --git a/RdXml/RdElement.cs b/RdXml/RdElement.cs new file mode 100644 index 0000000..c9f6af8 --- /dev/null +++ b/RdXml/RdElement.cs @@ -0,0 +1,103 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public abstract class RdElement + { + public const string ATTRIBUTE_NAME = "Name"; + public const string ATTRIBUTE_ACTIVATE = "Activate"; + public const string ATTRIBUTE_BROWSE = "Browse"; + public const string ATTRIBUTE_DYNAMIC = "Dynamic"; + public const string ATTRIBUTE_SERIALIZE = "Serialize"; + public const string ATTRIBUTE_DATA_CONTRACT_SERIALIZER = "DataContractSerializer"; + public const string ATTRIBUTE_DATA_CONTRACT_JSON_SERIALIZER = "DataContractJsonSerializer"; + public const string ATTRIBUTE_XML_SERIALIZER = "XmlSerializer"; + public const string ATTRIBUTE_MARSHAL_OBJECT = "MarshalObject"; + public const string ATTRIBUTE_MARSHAL_DELEGATE = "MarshalDelegate"; + public const string ATTRIBUTE_MARSHAL_STRUCTURE = "MarshalStructure"; + public const string VALUE_REQUIRED_ALL = "Required All"; + + protected RdElement Parent { get; } + protected XmlElement XmlElement { get; } + + public RdElement(RdElement parent, XmlElement xmlElement) + { + Parent = parent; + XmlElement = xmlElement; + } + + public abstract void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes); + + public bool HasReflectAttribute + { + get + { + if(XmlElement.HasAttribute(ATTRIBUTE_ACTIVATE)) + { + return true; + } + if (XmlElement.HasAttribute(ATTRIBUTE_BROWSE)) + { + return true; + } + if (XmlElement.HasAttribute(ATTRIBUTE_DYNAMIC)) + { + return true; + } + if (XmlElement.HasAttribute(ATTRIBUTE_SERIALIZE)) + { + return true; + } + if (XmlElement.HasAttribute(ATTRIBUTE_DATA_CONTRACT_SERIALIZER)) + { + return true; + } + if (XmlElement.HasAttribute(ATTRIBUTE_DATA_CONTRACT_JSON_SERIALIZER)) + { + return true; + } + if (XmlElement.HasAttribute(ATTRIBUTE_XML_SERIALIZER)) + { + return true; + } + return false; + } + } + + public bool HasMarshalDelegateAttribute + { + get + { + if(XmlElement.HasAttribute(ATTRIBUTE_MARSHAL_OBJECT)) + { + return true; + } + return XmlElement.HasAttribute(ATTRIBUTE_MARSHAL_DELEGATE); + } + } + + public bool HasMarshalStructureAttribute + { + get + { + if (XmlElement.HasAttribute(ATTRIBUTE_MARSHAL_OBJECT)) + { + return true; + } + return XmlElement.HasAttribute(ATTRIBUTE_MARSHAL_STRUCTURE); + } + } + } +} diff --git a/RdXml/RdEvent.cs b/RdXml/RdEvent.cs new file mode 100644 index 0000000..d9eb2fc --- /dev/null +++ b/RdXml/RdEvent.cs @@ -0,0 +1,30 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdEvent : RdElement + { + public const string ELEMENT_TAG = "Event"; + + public RdEvent(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + } + + public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes) + { + throw new NotImplementedException(); + } + } +} diff --git a/RdXml/RdField.cs b/RdXml/RdField.cs new file mode 100644 index 0000000..d7c2bda --- /dev/null +++ b/RdXml/RdField.cs @@ -0,0 +1,30 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdField : RdElement + { + public const string ELEMENT_TAG = "Field"; + + public RdField(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + } + + public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes) + { + throw new NotImplementedException(); + } + } +} diff --git a/RdXml/RdGenericParameter.cs b/RdXml/RdGenericParameter.cs new file mode 100644 index 0000000..1ce535d --- /dev/null +++ b/RdXml/RdGenericParameter.cs @@ -0,0 +1,30 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdGenericParameter : RdElement + { + public const string ELEMENT_TAG = "GenericParameter"; + + public RdGenericParameter(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + } + + public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes) + { + throw new NotImplementedException(); + } + } +} diff --git a/RdXml/RdMethod.cs b/RdXml/RdMethod.cs new file mode 100644 index 0000000..606b643 --- /dev/null +++ b/RdXml/RdMethod.cs @@ -0,0 +1,30 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdMethod : RdElement + { + public const string ELEMENT_TAG = "Method"; + + public RdMethod(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + } + + public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes) + { + throw new NotImplementedException(); + } + } +} diff --git a/RdXml/RdMethodInstantiation.cs b/RdXml/RdMethodInstantiation.cs new file mode 100644 index 0000000..a5ffe54 --- /dev/null +++ b/RdXml/RdMethodInstantiation.cs @@ -0,0 +1,30 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdMethodInstantiation : RdElement + { + public const string ELEMENT_TAG = "MethodInstantiation"; + + public RdMethodInstantiation(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + } + + public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes) + { + throw new NotImplementedException(); + } + } +} diff --git a/RdXml/RdNamespace.cs b/RdXml/RdNamespace.cs new file mode 100644 index 0000000..7a68ce4 --- /dev/null +++ b/RdXml/RdNamespace.cs @@ -0,0 +1,165 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using System.Linq; + +namespace RdXml +{ + public class RdNamespace : RdElement + { + public const string ELEMENT_TAG = "Namespace"; + + public List Namespaces { get; } = new List(); + public List Types { get; } = new List(); + public List TypeInstantiations { get; } = new List(); + + public RdNamespace(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + XmlNodeList namespaceList = xmlElement.GetElementsByTagName(RdNamespace.ELEMENT_TAG); + foreach (XmlNode namespaceNode in namespaceList) + { + Namespaces.Add(new RdNamespace(this, (XmlElement)namespaceNode)); + } + XmlNodeList typeList = xmlElement.GetElementsByTagName(RdType.ELEMENT_TAG); + foreach (XmlNode typeNode in typeList) + { + Types.Add(new RdType(this, (XmlElement)typeNode)); + } + XmlNodeList typeInstantiationList = xmlElement.GetElementsByTagName(RdTypeInstantiation.ELEMENT_TAG); + foreach (XmlNode typeInstantiationNode in typeInstantiationList) + { + TypeInstantiations.Add(new RdTypeInstantiation(this, (XmlElement)typeInstantiationNode)); + } + } + + public override void WriteNativeAOT(XmlDocument xmlDocument, XmlElement parentElement, HashSet writtenTypes) + { + string namespaceName = NamespaceName; + string assemblyName = AssemblyName; + + foreach (RdNamespace @namespace in Namespaces) + { + @namespace.WriteNativeAOT(xmlDocument, parentElement, writtenTypes); + } + foreach (RdType type in Types) + { + type.WriteNativeAOT(xmlDocument, parentElement, writtenTypes); + } + foreach (RdTypeInstantiation typeInstantiation in TypeInstantiations) + { + typeInstantiation.WriteNativeAOT(xmlDocument, parentElement, writtenTypes); + } + + //Only write other Namespace types after explicit declarations + WriteNativeAOTTypes(xmlDocument, parentElement, writtenTypes, namespaceName, assemblyName); + WriteNativeAOTDelegates(xmlDocument, parentElement, writtenTypes, namespaceName); + } + + private void WriteNativeAOTTypes(XmlDocument xmlDocument, XmlElement parentElement, HashSet writtenTypes, string namespaceName, string assemblyName) + { + IEnumerable classes; + if (!string.IsNullOrEmpty(assemblyName)) + { + classes = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(t => t.GetTypes()) + .Where(t => t.IsClass && t.Namespace == namespaceName && t.Assembly.FullName == assemblyName); + } + else + { + classes = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(t => t.GetTypes()) + .Where(t => t.IsClass && t.Namespace == namespaceName); + } + + foreach (Type type in classes) + { + if (!writtenTypes.Add(type)) + { + continue; + } + XmlElement typeElement = xmlDocument.CreateElement(RdType.ELEMENT_TAG); + typeElement.SetAttribute(RdElement.ATTRIBUTE_NAME, type.FullName); + if(HasReflectAttribute) + { + typeElement.SetAttribute(RdElement.ATTRIBUTE_DYNAMIC, VALUE_REQUIRED_ALL); + } + parentElement.AppendChild(typeElement); + } + } + + private void WriteNativeAOTDelegates(XmlDocument xmlDocument, XmlElement parentElement, HashSet writtenTypes, string namespaceName) + { + IEnumerable delegates = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(t => t.GetTypes()) + .Where(t => !t.IsClass && t.Namespace == namespaceName); + foreach (Type type in delegates) + { + if (!writtenTypes.Add(type)) + { + continue; + } + XmlElement delegateElement = xmlDocument.CreateElement(RdType.ELEMENT_TAG); + delegateElement.SetAttribute(RdElement.ATTRIBUTE_NAME, type.FullName); + if (HasMarshalDelegateAttribute) + { + delegateElement.SetAttribute(RdElement.ATTRIBUTE_MARSHAL_DELEGATE, VALUE_REQUIRED_ALL); + } + if (HasMarshalStructureAttribute) + { + delegateElement.SetAttribute(RdElement.ATTRIBUTE_MARSHAL_STRUCTURE, VALUE_REQUIRED_ALL); + } + parentElement.AppendChild(delegateElement); + } + } + + public string NamespaceName + { + get + { + StringBuilder result = new StringBuilder(); + string thisName = XmlElement.GetAttribute(ATTRIBUTE_NAME); + if (Parent is RdNamespace @namespace && !(Parent is RdAssembly)) + { + string parentNamespace = @namespace.NamespaceName; + if(!thisName.StartsWith(parentNamespace)) + { + result.Append(parentNamespace); + if (!parentNamespace.EndsWith(".")) + { + result.Append('.'); + } + } + } + result.Append(thisName); + return result.ToString(); + } + } + + public string AssemblyName + { + get + { + if (Parent is RdAssembly assembly) + { + return assembly.AssemblyName; + } + if (Parent is RdNamespace @namespace) + { + return @namespace.AssemblyName; + } + return ""; + } + } + + } +} diff --git a/RdXml/RdProperty.cs b/RdXml/RdProperty.cs new file mode 100644 index 0000000..3e6b981 --- /dev/null +++ b/RdXml/RdProperty.cs @@ -0,0 +1,30 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdProperty : RdElement + { + public const string ELEMENT_TAG = "Property"; + + public RdProperty(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + } + + public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes) + { + throw new NotImplementedException(); + } + } +} diff --git a/RdXml/RdSubtypes.cs b/RdXml/RdSubtypes.cs new file mode 100644 index 0000000..b4dc92b --- /dev/null +++ b/RdXml/RdSubtypes.cs @@ -0,0 +1,30 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdSubtypes : RdElement + { + public const string ELEMENT_TAG = "Subtypes"; + + public RdSubtypes(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + } + + public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet writtenTypes) + { + throw new NotImplementedException(); + } + } +} diff --git a/RdXml/RdType.cs b/RdXml/RdType.cs new file mode 100644 index 0000000..50abb6f --- /dev/null +++ b/RdXml/RdType.cs @@ -0,0 +1,51 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdType : RdTypeInstantiation + { + public new const string ELEMENT_TAG = "Type"; + + public RdSubtypes SubTypes { get; private set; } + public RdAttributeImplies AttributeImplies { get; private set; } + public List GenericParameters { get; } = new List(); + + public RdType(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + XmlNodeList subtypeList = xmlElement.GetElementsByTagName(RdSubtypes.ELEMENT_TAG); + if(subtypeList.Count > 0) + { + SubTypes = new RdSubtypes(this, (XmlElement)subtypeList[0]); + } + + XmlNodeList attributeImplesList = xmlElement.GetElementsByTagName(RdAttributeImplies.ELEMENT_TAG); + if (attributeImplesList.Count > 0) + { + AttributeImplies = new RdAttributeImplies(this, (XmlElement)attributeImplesList[0]); + } + + XmlNodeList genericParametersList = xmlElement.GetElementsByTagName(RdGenericParameter.ELEMENT_TAG); + foreach (XmlNode genericParameterNode in genericParametersList) + { + GenericParameters.Add(new RdGenericParameter(this, (XmlElement)genericParameterNode)); + } + } + + public override void WriteNativeAOT(XmlDocument xmlDocument, XmlElement parentElement, HashSet writtenTypes) + { + base.WriteNativeAOT(xmlDocument, parentElement, writtenTypes); + } + } +} diff --git a/RdXml/RdTypeInstantiation.cs b/RdXml/RdTypeInstantiation.cs new file mode 100644 index 0000000..502fb79 --- /dev/null +++ b/RdXml/RdTypeInstantiation.cs @@ -0,0 +1,122 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace RdXml +{ + public class RdTypeInstantiation : RdElement + { + public const string ELEMENT_TAG = "TypeInstantiation"; + + public List Types { get; } = new List(); + public List TypeInstantiations { get; } = new List(); + public List Methods { get; } = new List(); + public List MethodInstantiations { get; } = new List(); + public List Properties { get; } = new List(); + public List Fields { get; } = new List(); + public List Events { get; } = new List(); + + public RdTypeInstantiation(RdElement parent, XmlElement xmlElement) : base(parent, xmlElement) + { + XmlNodeList typeList = xmlElement.GetElementsByTagName(RdType.ELEMENT_TAG); + foreach (XmlNode typeNode in typeList) + { + Types.Add(new RdType(this, (XmlElement)typeNode)); + } + + XmlNodeList typeInstantiationList = xmlElement.GetElementsByTagName(RdTypeInstantiation.ELEMENT_TAG); + foreach (XmlNode typeInstantiationNode in typeInstantiationList) + { + TypeInstantiations.Add(new RdTypeInstantiation(this, (XmlElement)typeInstantiationNode)); + } + + XmlNodeList methodList = xmlElement.GetElementsByTagName(RdMethod.ELEMENT_TAG); + foreach (XmlNode methodNode in methodList) + { + Methods.Add(new RdMethod(this, (XmlElement)methodNode)); + } + + XmlNodeList methodInstantiationList = xmlElement.GetElementsByTagName(RdMethodInstantiation.ELEMENT_TAG); + foreach (XmlNode methodInstantiationNode in methodInstantiationList) + { + MethodInstantiations.Add(new RdMethodInstantiation(this, (XmlElement)methodInstantiationNode)); + } + + XmlNodeList propertyList = xmlElement.GetElementsByTagName(RdProperty.ELEMENT_TAG); + foreach (XmlNode propertyNode in propertyList) + { + Properties.Add(new RdProperty(this, (XmlElement)propertyNode)); + } + + XmlNodeList fieldList = xmlElement.GetElementsByTagName(RdField.ELEMENT_TAG); + foreach (XmlNode fieldNode in fieldList) + { + Fields.Add(new RdField(this, (XmlElement)fieldNode)); + } + + XmlNodeList eventList = xmlElement.GetElementsByTagName(RdEvent.ELEMENT_TAG); + foreach (XmlNode eventNode in eventList) + { + Events.Add(new RdEvent(this, (XmlElement)eventNode)); + } + } + + public override void WriteNativeAOT(XmlDocument xmlDocument, XmlElement parentElement, HashSet writtenTypes) + { + string typeName = TypeName; + Type resolvedType = Type.GetType(typeName); + if (writtenTypes.Add(resolvedType)) + { + XmlElement xmlElement = xmlDocument.CreateElement(ELEMENT_TAG); + xmlElement.SetAttribute(ATTRIBUTE_NAME, TypeName); + xmlDocument.AppendChild(xmlElement); + + if (HasReflectAttribute) + { + xmlElement.SetAttribute(RdElement.ATTRIBUTE_DYNAMIC, VALUE_REQUIRED_ALL); + } + if (HasMarshalDelegateAttribute) + { + xmlElement.SetAttribute(RdElement.ATTRIBUTE_MARSHAL_DELEGATE, VALUE_REQUIRED_ALL); + } + if (HasMarshalStructureAttribute) + { + xmlElement.SetAttribute(RdElement.ATTRIBUTE_MARSHAL_STRUCTURE, VALUE_REQUIRED_ALL); + } + } + } + + public string TypeName + { + get + { + StringBuilder result = new StringBuilder(); + string thisName = XmlElement.GetAttribute(ATTRIBUTE_NAME); + if (Parent is RdNamespace @namespace && !(Parent is RdAssembly)) + { + string parentNamespace = @namespace.NamespaceName; + if (!thisName.StartsWith(parentNamespace)) + { + result.Append(parentNamespace); + if (!parentNamespace.EndsWith(".")) + { + result.Append('.'); + } + } + } + result.Append(thisName); + return result.ToString(); + } + } + } +} diff --git a/RdXml/RdXml.csproj b/RdXml/RdXml.csproj new file mode 100644 index 0000000..040842f --- /dev/null +++ b/RdXml/RdXml.csproj @@ -0,0 +1,7 @@ + + + + netstandard20 + + + diff --git a/RdXmlConverter.Core/CliOptions.cs b/RdXmlConverter.Core/CliOptions.cs new file mode 100644 index 0000000..a3ab4b6 --- /dev/null +++ b/RdXmlConverter.Core/CliOptions.cs @@ -0,0 +1,26 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using CommandLine; +using System; +using System.Collections.Generic; +using System.Text; + +namespace RdXmlConverter +{ + class CliOptions + { + [Option("rdxml", Required = true, HelpText = "Input UWP rd.xml file")] + public string InputRdXml { get; set; } + [Option('o', "output", Required = true, HelpText = "Output NativeAOT rd.xml file")] + public string OutputRdXml { get; set; } + [Option('i', "input", Required = true, HelpText = "Input directory containing DLLs")] + public string InputDllDirectory { get; set; } + } +} diff --git a/RdXmlConverter.Core/Program.cs b/RdXmlConverter.Core/Program.cs new file mode 100644 index 0000000..495f9e0 --- /dev/null +++ b/RdXmlConverter.Core/Program.cs @@ -0,0 +1,55 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using CommandLine; +using System; +using System.IO; +using System.Reflection; +using System.Xml; + +namespace RdXmlConverter +{ + class Program + { + static void Main(string[] args) + { + Parser.Default.ParseArguments(args) + .WithParsed(options => + { + if(!Directory.Exists(options.InputDllDirectory)) + { + Console.Error.WriteLine(options.InputDllDirectory + " is not a directory"); + return; + } + + Run(options); + }); + } + + static void Run(CliOptions options) + { + string [] dlls = Directory.GetFiles(options.InputDllDirectory, "*.dll"); + if(dlls.Length == 0) + { + Console.Error.WriteLine("No DLLs in specified directory"); + return; + } + foreach(string dllFilename in dlls) + { + Assembly.LoadFrom(dllFilename); + } + + XmlDocument doc = new XmlDocument(); + doc.PreserveWhitespace = true; + doc.Load(options.InputRdXml); + + + } + } +} diff --git a/RdXmlConverter.Core/RdXmlConverter.Core.csproj b/RdXmlConverter.Core/RdXmlConverter.Core.csproj new file mode 100644 index 0000000..41e7dad --- /dev/null +++ b/RdXmlConverter.Core/RdXmlConverter.Core.csproj @@ -0,0 +1,16 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + diff --git a/RdXmlConverter.Framework/App.config b/RdXmlConverter.Framework/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/RdXmlConverter.Framework/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/RdXmlConverter.Framework/CliOptions.cs b/RdXmlConverter.Framework/CliOptions.cs new file mode 100644 index 0000000..a9527bc --- /dev/null +++ b/RdXmlConverter.Framework/CliOptions.cs @@ -0,0 +1,28 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using CommandLine; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RdXmlConverter.Framework +{ + class CliOptions + { + [Option("rdxml", Required = true, HelpText = "Input UWP rd.xml file")] + public string InputRdXml { get; set; } + [Option('o', "output", Required = true, HelpText = "Output NativeAOT rd.xml file")] + public string OutputRdXml { get; set; } + [Option('i', "input", Required = true, HelpText = "Input directory containing DLLs")] + public string InputDllDirectory { get; set; } + } +} diff --git a/RdXmlConverter.Framework/Program.cs b/RdXmlConverter.Framework/Program.cs new file mode 100644 index 0000000..cfed55f --- /dev/null +++ b/RdXmlConverter.Framework/Program.cs @@ -0,0 +1,24 @@ +/** + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * Copyright 2022 Thomas Cashman + * + * See LICENSE file + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RdXmlConverter.Framework +{ + class Program + { + static void Main(string[] args) + { + } + } +} diff --git a/RdXmlConverter.Framework/Properties/AssemblyInfo.cs b/RdXmlConverter.Framework/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0b47a1d --- /dev/null +++ b/RdXmlConverter.Framework/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RdXmlConverter.Framework")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RdXmlConverter.Framework")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b4722dd2-7267-4c70-826c-1daba067797a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/RdXmlConverter.Framework/RdXmlConverter.Framework.csproj b/RdXmlConverter.Framework/RdXmlConverter.Framework.csproj new file mode 100644 index 0000000..88e7e2e --- /dev/null +++ b/RdXmlConverter.Framework/RdXmlConverter.Framework.csproj @@ -0,0 +1,64 @@ + + + + + Debug + AnyCPU + {B4722DD2-7267-4C70-826C-1DABA067797A} + Exe + RdXmlConverter.Framework + RdXmlConverter.Framework + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\CommandLineParser.2.8.0\lib\net461\CommandLine.dll + + + + + + + + + + + + + + + + + + + + + + {dc9c03bd-4ee5-470e-a3a5-9f3b5185f47d} + RdXml + + + + \ No newline at end of file diff --git a/RdXmlConverter.Framework/packages.config b/RdXmlConverter.Framework/packages.config new file mode 100644 index 0000000..3eb2507 --- /dev/null +++ b/RdXmlConverter.Framework/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/RdXmlConverter.sln b/RdXmlConverter.sln new file mode 100644 index 0000000..c0b108f --- /dev/null +++ b/RdXmlConverter.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32106.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RdXml", "RdXml\RdXml.csproj", "{DC9C03BD-4EE5-470E-A3A5-9F3B5185F47D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RdXmlConverter.Core", "RdXmlConverter.Core\RdXmlConverter.Core.csproj", "{3E798DE6-CFDB-4E98-89D1-CD148E6673CB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RdXmlConverter.Framework", "RdXmlConverter.Framework\RdXmlConverter.Framework.csproj", "{B4722DD2-7267-4C70-826C-1DABA067797A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RdXml.Test", "RdXml.Test\RdXml.Test.csproj", "{75C11015-6C03-4CAD-B343-6A7A5148D686}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DC9C03BD-4EE5-470E-A3A5-9F3B5185F47D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC9C03BD-4EE5-470E-A3A5-9F3B5185F47D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC9C03BD-4EE5-470E-A3A5-9F3B5185F47D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC9C03BD-4EE5-470E-A3A5-9F3B5185F47D}.Release|Any CPU.Build.0 = Release|Any CPU + {3E798DE6-CFDB-4E98-89D1-CD148E6673CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E798DE6-CFDB-4E98-89D1-CD148E6673CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E798DE6-CFDB-4E98-89D1-CD148E6673CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E798DE6-CFDB-4E98-89D1-CD148E6673CB}.Release|Any CPU.Build.0 = Release|Any CPU + {B4722DD2-7267-4C70-826C-1DABA067797A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4722DD2-7267-4C70-826C-1DABA067797A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4722DD2-7267-4C70-826C-1DABA067797A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4722DD2-7267-4C70-826C-1DABA067797A}.Release|Any CPU.Build.0 = Release|Any CPU + {75C11015-6C03-4CAD-B343-6A7A5148D686}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75C11015-6C03-4CAD-B343-6A7A5148D686}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75C11015-6C03-4CAD-B343-6A7A5148D686}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75C11015-6C03-4CAD-B343-6A7A5148D686}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F94CFE0E-08C4-4ACB-B922-020BA757204C} + EndGlobalSection +EndGlobal