Skip to content

Commit

Permalink
Merge pull request #74862 from dibarbet/fix_mas_pdb
Browse files Browse the repository at this point in the history
Fix error closing source link documents in VSCode
  • Loading branch information
dibarbet authored Aug 22, 2024
2 parents d908128 + 75a501c commit 854d84d
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ protected static async Task GenerateFileAndVerifyAsync(

var masWorkspace = service.TryGetWorkspace();

using var fileStream = File.OpenRead(file.FilePath);
var sourceText = SourceText.From(fileStream);
var text = SourceText.From(File.ReadAllText(file.FilePath));

var pdbService = (PdbSourceDocumentMetadataAsSourceFileProvider)workspace.ExportProvider.GetExportedValues<IMetadataAsSourceFileProvider>().Single(s => s is PdbSourceDocumentMetadataAsSourceFileProvider);

var documentInfo = pdbService.GetTestAccessor().Documents[file.FilePath];
masWorkspace!.OnDocumentAdded(documentInfo.DocumentInfo);
var document = masWorkspace!.CurrentSolution.Projects.First().Documents.First(d => d.FilePath == file.FilePath);

// Mapping the project from the generated document should map back to the original project
Expand Down Expand Up @@ -330,4 +338,15 @@ protected static string GetPdbPath(string path)
{
return Path.Combine(path, "reference.pdb");
}

private class StaticSourceTextContainer(SourceText sourceText) : SourceTextContainer
{
public override SourceText CurrentText => sourceText;

public override event EventHandler<TextChangeEventArgs> TextChanged
{
add { }
remove { }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,15 +244,19 @@ internal sealed class PdbSourceDocumentMetadataAsSourceFileProvider(
return null;

var symbolId = SymbolKey.Create(symbol, cancellationToken);
var navigateProject = metadataWorkspace.CurrentSolution.GetRequiredProject(projectId);

var documentInfos = CreateDocumentInfos(sourceFileInfos, encoding, navigateProject.Id, sourceWorkspace, sourceProject);
// Get a view of the solution with the document added, but do not actually update the workspace.
// TryAddDocumentToWorkspace is responsible for actually updating the solution with the new document(s).
// We just need a view with the document added so we can find the right location in the generated source.
var pendingSolution = metadataWorkspace.CurrentSolution;
var documentInfos = CreateDocumentInfos(sourceFileInfos, encoding, projectId, sourceWorkspace, sourceProject);
if (documentInfos.Length > 0)
{
metadataWorkspace.OnDocumentsAdded(documentInfos);
navigateProject = metadataWorkspace.CurrentSolution.GetRequiredProject(projectId);
pendingSolution = pendingSolution.AddDocuments(documentInfos);
}

var navigateProject = pendingSolution.GetRequiredProject(projectId);

// If MetadataAsSourceHelpers.GetLocationInGeneratedSourceAsync can't find the actual document to navigate to, it will fall back
// to the document passed in, which we just use the first document for.
// TODO: Support results from multiple source files: https://github.com/dotnet/roslyn/issues/55834
Expand Down Expand Up @@ -319,20 +323,22 @@ private ImmutableArray<DocumentInfo> CreateDocumentInfos(
}

// If a document has multiple symbols then we might already know about it
if (_fileToDocumentInfoMap.ContainsKey(info.FilePath))
if (_fileToDocumentInfoMap.TryGetValue(info.FilePath, out var sourceDocumentInfo))
{
documents.Add(sourceDocumentInfo.DocumentInfo);
continue;
}

var documentId = DocumentId.CreateNewId(projectId);

documents.Add(DocumentInfo.Create(
var documentInfo = DocumentInfo.Create(
documentId,
name: Path.GetFileName(info.FilePath),
loader: info.Loader,
filePath: info.FilePath,
isGenerated: true)
.WithDesignTimeOnly(true));
.WithDesignTimeOnly(true);
documents.Add(documentInfo);

// If we successfully got something from SourceLink for this project then its nice to wait a bit longer
// if the user performs subsequent navigation
Expand All @@ -342,7 +348,7 @@ private ImmutableArray<DocumentInfo> CreateDocumentInfos(
}

// In order to open documents in VS we need to understand the link from temp file to document and its encoding etc.
_fileToDocumentInfoMap[info.FilePath] = new(documentId, encoding, info.ChecksumAlgorithm, sourceProject.Id, sourceWorkspace);
_fileToDocumentInfoMap[info.FilePath] = new(documentId, encoding, info.ChecksumAlgorithm, sourceProject.Id, sourceWorkspace, documentInfo);
}

return documents.ToImmutableAndClear();
Expand All @@ -359,6 +365,7 @@ public bool TryAddDocumentToWorkspace(MetadataAsSourceWorkspace workspace, strin
{
if (_fileToDocumentInfoMap.TryGetValue(filePath, out var info))
{
workspace.OnDocumentAdded(info.DocumentInfo);
workspace.OnDocumentOpened(info.DocumentId, sourceTextContainer);
documentId = info.DocumentId;
return true;
Expand All @@ -376,6 +383,7 @@ public bool TryRemoveDocumentFromWorkspace(MetadataAsSourceWorkspace workspace,
if (_fileToDocumentInfoMap.TryGetValue(filePath, out var info))
{
workspace.OnDocumentClosed(info.DocumentId, new WorkspaceFileTextLoader(workspace.Services.SolutionServices, filePath, info.Encoding));
workspace.OnDocumentRemoved(info.DocumentId);
return true;
}

Expand Down Expand Up @@ -421,8 +429,25 @@ public void CleanupGeneratedFiles(MetadataAsSourceWorkspace workspace)
_sourceLinkEnabledProjects.Clear();
_implementationAssemblyLookupService.Clear();
}

internal TestAccessor GetTestAccessor()
{
return new TestAccessor(this);
}

internal readonly struct TestAccessor
{
private readonly PdbSourceDocumentMetadataAsSourceFileProvider _instance;

internal TestAccessor(PdbSourceDocumentMetadataAsSourceFileProvider instance)
{
_instance = instance;
}

public ImmutableDictionary<string, SourceDocumentInfo> Documents => _instance._fileToDocumentInfoMap.ToImmutableDictionary();
}
}

internal sealed record SourceDocument(string FilePath, SourceHashAlgorithm ChecksumAlgorithm, ImmutableArray<byte> Checksum, byte[]? EmbeddedTextBytes, string? SourceLinkUrl);

internal record struct SourceDocumentInfo(DocumentId DocumentId, Encoding Encoding, SourceHashAlgorithm ChecksumAlgorithm, ProjectId SourceProjectId, Workspace SourceWorkspace);
internal record struct SourceDocumentInfo(DocumentId DocumentId, Encoding Encoding, SourceHashAlgorithm ChecksumAlgorithm, ProjectId SourceProjectId, Workspace SourceWorkspace, DocumentInfo DocumentInfo);

0 comments on commit 854d84d

Please sign in to comment.