Skip to content

Commit

Permalink
Initial work on rd.xml parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
tomcashman committed Jan 15, 2022
1 parent 6ccd249 commit 55100bd
Show file tree
Hide file tree
Showing 28 changed files with 1,292 additions and 0 deletions.
20 changes: 20 additions & 0 deletions RdXml.Test/RdXml.Test.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\RdXml\RdXml.csproj" />
</ItemGroup>

</Project>
40 changes: 40 additions & 0 deletions RdXml.Test/TypeTests.cs
Original file line number Diff line number Diff line change
@@ -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 = @"<Directives xmlns=""http://schemas.microsoft.com/netfx/2013/01/metadata\"">
<Application>
<Type Name=""Dictionary"">
<Subtypes Activate=""Public"" Dynamic=""Public""/>
</Type>
</Application>
</Directives>";

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);
}
}
}
85 changes: 85 additions & 0 deletions RdXml/RdAssembly.cs
Original file line number Diff line number Diff line change
@@ -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<Type> 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<Type> 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);
}
}
}
}
30 changes: 30 additions & 0 deletions RdXml/RdAttributeImplies.cs
Original file line number Diff line number Diff line change
@@ -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<Type> writtenTypes)
{
throw new NotImplementedException();
}
}
}
86 changes: 86 additions & 0 deletions RdXml/RdDirective.cs
Original file line number Diff line number Diff line change
@@ -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<RdDll> Libraries { get; } = new List<RdDll>();

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<Type> writtenTypes = new HashSet<Type>();
WriteNativeAOT(result, result.DocumentElement, writtenTypes);
result.Save(outputStream);
}

public override void WriteNativeAOT(XmlDocument result, XmlElement parentElement, HashSet<Type> 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);
}
}
}
71 changes: 71 additions & 0 deletions RdXml/RdDll.cs
Original file line number Diff line number Diff line change
@@ -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<RdAssembly> Assemblies { get; } = new List<RdAssembly>();
public List<RdNamespace> Namespaces { get; } = new List<RdNamespace>();
public List<RdType> Types { get; } = new List<RdType>();
public List<RdTypeInstantiation> TypeInstantiations { get; } = new List<RdTypeInstantiation>();

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<Type> 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);
}
}
}
}
Loading

0 comments on commit 55100bd

Please sign in to comment.