Skip to content

Commit

Permalink
Reference new debugger bits and implement SourceLinkService to call i…
Browse files Browse the repository at this point in the history
…nto debugger services
  • Loading branch information
davidwengier committed Dec 1, 2021
1 parent f17419c commit 0d6eb3e
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 2 deletions.
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
<MicrosoftVisualStudioCompositionVersion>16.9.20</MicrosoftVisualStudioCompositionVersion>
<MicrosoftVisualStudioCoreUtilityVersion>$(VisualStudioEditorNewPackagesVersion)</MicrosoftVisualStudioCoreUtilityVersion>
<MicrosoftVisualStudioDebuggerUIInterfacesVersion>17.2.0-beta.21477.1</MicrosoftVisualStudioDebuggerUIInterfacesVersion>
<MicrosoftVisualStudioDebuggerContractsVersion>17.2.0-beta.21477.1</MicrosoftVisualStudioDebuggerContractsVersion>
<MicrosoftVisualStudioDebuggerContractsVersion>17.2.0-beta.21580.1</MicrosoftVisualStudioDebuggerContractsVersion>
<MicrosoftVisualStudioDebuggerEngineimplementationVersion>17.0.1042805-preview</MicrosoftVisualStudioDebuggerEngineimplementationVersion>
<MicrosoftVisualStudioDebuggerMetadataimplementationVersion>17.0.1042805-preview</MicrosoftVisualStudioDebuggerMetadataimplementationVersion>
<MicrosoftVisualStudioDesignerInterfacesVersion>$(MicrosoftVisualStudioShellPackagesVersion)</MicrosoftVisualStudioDesignerInterfacesVersion>
Expand Down
97 changes: 97 additions & 0 deletions src/EditorFeatures/Core/PdbSourceDocument/SourceLinkService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// 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;
using System.Composition;
using System.IO;
using System.Reflection.PortableExecutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.PdbSourceDocument;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.VisualStudio.Debugger.Contracts.SourceLink;
using Microsoft.VisualStudio.Debugger.Contracts.SymbolLocator;

namespace Microsoft.CodeAnalysis.Editor.PdbSourceDocument
{
[Export(typeof(ISourceLinkService)), Shared]
internal class SourceLinkService : ISourceLinkService
{
private readonly IDebuggerSymbolLocatorService _debuggerSymbolLocatorService;
private readonly IDebuggerSourceLinkService _debuggerSourceLinkService;

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public SourceLinkService(IDebuggerSymbolLocatorService debuggerSymbolLocatorService, IDebuggerSourceLinkService debuggerSourceLinkService)
{
_debuggerSymbolLocatorService = debuggerSymbolLocatorService;
_debuggerSourceLinkService = debuggerSourceLinkService;
}

public async Task<PdbFilePathResult?> GetPdbFilePathAsync(string dllPath, PEReader peReader, IPdbSourceDocumentLogger? logger, 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 = SymbolLocatorSearchFlags.ForceMsftSymbolServer | SymbolLocatorSearchFlags.ForceNuGetSymbolServer;
var result = await _debuggerSymbolLocatorService.LocateSymbolFileAsync(pdbInfo, flags, progress: null, cancellationToken).ConfigureAwait(false);

// TODO: Logging: https://github.com/dotnet/roslyn/issues/57352
if (result.Found && result.SymbolFilePath is not null)
{
return new PdbFilePathResult(
result.SymbolFilePath,
result.Status,
result.Log,
result.IsPortablePdb);
}

return null;
}

public async Task<SourceFilePathResult?> GetSourceFilePathAsync(string url, string relativePath, IPdbSourceDocumentLogger? logger, CancellationToken cancellationToken)
{
var result = await _debuggerSourceLinkService.GetSourceLinkAsync(url, relativePath, allowInteractiveLogin: false, cancellationToken).ConfigureAwait(false);

// TODO: Logging: https://github.com/dotnet/roslyn/issues/57352
if (result.Status == SourceLinkResultStatus.Succeeded && result.Path is not null)
{
return new SourceFilePathResult(
result.Path,
result.Log);
}

return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public bool TryNavigateToSymbol(ISymbol symbol, Project project, OptionSet? opti

// Generate new source or retrieve existing source for the symbol in question
var allowDecompilation = _globalOptions.GetOption(FeatureOnOffOptions.NavigateToDecompiledSources);
var result = _metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, signaturesOnly: false, allowDecompilation, cancellationToken).WaitAndGetResult(cancellationToken);
var result = ThreadingContext.JoinableTaskFactory.Run(() => _metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, signaturesOnly: false, allowDecompilation, cancellationToken));

var vsRunningDocumentTable4 = IServiceProviderExtensions.GetService<SVsRunningDocumentTable, IVsRunningDocumentTable4>(_serviceProvider);
var fileAlreadyOpen = vsRunningDocumentTable4.IsMonikerValid(result.FilePath);
Expand Down

0 comments on commit 0d6eb3e

Please sign in to comment.