Files
MicrosoftIris/UIX/Microsoft/Iris/Debug/Symbols/ApplicationDebugSymbols.cs
T

178 lines
5.1 KiB
C#
Raw Normal View History

2025-09-27 02:22:15 -05:00
using System;
using System.Collections.Generic;
using System.Diagnostics;
2025-11-27 23:41:04 -06:00
using System.Linq;
2025-11-28 20:27:34 -06:00
using System.Text;
2025-09-27 02:22:15 -05:00
namespace Microsoft.Iris.Debug.Symbols;
2025-11-28 20:27:34 -06:00
[CLSCompliant(false)]
2025-09-27 02:22:15 -05:00
public class ApplicationDebugSymbols
{
public List<FileDebugSymbols> Files { get; set; }
}
2025-11-28 20:27:34 -06:00
[CLSCompliant(false)]
2025-09-27 02:22:15 -05:00
public class FileDebugSymbols
{
2025-11-27 23:41:04 -06:00
private string[] _sourceCodeLines;
public string OriginalFileName { get; set; }
2025-09-27 02:22:15 -05:00
public string CompiledFileName { get; set; }
2025-11-27 23:41:04 -06:00
public string SourceFileName { get; set; }
2025-09-27 02:22:15 -05:00
2025-11-28 18:05:23 -06:00
public SourceMap SourceMap { get; } = new();
2025-11-27 23:41:04 -06:00
2025-11-28 20:27:34 -06:00
public string GetSourceSubstring(SourceSpan span)
{
if (!HasSourceCode())
throw new InvalidOperationException($"Must supply source with {nameof(SetSourceCode)}");
span.Start.AsZeroIndexed(out var startLine, out var startColumn);
span.End.AsZeroIndexed(out var endLine, out var endColumn);
StringBuilder sb = new();
2025-11-29 01:27:32 -06:00
for (int currentLineIndex = startLine; currentLineIndex <= endLine; ++currentLineIndex)
2025-11-28 20:27:34 -06:00
{
var line = _sourceCodeLines[currentLineIndex];
Index lineStartIndex = currentLineIndex == startLine
? startColumn
: 0;
Index lineEndIndex = currentLineIndex == endLine
? endColumn
: ^1;
2025-11-29 01:27:32 -06:00
var start = lineStartIndex.GetOffset(line.Length);
var end = lineEndIndex.GetOffset(line.Length);
var length = end - start;
if (length > 0)
sb.AppendLine(line.Substring(start, length));
2025-11-28 20:27:34 -06:00
}
return sb.ToString();
2025-11-27 23:41:04 -06:00
}
public void SetSourceCode(string source)
{
_sourceCodeLines = source.Split('\n')
.Select(s => s.TrimEnd('\r'))
.ToArray();
}
2025-11-28 20:27:34 -06:00
public bool HasSourceCode() => _sourceCodeLines is not null;
2025-11-27 23:41:04 -06:00
}
2025-11-28 20:27:34 -06:00
[CLSCompliant(false)]
2025-11-28 18:05:23 -06:00
public class SourceMap
{
public Dictionary<uint, SourceSpan> Xml { get; } = [];
public Dictionary<uint, Tuple<int, int>> Script { get; } = [];
2025-11-29 01:27:32 -06:00
public (uint Offset, SourceSpan Span)? GetLocationFromPosition(SourcePosition pos)
{
var foundLocation = Xml.FirstOrDefault(kvp =>
{
var offset = kvp.Key;
var span = kvp.Value;
return span.Contains(pos);
});
if (foundLocation.Equals(default(KeyValuePair<uint, SourceSpan>)))
return null;
return (foundLocation.Key, foundLocation.Value);
}
public uint? OffsetByLineAndColumn(int line, int col) => OffsetByLineAndColumn(new(line, col));
public SourceSpan GetContainingSpan(SourcePosition pos) => GetLocationFromPosition(pos)?.Span;
public uint? OffsetByLineAndColumn(SourcePosition pos) => GetLocationFromPosition(pos)?.Offset;
2025-11-28 18:05:23 -06:00
}
2025-11-27 23:41:04 -06:00
[DebuggerDisplay("L{Line}C{Column}")]
public class SourcePosition : IComparable<SourcePosition>, IEquatable<SourcePosition>
{
public int Line { get; }
public int Column { get; }
private ulong Position => ((ulong)Line << (sizeof(uint) * 8)) | (uint)Column;
public SourcePosition(int line, int column)
{
if (line <= 0)
throw new ArgumentOutOfRangeException(nameof(line));
if (column <= 0)
throw new ArgumentOutOfRangeException(nameof(line));
Line = line;
Column = column;
}
2025-11-28 20:27:34 -06:00
public void AsZeroIndexed(out int line, out int column)
{
line = Line - 1;
column = Column - 1;
}
2025-11-27 23:41:04 -06:00
public int CompareTo(SourcePosition other) => Position.CompareTo(other.Position);
public bool Equals(SourcePosition other) => Position == other.Position;
public override bool Equals(object obj)
{
if (obj is not SourcePosition other)
return false;
return Equals(other);
}
public override int GetHashCode()
{
int hashCode = 533871040;
hashCode = hashCode * -1521134295 + Line.GetHashCode();
hashCode = hashCode * -1521134295 + Column.GetHashCode();
hashCode = hashCode * -1521134295 + Position.GetHashCode();
return hashCode;
}
public static bool operator <(SourcePosition left, SourcePosition right) => left.CompareTo(right) < 0;
public static bool operator >(SourcePosition left, SourcePosition right) => left.CompareTo(right) > 0;
public static bool operator <=(SourcePosition left, SourcePosition right) => left.CompareTo(right) <= 0;
public static bool operator >=(SourcePosition left, SourcePosition right) => left.CompareTo(right) >= 0;
public static bool operator ==(SourcePosition left, SourcePosition right) => left.Equals(right);
public static bool operator !=(SourcePosition left, SourcePosition right) => !(left == right);
2025-09-27 02:22:15 -05:00
}
[DebuggerDisplay("[{Start}..{End}]")]
public class SourceSpan
{
2025-11-27 23:41:04 -06:00
public SourceSpan(SourcePosition start, SourcePosition end)
2025-09-27 02:22:15 -05:00
{
if (start > end)
throw new ArgumentException($"Source start index must be at or after end index.");
Start = start;
End = end;
}
2025-11-27 23:41:04 -06:00
public SourcePosition Start { get; }
2025-09-27 02:22:15 -05:00
2025-11-27 23:41:04 -06:00
public SourcePosition End { get; }
2025-09-27 02:22:15 -05:00
2025-11-29 01:27:32 -06:00
public bool Contains(SourcePosition pos) => Start <= pos && pos < End;
2025-09-27 02:22:15 -05:00
}