/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/VisualStudio/Core/Def/PdbSourceDocument/AbstractSourceLinkService.cs
104 строки
4 KB
David Barbet
Add support in DevKit for source link go to definition
02 авг 2024, 03:49
02 авг 2024, 03:49
2378964
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.IO; using System.Reflection.PortableExecutable; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.PdbSourceDocument; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.VisualStudio.Debugger.Contracts.SourceLink; using Microsoft.VisualStudio.Debugger.Contracts.SymbolLocator; namespace Microsoft.VisualStudio.LanguageServices.PdbSourceDocument; internal abstract class AbstractSourceLinkService : ISourceLinkService { public async Task<PdbFilePathResult?> GetPdbFilePathAsync(string dllPath, PEReader peReader, bool useDefaultSymbolServers, CancellationToken cancellationToken) { var hasCodeViewEntry = false; uint timeStamp = 0; CodeViewDebugDirectoryData codeViewEntry = default; using var _ = ArrayBuilder<PdbChecksum>.GetInstance(out var checksums); foreach (var entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.PdbChecksum) { var checksum = peReader.ReadPdbChecksumDebugDirectoryData(entry); checksums.Add(new PdbChecksum(checksum.AlgorithmName, checksum.Checksum)); } else if (entry.Type == DebugDirectoryEntryType.CodeView && entry.IsPortableCodeView) { hasCodeViewEntry = true; timeStamp = entry.Stamp; codeViewEntry = peReader.ReadCodeViewDebugDirectoryData(entry); } } if (!hasCodeViewEntry) return null; var pdbInfo = new SymbolLocatorPdbInfo( Path.GetFileName(codeViewEntry.Path), codeViewEntry.Guid, (uint)codeViewEntry.Age, timeStamp, checksums.ToImmutable(), dllPath, codeViewEntry.Path); var flags = useDefaultSymbolServers ? SymbolLocatorSearchFlags.ForceNuGetSymbolServer | SymbolLocatorSearchFlags.ForceMsftSymbolServer : SymbolLocatorSearchFlags.None; var result = await LocateSymbolFileAsync(pdbInfo, flags, cancellationToken).ConfigureAwait(false); if (result is null) { Logger?.Log($"{nameof(LocateSymbolFileAsync)} returned null"); return null; } if (result.Value.Found && result.Value.SymbolFilePath is not null) { return new PdbFilePathResult(result.Value.SymbolFilePath); } else if (Logger is not null) { // We log specific info from the debugger if there is a failure, but the caller will log general failure // information otherwise Logger.Log(result.Value.Status); Logger.Log(result.Value.Log); } return null; } public async Task<SourceFilePathResult?> GetSourceFilePathAsync(string url, string relativePath, CancellationToken cancellationToken) { var result = await GetSourceLinkAsync(url, relativePath, cancellationToken).ConfigureAwait(false); if (result is null) { Logger?.Log($"{nameof(GetSourceLinkAsync)} returned null"); return null; } if (result.Value.Status == SourceLinkResultStatus.Succeeded && result.Value.Path is not null) { return new SourceFilePathResult(result.Value.Path); } else if (Logger is not null && result.Value.Log is not null) { // We log specific info from the debugger if there is a failure, but the caller will log general failure // information otherwise. Logger.Log(result.Value.Log); } return null; } protected abstract Task<SymbolLocatorResult?> LocateSymbolFileAsync(SymbolLocatorPdbInfo pdbInfo, SymbolLocatorSearchFlags flags, CancellationToken cancellationToken); protected abstract Task<SourceLinkResult?> GetSourceLinkAsync(string url, string relativePath, CancellationToken cancellationToken); protected abstract IPdbSourceDocumentLogger? Logger { get; } }