Add XML Serialization classes #557
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
XML Serialization
When the ClangSharp P/Invoke generator operates in output mode
Xml, the generator outputs Xml data that includes the information the generator has inferred by processing the output from ClangSharp. As such the Xml data can be seen as an intermediate step to producing C# P/Invoke bindings for the C/C++ input.This PR includes C# DTO-classes that can be used to deserialize the output generated by the ClangSharp P/Invoke generator. This is useful for tools down the line that want to create different code to the C# code generated by ClangSharp, e.g. in order to introduce some case-specific knowledge into the code generator that a general-purpose tool like the ClangSharp P/Invoke generator cannot have.
This PR is currently in draft-state to provide an example for a general for-or-against discussion originally posed by issue #550.
There are several aspects that should be adressed code-wise specifically in this PR:
Where should the serialization classes be located?
ClangSharp.PInvokeGeneratorlibrary and nuget package contains a namespaceXMLwhich is the current location of theXmlOutputBuilderclass, the class that generates the XML output. Placing the serialization classes in the same namespace as the class that actually generates the XML keeps the code in the same place.ClangSharp.PInvokeGeneratorcould be a tool that creates data conforming to that contract whereas other applications could be designed to consume data conforming to that contract (without depending on the generator itself).This PR chose option 1. of the options above for simplicit. Option 2 while having some benefits seems too heavy handed.
Use
System.Xml.SerializationThis PR uses annotations from the
System.Xml.Serializationnamespace.System.Runtime.Serialization.DataContractAttributecould possible be used as an alternative. Since the output mode is XML specific, using the XML-specific serialization technology seems like the better choice.Naming and class design
The classes in this PR are meant to act as DTO-types only, i.e. they only represent the data exacly as emitted in the generated XML. For that purpose I simply added the round-tripping code in the Unit test library and tweaked the classes until all Unit tests that involve XML generation passed with a round-trippable output.
However, naming things is hard, and I tried to follow naming inspired by the type names passed as input to the various methods on
XmlOutputBuilder(FieldDescis one example leading to the nameFieldDescElementfor the type representing the<field>element in the output XML). Some of the methods onXmlOutputBuilderare a little more complex however and create multiple elements as part of their implementation, which is why some classes don't have a corresponding type in theAbstractionsnamespace.We should have a discussion on what a reasonable naming scheme should be here and make the serialization classes be named consistently. One possiblity could be to just simply make the types be named by their XML-element name (e.g.
ConstantElementfor the<constant>tag).I have also introduced some hierarchical structure to the types and created common base types in an attempt to de-duplicate some aspects of the generated XML (e.g.
NamedAccessDescElementwhich describes an Element with anameandaccessattribute).In order to guarantee round-trippable XML in the unit tests the serialization types needed to structure some properties in a way that guarateed identical ordering of XML elements (e.g. in the
NamespaceElementclass). Obviously fields in structs, v-tables and interfaces need to preserve ordering, but in other situations the ordering from the XML output is probably not required.The
<value>and<code>elementsA tricky part in the serialization classes are the
<value>and<code>elements in the XML output. Currently, this PR exposes this by simply having aList<XmlNode>property on theCSharpCodeElementclass which may not be ideal. Given that the generator code emits these elements with mixed XML Text and element contents we should discuss the level of detail that should be represented in the serialization types and how to best expose this. Especially code related to bitfields contains a lot of extra elements that might occur as descandants to<code>.Should
XmlOutputBuilderre-use the serialization classes to generate XML?Currently the ClangSharp P/Invoke generator uses a simple
StringBuilderapproach to generate the XML output. The generated output contains no XML namespaces and the generated XML is fairly simple. However, once you have serialization types available that other applications make use of, there is the question of how to enforce that the serialization types match the generated output produced by the generator? Sure, the Unit tests do help in that regard, but an argument can be made that theXmlOutputBuildershould re-use the serialization types to procude the XML. That way it would become very unlikely that theXmlOutputBuildergenerates something that is not losslessly deserializable with the serialization types.