| File: Compiler\SourceLinkWriter.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.IO; using System.Text; using Microsoft.SourceLink.Tools; using ILCompiler.DependencyAnalysis; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; using ObjectData = ILCompiler.DependencyAnalysis.ObjectNode.ObjectData; namespace ILCompiler { public class SourceLinkWriter : ObjectDumper { private readonly TextWriter _writer; private readonly HashSet<string> _generatedSourceMappings; private readonly Dictionary<EcmaModule, SourceLinkMap> _sourceLinkMaps; public SourceLinkWriter(string sourceLinkFileName) { _writer = File.CreateText(sourceLinkFileName); _generatedSourceMappings = new HashSet<string>(StringComparer.OrdinalIgnoreCase); _sourceLinkMaps = new Dictionary<EcmaModule, SourceLinkMap>(); } internal override void Begin() { _writer.Write("{\"documents\":{"); } protected override void DumpObjectNode(NodeFactory factory, ObjectNode node, ObjectData objectData) { if (node is not INodeWithDebugInfo debugInfoNode || node is not IMethodBodyNode methodBodyNode || methodBodyNode.Method.GetTypicalMethodDefinition() is not EcmaMethod ecmaMethod) { return; } if (!_sourceLinkMaps.TryGetValue(ecmaMethod.Module, out SourceLinkMap map)) { ReadOnlySpan<byte> sourceLinkBytes = ecmaMethod.Module.PdbReader is PdbSymbolReader reader ? reader.GetSourceLinkData() : default; string sourceLinkData = sourceLinkBytes.IsEmpty ? "{\"documents\":{}}" : Encoding.UTF8.GetString(sourceLinkBytes); _sourceLinkMaps.Add(ecmaMethod.Module, map = SourceLinkMap.Parse(sourceLinkData)); } if (map.Entries.Count == 0) { return; } foreach (NativeSequencePoint sequencePoint in debugInfoNode.GetNativeSequencePoints()) { if (_generatedSourceMappings.Contains(sequencePoint.FileName)) continue; if (!map.TryGetUri(sequencePoint.FileName, out string uri)) continue; if (_generatedSourceMappings.Count != 0) _writer.Write(", "); _writer.Write($"\"{JsonEscape(sequencePoint.FileName)}\": \"{JsonEscape(uri)}\""); _generatedSourceMappings.Add(sequencePoint.FileName); } static string JsonEscape(string str) => str.Replace(@"\", @"\\").Replace("\"", "\\\""); } internal override void End() { _writer.WriteLine("}}"); _writer.Dispose(); } } }