Created
November 27, 2022 21:00
-
-
Save m-sedl/cfc0dcd919145a5cc3077801d5225e07 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Reflection.Metadata; | |
using System.Text; | |
namespace Foo; | |
class TestSequencePointsIndex | |
{ | |
private readonly Dictionary<string, List<SequencePoint>> _index = new (); | |
public FooClass(params string[] pdbPaths) | |
{ | |
var documentPaths = new Dictionary<Document, string>(); | |
foreach (var pdbPath in pdbPaths) | |
{ | |
IndexPdbFile(pdbPath, documentPaths); | |
} | |
} | |
public List<int> FindOffsets(string sourceFilePath, int startLine, int startColumn) | |
{ | |
if (!_index.ContainsKey(sourceFilePath)) | |
{ | |
return new List<int>(); | |
} | |
var sf = _index[sourceFilePath]; | |
return sf.Where(sp => sp.StartLine == startLine).Select(sp => sp.Offset).ToList(); | |
} | |
private void IndexPdbFile(string pdbPath, Dictionary<Document, string> documentPaths) | |
{ | |
using var fs = new FileStream(pdbPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); | |
using var provider = MetadataReaderProvider.FromPortablePdbStream(fs); | |
var reader = provider.GetMetadataReader(); | |
foreach (var di in reader.MethodDebugInformation) | |
{ | |
var mdi = reader.GetMethodDebugInformation(di); | |
if (mdi.Document.IsNil) continue; | |
var doc = reader.GetDocument(mdi.Document); | |
if (!documentPaths.ContainsKey(doc)) | |
{ | |
var path = ReadDocumentPath(reader, doc); | |
documentPaths[doc] = path; | |
_index[path] = new List<SequencePoint>(); | |
} | |
var notHiddenPoints = mdi.GetSequencePoints().Where(sp => !sp.IsHidden); | |
var sourceFilePath = documentPaths[doc]; | |
_index[sourceFilePath].AddRange(notHiddenPoints); | |
} | |
} | |
private static string ReadDocumentPath(MetadataReader reader, Document doc) | |
{ | |
var blob = reader.GetBlobReader(doc.Name); | |
// Read path separator character | |
var separator = (char)blob.ReadByte(); | |
var sb = new StringBuilder(blob.Length * 2); | |
// Read path segments | |
while (true) | |
{ | |
var bh = blob.ReadBlobHandle(); | |
if (!bh.IsNil) | |
{ | |
var nameBytes = reader.GetBlobBytes(bh); | |
sb.Append(Encoding.UTF8.GetString(nameBytes)); | |
} | |
if (blob.Offset >= blob.Length) break; | |
sb.Append(separator); | |
} | |
return sb.ToString(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment