Skip to content

Commit

Permalink
Query IDocumentTrackingService for active document when we are not
Browse files Browse the repository at this point in the history
passed a project context in an LSP request.
  • Loading branch information
dibarbet committed Jun 25, 2021
1 parent 87675a2 commit 41734a7
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 23 deletions.
29 changes: 21 additions & 8 deletions src/Features/LanguageServer/Protocol/Extensions/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,30 @@ public static T FindDocumentInProjectContext<T>(this ImmutableArray<T> documents
if (documents.Length > 1)
{
// We have more than one document; try to find the one that matches the right context
if (documentIdentifier is VSTextDocumentIdentifier vsDocumentIdentifier)
if (documentIdentifier is VSTextDocumentIdentifier vsDocumentIdentifier && vsDocumentIdentifier.ProjectContext != null)
{
if (vsDocumentIdentifier.ProjectContext != null)
var projectId = ProtocolConversions.ProjectContextToProjectId(vsDocumentIdentifier.ProjectContext);
var matchingDocument = documents.FirstOrDefault(d => d.Project.Id == projectId);

if (matchingDocument != null)
{
var projectId = ProtocolConversions.ProjectContextToProjectId(vsDocumentIdentifier.ProjectContext);
var matchingDocument = documents.FirstOrDefault(d => d.Project.Id == projectId);
return matchingDocument;
}
}
else
{
// We were not passed a project context. This can happen when the LSP powered NavBar is not enabled.
// This branch should be removed when we're using the LSP based navbar in all scenarios.

// Lookup the active document and determine if any of the documents from the request URI match.
var solution = documents.First().Project.Solution;
var service = solution.Workspace.Services.GetRequiredService<IDocumentTrackingService>();

if (matchingDocument != null)
{
return matchingDocument;
}
var activeDocument = service.GetActiveDocument(solution);
var matchingDocument = documents.FirstOrDefault(d => d.Id == activeDocument?.Id);
if (matchingDocument != null)
{
return matchingDocument;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Test;
using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Text;
Expand All @@ -33,7 +35,7 @@ public async Task TestNoDocumentDiagnosticsForClosedFilesWithFSAOff()

var document = testLspServer.GetCurrentSolution().Projects.Single().Documents.Single();

var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document);
var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI());

Assert.Empty(results);
}
Expand All @@ -53,7 +55,7 @@ public async Task TestDocumentDiagnosticsForOpenFilesWithFSAOff()
await OpenDocumentAsync(testLspServer, document);

var results = await RunGetDocumentPullDiagnosticsAsync(
testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single());
testLspServer, document.GetURI());

Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code);
}
Expand All @@ -72,7 +74,7 @@ public async Task TestNoDocumentDiagnosticsForOpenFilesWithFSAOffIfInPushMode()

await OpenDocumentAsync(testLspServer, document);

var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document);
var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI());

Assert.Empty(results.Single().Diagnostics);
}
Expand All @@ -98,7 +100,7 @@ public async Task TestDocumentDiagnosticsForRemovedDocument()
await WaitForDiagnosticsAsync(workspace);
var results = await testLspServer.ExecuteRequestAsync<DocumentDiagnosticsParams, DiagnosticReport[]>(
MSLSPMethods.DocumentPullDiagnosticName,
CreateDocumentDiagnosticParams(document),
CreateDocumentDiagnosticParams(document.GetURI()),
new LSP.ClientCapabilities(),
clientName: null,
CancellationToken.None);
Expand Down Expand Up @@ -136,13 +138,13 @@ public async Task TestNoChangeIfDocumentDiagnosticsCalledTwice()

await OpenDocumentAsync(testLspServer, document);

var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document);
var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI());

Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code);

var resultId = results.Single().ResultId;
results = await RunGetDocumentPullDiagnosticsAsync(
testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single(), previousResultId: resultId);
testLspServer, document.GetURI(), previousResultId: resultId);

Assert.Null(results.Single().Diagnostics);
Assert.Equal(resultId, results.Single().ResultId);
Expand All @@ -162,13 +164,13 @@ public async Task TestDocumentDiagnosticsRemovedAfterErrorIsFixed()

await OpenDocumentAsync(testLspServer, document);

var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document);
var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI());

Assert.Equal("CS1513", results[0].Diagnostics.Single().Code);

await InsertTextAsync(testLspServer, document, buffer.CurrentSnapshot.Length, "}");

results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single());
results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI());

Assert.Empty(results[0].Diagnostics);
}
Expand All @@ -186,7 +188,7 @@ public async Task TestDocumentDiagnosticsRemainAfterErrorIsNotFixed()
var document = testLspServer.GetCurrentSolution().Projects.Single().Documents.Single();

await OpenDocumentAsync(testLspServer, document);
var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document);
var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI());

Assert.Equal("CS1513", results[0].Diagnostics.Single().Code);
Assert.Equal(new Position { Line = 0, Character = 9 }, results[0].Diagnostics.Single().Range.Start);
Expand All @@ -195,7 +197,7 @@ public async Task TestDocumentDiagnosticsRemainAfterErrorIsNotFixed()
await InsertTextAsync(testLspServer, document, position: 0, text: " ");

results = await RunGetDocumentPullDiagnosticsAsync(
testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single(),
testLspServer, document.GetURI(),
previousResultId: results[0].ResultId);

Assert.Equal("CS1513", results[0].Diagnostics.Single().Code);
Expand Down Expand Up @@ -233,12 +235,56 @@ public async Task TestStreamingDocumentDiagnostics()
await OpenDocumentAsync(testLspServer, document);

var progress = BufferedProgress.Create<DiagnosticReport>(null);
var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single(), progress: progress);
var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI(), progress: progress);

Assert.Null(results);
Assert.Equal("CS1513", progress.GetValues()!.Single().Diagnostics.Single().Code);
}

[Fact]
public async Task TestDocumentDiagnosticsForOpenFilesUsesActiveContext()
{
var documentText =
@"#if ONE
class A {
#endif
class B {";
var workspaceXml =
@$"<Workspace>
<Project Language=""C#"" CommonReferences=""true"" AssemblyName=""CSProj1"" PreprocessorSymbols=""ONE"">
<Document FilePath=""C:\C.cs"">{documentText}</Document>
</Project>
<Project Language=""C#"" CommonReferences=""true"" AssemblyName=""CSProj2"">
<Document IsLinkFile=""true"" LinkFilePath=""C:\C.cs"" LinkAssemblyName=""CSProj1"">{documentText}</Document>
</Project>
</Workspace>";

using var testLspServer = CreateTestWorkspaceFromXml(workspaceXml, BackgroundAnalysisScope.OpenFilesAndProjects);

var csproj1Document = testLspServer.GetCurrentSolution().Projects.Where(p => p.Name == "CSProj1").Single().Documents.First();
var csproj2Document = testLspServer.GetCurrentSolution().Projects.Where(p => p.Name == "CSProj2").Single().Documents.First();

// Open either of the documents, LSP is just tracking the URI and text.
await OpenDocumentAsync(testLspServer, csproj1Document);

// Set the active context to be document from CSProj2
var documentTrackingService = (TestDocumentTrackingService)testLspServer.TestWorkspace.Services.GetRequiredService<IDocumentTrackingService>();
documentTrackingService.SetActiveDocument(csproj2Document.Id);

var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, csproj2Document.GetURI());
Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code);
var vsDiagnostic = (LSP.VSDiagnostic)results.Single().Diagnostics.Single();
Assert.Equal("CSProj2", vsDiagnostic.Projects.Single().ProjectName);

// Set the active context to be document from CSProj1
documentTrackingService.SetActiveDocument(csproj1Document.Id);

results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, csproj1Document.GetURI());
Assert.Equal(2, results.Single().Diagnostics!.Length);
Assert.All(results.Single().Diagnostics, d => Assert.Equal("CS1513", d.Code));
Assert.All(results.Single().Diagnostics, d => Assert.Equal("CSProj1", ((VSDiagnostic)d).Projects.Single().ProjectName));
}

#endregion

#region Workspace Diagnostics
Expand Down Expand Up @@ -439,15 +485,15 @@ public async Task TestStreamingWorkspaceDiagnostics()

private static async Task<DiagnosticReport[]> RunGetDocumentPullDiagnosticsAsync(
TestLspServer testLspServer,
Document document,
Uri uri,
string? previousResultId = null,
IProgress<DiagnosticReport[]>? progress = null)
{
await WaitForDiagnosticsAsync(testLspServer.TestWorkspace);

var result = await testLspServer.ExecuteRequestAsync<DocumentDiagnosticsParams, DiagnosticReport[]>(
MSLSPMethods.DocumentPullDiagnosticName,
CreateDocumentDiagnosticParams(document, previousResultId, progress),
CreateDocumentDiagnosticParams(uri, previousResultId, progress),
new LSP.ClientCapabilities(),
clientName: null,
CancellationToken.None);
Expand Down Expand Up @@ -482,13 +528,13 @@ private static async Task WaitForDiagnosticsAsync(TestWorkspace workspace)
}

private static DocumentDiagnosticsParams CreateDocumentDiagnosticParams(
Document document,
Uri uri,
string? previousResultId = null,
IProgress<DiagnosticReport[]>? progress = null)
{
return new DocumentDiagnosticsParams
{
TextDocument = ProtocolConversions.DocumentToTextDocumentIdentifier(document),
TextDocument = new LSP.TextDocumentIdentifier { Uri = uri },
PreviousResultId = previousResultId,
PartialResultToken = progress,
};
Expand All @@ -512,6 +558,13 @@ private TestLspServer CreateTestWorkspaceWithDiagnostics(string markup, Backgrou
return testLspServer;
}

private TestLspServer CreateTestWorkspaceFromXml(string xmlMarkup, BackgroundAnalysisScope scope, bool pullDiagnostics = true)
{
var testLspServer = CreateXmlTestLspServer(xmlMarkup, out _);
InitializeDiagnostics(scope, testLspServer.TestWorkspace, pullDiagnostics);
return testLspServer;
}

private TestLspServer CreateTestWorkspaceWithDiagnostics(string[] markups, BackgroundAnalysisScope scope, bool pullDiagnostics = true)
{
var testLspServer = CreateTestLspServer(markups, out _);
Expand Down

0 comments on commit 41734a7

Please sign in to comment.