mirror of
https://github.com/ZuneDev/ZuneUIXTools.git
synced 2026-07-27 13:11:59 -07:00
119 lines
3.3 KiB
C#
119 lines
3.3 KiB
C#
using Microsoft.CodeAnalysis.Text;
|
|
using Microsoft.Iris.Debug.Symbols;
|
|
using System;
|
|
using System.Text;
|
|
using System.Xml;
|
|
using System.Xml.Linq;
|
|
|
|
namespace Microsoft.Iris.DecompXml;
|
|
|
|
internal class IrisXmlWriter : IDisposable
|
|
{
|
|
private readonly IrisTextWriter _textWriter;
|
|
private readonly XmlWriter _xmlWriter;
|
|
private readonly XDocument _xDoc;
|
|
private readonly FileDebugSymbols _symbols;
|
|
|
|
public IrisXmlWriter(XDocument xDoc, FileDebugSymbols symbols)
|
|
{
|
|
_xDoc = xDoc;
|
|
_symbols = symbols;
|
|
|
|
_textWriter = new();
|
|
_xmlWriter = XmlWriter.Create(_textWriter, new XmlWriterSettings
|
|
{
|
|
Indent = true,
|
|
NamespaceHandling = NamespaceHandling.OmitDuplicates,
|
|
Encoding = Encoding.UTF8,
|
|
});
|
|
}
|
|
|
|
public void Dispose() => _xmlWriter.Dispose();
|
|
|
|
public string WriteToString()
|
|
{
|
|
Write();
|
|
return _textWriter.ToString();
|
|
}
|
|
|
|
private void Write()
|
|
{
|
|
if (_symbols is null)
|
|
{
|
|
// If we're not generating symbols, there's no reason to
|
|
// use our custom implementation.
|
|
_xDoc.WriteTo(_xmlWriter);
|
|
_xmlWriter.Flush();
|
|
return;
|
|
}
|
|
|
|
_xmlWriter.WriteStartDocument();
|
|
|
|
foreach (var node in _xDoc.Nodes())
|
|
WriteXObject(node);
|
|
|
|
_xmlWriter.WriteEndDocument();
|
|
_xmlWriter.Flush();
|
|
}
|
|
|
|
private void WriteXObject(XObject obj)
|
|
{
|
|
_xmlWriter.Flush();
|
|
var startPos = _textWriter.Position;
|
|
|
|
if (obj is XElement element)
|
|
{
|
|
_xmlWriter.WriteStartElement(element.Name.LocalName, element.Name.NamespaceName);
|
|
|
|
foreach (var attribute in element.Attributes())
|
|
WriteXObject(attribute);
|
|
|
|
foreach (var childNode in element.Nodes())
|
|
WriteXObject(childNode);
|
|
|
|
_xmlWriter.WriteEndElement();
|
|
}
|
|
else if (obj is XIrisScriptContent script)
|
|
{
|
|
foreach (var node in script.Syntax.GetAnnotatedNodes(UIBOffsetAnnotation.Kind))
|
|
{
|
|
var expressionOffset = node.GetOffset();
|
|
if (expressionOffset is null)
|
|
continue;
|
|
|
|
var location = node.GetLocation().GetLineSpan().Span;
|
|
|
|
SourceSpan span = new(
|
|
RoslynToIrisPosition(location.Start, startPos.Line),
|
|
RoslynToIrisPosition(location.End, startPos.Line));
|
|
_symbols.SourceMap[expressionOffset.Value] = span;
|
|
}
|
|
|
|
_xmlWriter.WriteCData(script.Value);
|
|
}
|
|
else if (obj is XCData cdata)
|
|
{
|
|
_xmlWriter.WriteCData(cdata.Value);
|
|
}
|
|
else if (obj is XAttribute attribute)
|
|
{
|
|
_xmlWriter.WriteAttributeString(attribute.Name.LocalName, attribute.Name.NamespaceName, attribute.Value);
|
|
}
|
|
|
|
var offset = obj.GetOffset();
|
|
if (offset is not null)
|
|
{
|
|
_xmlWriter.Flush();
|
|
var endPos = _textWriter.Position;
|
|
|
|
var span = new SourceSpan(startPos, endPos);
|
|
_symbols.SourceMap[offset.Value] = span;
|
|
}
|
|
}
|
|
|
|
private static SourcePosition RoslynToIrisPosition(LinePosition linePosition, int currentLine)
|
|
{
|
|
return new(linePosition.Line + currentLine + 1, linePosition.Character + 1);
|
|
}
|
|
}
|